9

1対多の関連付けを持つ2つのモデルがあります。親の状態に基づいて、初期化時に子モデルにデフォルト値を設定したいと考えています。これには、belongs_to アソシエーションを介して親にアクセスする必要がある子で after_initialize コールバックを発生させることが含まれます。問題は、build メソッドを使用して子をインスタンス化すると、after_initialize コールバックで親への関連付けが nil になることです。これは予想される動作ですか?私はレール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 の呼び出しでは、merchant は 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

私はレール2.3を使用しており、次のことを確認できます。

product = merchant.products.build

after_initializeコールバックで正しいmerchant_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 に答える