2012-06-02 44 views
8

我有两个模型与一对多关联。我想根据父项的某些状态在初始化时在子模型上设置默认值。这涉及到需要通过belongs_to关联访问父对象的child的after_initialize回调触发器。问题是,当我使用构建方法实例化子对象时,与父对象的关联在after_initialize回调中为零。这是预期的行为?我在轨道3.0.6Rails协会在after_initialize无

,一种玩具,例如:

class Merchant < ActiveRecord::Base 
    has_many :products 
end 

class Product < ActiveRecord::Base 
    belongs_to :merchant 

    after_initialize :set_default_value 

    def set_default_value 
     if merchant.state 
      self.foo = some_value 
     else 
      self.foo = some_other_value 
     end 
    end 
end 

而在一个控制器:

product = merchant.products.build 

在调用set_default_value,商户零,虽然它似乎不该不会的。

+1

具有原始商户实例被保存呢,你叫商人了。 products.build? – Pasted

+0

是的,商家将是一个现有的记录在分贝,所以它会有一个有效的ID。 – Dino

+1

我几乎完全按照你的想法试过它,它对我很有用。唯一的区别是'class Products'应该是'class Product'而不是's'。 –

回答

1

如下我会改变代码:

class Product < ActiveRecord::Base 
    ... 
    def set_default_value(state = merchant.state) 
    if state 
     self.foo = some_value 
    else 
     self.foo = some_other_value 
    end 
    end 
end 

然后改变你的来电者:

product = merchant.products.build(:state => merchant.state) 

而且,我发现after_initialize回调是缓慢的。因此,另一种选择是将逻辑转移到产品的构建器中。

product = merchant.products.build(:foo => merchant.state ? some_value : some_other_value) 

这也消除得墨忒耳定律违反从代码(即产品不应该知道/关心商户的状态是什么)。

0

我在轨道上2.3,我可以证实,

product = merchant.products.build 

在after_initialize回调将不会返回正确的MERCHANT_ID协会

,但我发现,它会与

正常工作
product = merchant.products.new 

我认为它是用这个提交修复的(我真的不知道,但我并不真正熟悉git工作流程):

https://github.com/rails/rails/issues/1842

因为在轨3.1.11它同时适用于buildnew

0

你可能找inverse_of

has_many :products, inverse_of: :merchant