我有一个模型,比方说Cat
,我想创建一个新模型Owner
。 Cat
has_one :owner
,但是当我创建Cat
模型时,Owner
模型尚不存在。
不依靠为每个Owner
回填新的Cat
模型,我希望有一个简单的方法,所以如果我致电@cat.owner.something
,@cat.owner
不存在然而,它会动态调用@cat.create_owner
并将其返回。
我已经看到这样做了几种不同的方式,但我想知道什么是最常用的Rails解决方法,因为我需要经常这样做。
答案 0 :(得分:3)
我之前没有看到过这个,但还是决定尝试一下。
我首先在owner
模型中对关联方法Cat
进行了别名,以保留原始方法的备份。如果原始方法返回nil,我会覆盖owner
方法以调用build_owner
方法(通过关联返回新的Owner
对象)。否则,返回original_owner_method
对象。
class Cat < ActiveRecord::Base
has_one :owner
alias :original_owner_method :owner
def owner
if original_owner_method.nil?
build_owner
else
original_owner_method
end
end
现在如果你打电话:
cat = Cat.first
假设它没有所有者,它将在您调用时构建一个新的Owner对象:
cat.owner.name
它将返回nil,但仍然在链的cat.owner
部分构建所有者对象,而不调用method_missing。
答案 1 :(得分:1)
我不会在第一次访问时创建所有者,而是使用回调来创建所有者。这可以确保所有者永远不会为零,如果回调失败,它将自动回滚Cat创建。
class Cat < ActiveRecord::Base
before_create :create_owner
private
def create_owner
return true unless owner.nil?
create_owner(:default => 'stuff')
end
end
更新:虽然我仍然会为新应用程序推荐上述方法,但由于您已有现有记录,因此可能需要更多类似的内容:
class Cat < ActiveRecord::Base
def owner
super || create_owner(:default => 'stuff')
end
end
答案 2 :(得分:1)
对于这类问题的一般方法,我认为这是最“红宝石”
def owner
@owner ||= create_owner
end
在rails中,我会采取类似这样的方式
def owner
@owner ||= Owner.find_or_create(cat: self)
end
但总的来说,我会尝试找出一种方法来使用Cat#create_owner或Owner#create_cat,如果可以的话,尽量避免整个问题。
答案 3 :(得分:0)
根据我的经验,覆盖来自.directive("colorTag", function(){
return {
restrict: "A",
scope: {
value: "=colorTag"
},
link: function (scope, element, attrs) {
var colors = new App.Colors();
element.css("background-color", stringToColor(scope.value));
element.css("color", contrastColor(scope.value));
// Destroy scope, because it's no longer needed.
scope.$destroy();
}
};
})
的默认属性getter / setter是一种危险的做法 - 有龙。我将通过示例解释哪个让我失望。
我使用this answer中建议的ActiveRecord::Base
模式。你最终可能会遇到像这样的棘手问题:
super || create_association
我错误地期望Rails魔术用它新创建的From: /Users/mec/Sites/zipmark/service/spec/models/vendor_application_spec.rb @ line 39 :
34: subject.read_attribute(:ledger_id).should be_blank
35: end
36:
37: it "lazily creates the association" do
38: subject.ledger
=> 39: binding.pry
40: subject.reload.ledger_id.should be_present
41: end
42: end
43: end
44:
[1] pry(#<RSpec::Core::ExampleGroup>)> subject.ledger
#<Ledger:0x007fc3c30ad398> {
:id => "cf0ac70e-ce23-4648-bf3f-85f56fdb123a",
:created_at => Wed, 30 Sep 2015 17:56:18 UTC +00:00,
:updated_at => Wed, 30 Sep 2015 17:56:18 UTC +00:00,
:description => "Freshbooks Ledger"
}
[2] pry(#<RSpec::Core::ExampleGroup>)> subject.reload.ledger_id
nil
记录来更新手头的记录(self
)。我最终将重载的ledger
方法重写为以下内容:
#ledger