42

我有一个Foohas_many 'Bar' 的模型。我为这些对象中的每一个都有一个 factory_girl 工厂。Bar 的工厂与 Foo 有关联;它会在创建 Bar 时实例化一个 Foo。

我想要一个创建包含 Bar 的 Foo 的工厂。理想情况下,此 Bar 将通过 :bar 工厂创建,并尊重用于创建 Foo 的构建策略(创建/构建)。

我知道我可以调用 :bar 工厂,然后从新 Bar 中获取 Foo 引用。我想避免这种情况;在我的测试用例中,重要的对象是 Foo;调用酒吧工厂似乎有点迂回。此外,我可以看到需要具有多个 Bar 的 Foo。

这可能在 factory_girl 中吗?您如何在父级中定义这种关系?

4

5 回答 5

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将在之前调用。如果被使用,那么只有被调用,并且每个人都很高兴。after_create:create:buildafter_build

我还在这个要点上创建了一个抽象的普遍适用的版本,以保持干燥。

于 2010-06-13T18:45:54.700 回答
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
于 2010-05-30T19:52:53.060 回答
3

FactoryGirl 4.3.0在调用父对象save!时调用关联build,我认为这不是正确的行为。

在挖掘 FactoryGirl 代码之后,添加strategy: :build到工厂中的关联定义现在似乎正在创建我的关联而不调用save!.

于 2013-12-29T08:16:55.410 回答
3

FactoryGirl 现在有一个:method => :build您可以在关联上使用的选项,它将构建关联的对象而不是创建它。

#64:构建对象会产生关联

于 2011-11-12T14:44:20.547 回答
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
于 2015-04-15T13:29:33.900 回答