web-dev-qa-db-ja.com

factory_girlでの子供との関連付けの設定

Has_many 'Bar'というモデルFooがあります。これらのオブジェクトごとにfactory_girlファクトリがあります。 BarのファクトリーはFooに関連しています。バーを作成するときにFooをインスタンス化します。

バーを含むFooを作成するファクトリーが欲しいのですが。理想的には、このバーは:barファクトリーを通じて作成され、Fooの作成に使用されたビルド戦略(create/build)を尊重します。

:barファクトリーを呼び出して、新しいBarからFoo参照を取得できることはわかっています。これは避けたいです。私のテストケースでは、重要なオブジェクトはFooです。 Barファクトリーを呼び出すことは少し遠回りに思えます。また、複数のバーを持つFooの必要性もわかります。

これはfactory_girlで可能ですか?この関係を親でどのように定義しますか?

42
Craig Walker

Factory.after_ hooksは、これを成功させる唯一の方法のようです。コードを複製せずにビルド戦略を維持する方法を見つけました。

Factory.define :foo do |f|
  f.name "A Foo"
  f.after(:build) { |foo|
    foo.bars << Factory.build(:bar, :foo => foo)
  }
  f.after(:create) { |foo|
    foo.bars.each { |bar| bar.save! }
  }
end

documentation は、after_buildビルド戦略が使用されている場合、after_createの前に:createが呼び出されることを示しています。 :buildを使用すると、after_buildのみが呼び出され、誰もが満足します。

抽象化された一般的に適用可能なバージョン この要点 も作成して、物事を乾いた状態に保ちます。

50
Craig Walker

associationメソッドは両方の方法で使用できます。

Factory.define :foo do |f|
  # ...
  f.association :bar
end

それが機能しない場合は、コールバックを使用して手動で関連付けることができます。これが私のアプリの例です:

Factory.define :live_raid do |raid|
end

Factory.define :live_raid_with_attendee, :parent => :live_raid do |raid|
  raid.after_create { |r| Factory(:live_attendee, :live_raid => r) }
end
4
Robert Speicher

FactoryGirl 4.3.0は、親オブジェクトでbuildを呼び出すときに、関連付けでsave!を呼び出していますが、これは正しい動作を意図したものではないと考えています。

FactoryGirlコードを調べた後、strategy: :buildをファクトリの関連付け定義に追加すると、save!を呼び出さずに関連付けが作成されるようになりました。

3
mgp

FactoryGirlに:method => :buildオプションを関連付けで使用すると、関連付けられたオブジェクトを作成するのではなく作成します。

#64:オブジェクトを作成すると関連付けが作成されます

3
bjnord

factory_girl-4.5.0を使用して、親オブジェクトファクトリにn個の子オブジェクトを作成します

FactoryGirl.define do
  factory :foo do
    name "test"        

    after(:build) do |instance|
      n.times { instance.bars << FactoryGirl.create(:bar) }          
    end
  end
end
2
Epigene