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?
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.
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
FactoryGirl now has a :method => :build
option you can use on the association, which will build the associated object rather than creating it.
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!
.
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