2010-10-26 8 views
18

Ich verwende Factory Girl/Rspec2/Rails 3.Factory Girl: Wie verknüpfe ich einen Datensatz mit einem anderen Datensatz, ohne einen neuen Datensatz zu erstellen?

In factories.rb, ich habe:

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 

und dann in meinem rspec Test habe ich:

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 

Wenn ich den Test starte, bekomme ich:

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

Ich verstehe den Grund für den Fehler, weil FactoryGirl eine andere Organisation (mit dem gleichen Namen) erstellt.

Aber was ich tun möchte, ist mehrere Mitgliedschaften alle mit der gleichen Organisation verbunden zu schaffen. Wie mache ich das?

Danke.

Sean

Antwort

18

Sie könnten für eine bestehende Organisation überprüfen und es verwenden, oder erstellen, wenn keine vorhanden ist:

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

factory 4+ Update:

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

Ein weiterer Ansatz ist eindeutige Kennungen verwendet werden (zB : Namen) für jede Fabrik, die Sie wiederverwenden möchten, dann initialize_with zu generieren verwenden:

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

Nun wird jeder Verweis auf :organization_1 immer denselben Organization abrufen. Natürlich müssen Sie verschiedene Namen verwenden, damit dies funktioniert.

+0

Danke Zeteic. Ich habe das benutzt. Es funktioniert für jetzt. (Wenn es mehr als eine Org gibt, muss ich wohl eine andere Lösung finden ... ein anderes Problem für einen anderen Tag. " –

4

Es gibt zwei Dinge. 1. Sie möchten vielleicht immer noch eindeutige Namen für Factory(:organisation) erstellen, die Sie erreichen können, indem Sie Factory.sequence verwenden, die es nur für Sie generiert. 2. Sie können eine Factory(:membership_request, :organization => @organization) übergeben, um das vorhandene Objekt zu verwenden, anstatt ein neues zu erstellen.

+0

Dank Kunday. Ich habe das auch benutzt .. es scheint so, als ob ich mehr als alles andere im rspec Test definieren muss anstatt in factories.rb. Ich muss Fabriken immer noch verstehen und sie auf einer höheren Ebene anwenden. Ich kann nur einen von euch korrekt markieren, obwohl ich beide Vorschläge benutzt habe. –

+0

Kühle Sean. Nach dem, was ich in den letzten Monaten mit factory_girl festgestellt habe, sind mehr als 50% der Tests von einigen expliziten Daten aus dem rspec-Test abhängig. Aber angesichts der Menge an Daten, die Sie nicht tun, wenn Ihr Modell komplex wird, ist es immer noch in Ordnung, denke ich. Schön zu hören, dass es geklappt hat. – Kunday

2

Mit mongoid Sie nehmen die Verwendung des #find_or_create_by Methode mit Factory.attributes_for und tun so etwas wie dieses

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

kombinieren kann ich bin sicher, dass Active etwas ähnlich.

Verwandte Themen