问题
I have a model Foo
that has_many 'Bar'. I have a factory_girl factory for each of these objects. The factory for Bar has an association to Foo; it will instantiate a Foo when it creates the Bar.
I'd like a Factory that creates a Foo that contains a Bar. Ideally this Bar would be created through the :bar factory, and respect the build strategy (create/build) used to create the Foo.
I know I could just call the :bar factory and then grab the Foo reference from the new Bar. I'd like to avoid this; in my test case, the important object is Foo; calling the Bar factory seems a bit circuitous. Also, I can see the need for a Foo with multiple Bars.
Is this possible in factory_girl? How do you define this relationship in the parent?
回答1:
The Factory.after_ hooks
appear to be the only way to do this successfully. I've figured out a way to maintain the build strategy without duplicating code:
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
The documentation states that after_build
will be called before after_create
if the :create
build strategy is used. If :build
is used, then only after_build
is called, and everyone is happy.
I've also created an abstracted generally-applicable version at this gist to keep things DRY.
回答2:
You can use the association
method both ways:
Factory.define :foo do |f|
# ...
f.association :bar
end
If that won't work, you can associate them manually using a callback. Here's an example from one of my apps:
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
回答3:
FactoryGirl now has a :method => :build
option you can use on the association, which will build the associated object rather than creating it.
#64: Building an object creates associations
回答4:
FactoryGirl 4.3.0 is calling save!
on an association when calling build
on the parent object, which i believe is not intended to be the correct behavior.
After digging through the FactoryGirl code, adding strategy: :build
to the association definition in the factory seems now be creating my association without calling save!
.
回答5:
Using factory_girl-4.5.0
, create n child objects in a parent object factory
FactoryGirl.define do
factory :foo do
name "test"
after(:build) do |instance|
n.times { instance.bars << FactoryGirl.create(:bar) }
end
end
end
来源:https://stackoverflow.com/questions/2937326/populating-an-association-with-children-in-factory-girl