2010-10-26 57 views
18

我使用工廠女孩/ Rspec2/Rails的3工廠女孩:如何將記錄與另一條記錄關聯而不創建新記錄?

factories.rb,我有:

Factory.define :user do |user| 
    user.name  'Some guy' 
    user.email  '[email protected]' 
    user.password 'password' 
end 

Factory.define :org_admin, :parent => :user do |user| 
    user.email '[email protected]' 
end 

Factory.define :user_with_membership_request, :parent => :user do |user| 
    user.email '[email protected]' 
end 

Factory.define :organization do |org| 
    org.name  'MEC' 
    org.description 'Mountain Equipment Co-op' 
end 

Factory.define :membership do |membership| 
    membership.user { Factory(:user) } 
    membership.organization { Factory(:organization) } 
end 

Factory.define :admin_membership, :parent => :membership do |membership| 
    membership.user { Factory(:org_admin) } 
    membership.is_admin true 
    membership.status 'active' 
end 

Factory.define :membership_request, :parent => :membership do |membership| 
    membership.user { Factory(:user_with_membership_request) } 
    membership.status 'requested' 
end 

,然後在我的RSpec的測試我有:

it 'should accept the membership request' do 
    @org_admin = Factory(:org_admin) 
    test_sign_in(@org_admin) 
    @organization = Factory(:organization) 
    @membership_request = Factory(:membership_request) 

    put :update, :organization_id => @organization.id, :id => @membership_request.id, :acceptance => 'approve' 
    ... 
    end 

當我運行測試時,我得到:

Failure/Error: @membership_request = Factory(:membership_request) 
Validation failed: Name has already been taken 

我明白失敗的原因是因爲FactoryGirl正在創建另一個組織(具有相同的名稱)。

但我想要做的是創建與同一組織關聯的多個成員。我怎麼做?

謝謝。

肖恩

回答

18

你可以檢查現有的組織和使用它,或者如果沒有創建一個:

Factory.define :membership do |membership| 
    membership.user { Factory(:user) } 
    membership.organization { Organization.first || Factory(:organization) } 
end 

FactoryGirl 4+更新:

Factory.define do 
    factory :membership do 
    user { create(:user) } 
    organization { Organization.first || create(:organization) } 
    end 
end 

另一種方法是使用唯一標識符(如:名稱),然後用initialize_with生成它:

factory :organization_1 do 
    ignore { organization_name 'Sample Organization 1' } 
    name { organization_name } 
    initialize_with { Organization.find_or_create_by_name(organization_name) } 
end 

現在對:organization_1的任何引用將始終檢索相同的Organization。顯然,你必須使用不同的名稱才能工作。

+0

謝謝Zeteic。我用過這個。它現在工作。 (雖然當有不止一個組織時,我想我需要找到另一個解決方案......另一個問題是另一天「。 – 2010-10-27 20:38:19

4

有兩件事。 1.您可能仍想爲Factory(:organisation)創建唯一名稱,您可以使用Factory.sequence來實現該名稱,這將爲您生成唯一的名稱。 2.您可以傳入Factory(:membership_request, :organization => @organization)以使用現有對象,而不是創建新對象。

+0

謝謝Kunday。我也用過這個..好像我必須在rspec測試中定義比基本更多的東西,而不是在factories.rb中。我仍然需要了解工廠以及如何在更高層次上使用它們。儘管我已經使用了兩個建議,但我只能標記其中一個正確。 – 2010-10-27 20:40:08

+0

酷肖恩。從過去幾個月使用factory_girl注意到的事情來看,超過50%的測試依賴於rspec測試中設置的一些顯式數據。但是,考慮到當你的模型變得複雜時你不會做的數據設置的數量,我仍然可以。很高興聽到你解決它。 – Kunday 2010-10-27 21:15:06

2

隨着mongoid您可以結合使用與Factory.attributes_for的#find_or_create_by方法,做這樣的事情

factory :membership do 
    organization { Organization.find_or_create_by(Factory.attributes_for(:organization))} 
end 

我敢肯定的ActiveRecord有類似的東西。

相關問題