2012-10-24 15 views
6

Sto cercando di capire come scrivere una factory che appartiene a 2 modelli diversi, ognuno dei quali dovrebbe avere lo stesso modello padre. Ecco il codice di esempio artificiosa:Associazione FactoryGirl con più modelli

class User < ActiveRecord::Base 
    has_many :widgets 
    has_many :suppliers 

    attr_accessible :username 
end 

class Widget < ActiveRecord::Base 
    belongs_to :user 
    has_many :parts 

    attr_accessible :name 
end 

class Supplier < ActiveRecord::Base 
    belongs_to :user 
    has_many :parts 

    attr_accessible :name 
end 

class Part < ActiveRecord::Base 
    belongs_to :supplier 
    belongs_to :widget 

    attr_accessible :name 
end 

Ecco quello che ho finora:

factory :user do 
    name 'foo' 
end 

factory :widget do 
    association :user 
    name 'widget' 
end 

factory :supplier do 
    association :user 
    name 'supplier' 
end 

factory :part do 
    association :widget 
    association :supplier 
    name 'part' 
end 

Il problema di questo è che il part.widget.user != part.supplier.user e devono essere gli stessi.

Ho provato la seguente senza successo:

factory :part do 
    association :widget 
    association :supplier, user: widget.user 
    name 'part' 
end 

Qualche suggerimento? O devo modificarlo dopo aver creato la parte?

Grazie

risposta

7

credo che si possa fare questo con un callback:

factory :part do 
    association :widget 
    association :supplier 
    name 'part' 
    after(:create) do |part| 
    user = FactoryGirl.create(:user) 
    part.widget.user = part.supplier.user = user 
    end 
end 

Vedi anche: Get two associations within a Factory to share another association

+0

Grazie mille. Ho finito per usare 'after (: build)' e 'part.widget.user = part.supplier.user' in questo modo non sto creando 3 utenti :) –

+0

Oh fantastico che ha funzionato! Non ero abbastanza sicuro che lo sarebbe. Mi sembra comunque che ci debba essere un modo più pulito per farlo. –

+0

Questo è quello che ho pensato anch'io, ma 'associazione: fornitore, utente: widget.user' non funziona potrebbe essere qualcosa da cercare per una patch –

0

Un'altra opzione è quella di utilizzare le variabili transitorie per consentire un oggetto associato per essere passato poll.

Generalmente utilizzo due variabili:

  • una variabile per contenere l'associazione da utilizzare all'interno della fabbrica
  • una variabile booleana per indicare se o non generare un valore di default per la variabile associazione - probabilmente non necessario nel tuo caso specifico, ma possono essere molto utile

Questo è come dovrebbe apparire:

factory :part do 
    transient do 
    # this variable is so we can specify the user 
    with_user { no_user ? nil : Factory.create(:user) } 

    # this variable allows the user to be nil 
    no_user false 
    end 

    # The transient variable for_user can now be used to create the 
    # associations for this factory 
    widget { Factory.create(:widget, :user => with_user) } 
    supplier { Factory.create(:supplier, :user => with_user) } 

    name 'part' 
end 

Questo può quindi essere utilizzata nei seguenti modi:

# use the default user 
part = Factory.create :part 
part.widget.user.should == part.supplier.user 

# use a custom created user 
user = Factory.create :user, :name => 'Custom user' 
part = Factory.create :part, for_user: user 
part.widget.user.should == user 
part.supplier.user.should == user 

# create a part without any user 
# (again this probably isn't need in your specific case, but I have 
# found it a useful pattern) 
part = Factory.create :part, no_user: true 
part.widget.user.should be_nil 
part.supplier.user.should be_nil 
Problemi correlati