我有一个模型Foo
has_many'Bar'。我为每个对象都有一个factory_girl工厂。 Bar的工厂与Foo有关联;它会在创建Bar时实例化Foo。
我想要一个创建包含Bar的Foo的Factory。理想情况下,这个Bar将通过:bar工厂创建,并尊重用于创建Foo的构建策略(创建/构建)。
我知道我可以调用:bar工厂,然后从新的Bar中获取Foo引用。我想避免这种情况;在我的测试用例中,重要的对象是Foo;称酒吧工厂似乎有点迂回曲折。此外,我可以看到需要一个具有多个条形的Foo。
这可能在factory_girl吗?你如何在父母中定义这种关系?
答案 0 :(得分:50)
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
如果使用after_build
构建策略,则documentation表示after_create
将在:create
之前调用。如果使用:build
,则只会调用after_build
,并且每个人都很满意。
我还创建了一个抽象的通用版本at this gist来保持干净。
答案 1 :(得分:4)
您可以双向使用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
答案 2 :(得分:3)
FactoryGirl现在有一个:method => :build
选项,您可以在关联上使用它,它将构建关联对象而不是创建它。
答案 3 :(得分:3)
FactoryGirl 4.3.0在父对象上调用save!
时正在关联上调用build
,我认为这不是正确的行为。
在挖掘FactoryGirl代码后,将strategy: :build
添加到工厂中的关联定义似乎现在正在创建我的关联而不调用save!
。
答案 4 :(得分:2)
使用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