2010-05-30 73 views
40

我有一個模型Foo has_many'酒吧'。我爲每個這些對象都有一個factory_girl工廠。 Bar的工廠與Foo有聯繫;它會在創建Bar時實例化一個Foo。在factory_girl填充與兒童的關聯

我想創建一個包含一個條的Foo的工廠。理想情況下,這個Bar將通過:bar工廠創建,並且尊重用於創建Foo的構建策略(創建/構建)。

我知道我可以打電話給:bar工廠,然後從新的Bar中獲取Foo引用。我想避免這種情況;在我的測試案例中,重要的對象是Foo;稱酒吧工廠似乎有點迂迴。另外,我可以看到需要一個帶有多個酒吧的Foo。

這是可能的factory_girl?你如何在家長中定義這種關係?

回答

48

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_buildafter_create之前如果使用:create構造策略被調用。如果使用:build,那麼只有after_build被調用,並且每個人都很高興。

我還創建了一個抽象通用版本at this gist以保持乾燥。

+2

完美 - 一直在撕掉我的頭髮。謝謝! – recurser 2012-02-24 06:10:47

+2

很難相信這是做到這一點的最佳方式,但它似乎仍然是如此。贊成這個答案。 – spier 2013-08-02 09:34:26

+0

你如何使用你的主要版本?將其整合到Rails應用程序中的最佳方式是什麼? – 2013-12-07 06:37:44

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 
+1

第一語法導致我的代碼堆棧溢出/無限遞歸n個子對象。 第二種語法奇妙地工作,除了它不服從構建策略。 – 2010-06-13 18:30:53

3

FactoryGirl 4.3.0被父對象,我相信這是並非是正確的行爲上呼籲build當關聯調用save!

在挖掘FactoryGirl代碼後,將strategy: :build添加到工廠中的關聯定義中似乎現在正在創建我的關聯,而不會調用save!

2

使用factory_girl-4.5.0,創建一個父對象工廠

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

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