9

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

一个玩具例子:

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 的调用中,商家是 nil,尽管它似乎不应该是。

4

3 回答 3

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)

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

于 2012-07-16T14:50:14.107 回答
0

我在 Rails 2.3 上,我可以确认

product = merchant.products.build

不会在 after_initialize 回调中返回正确的商家 ID 关联

但我发现它可以正常工作

product = merchant.products.new

我认为它已通过此提交修复(不过我真的不知道,我并不十分熟悉 git 工作流程):

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

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

于 2013-03-14T17:31:08.870 回答
0

您可能会寻找inverse_of

has_many :products, inverse_of: :merchant
于 2016-05-17T23:03:43.000 回答