2014-04-21 17 views
5

Ho molti modelli che possono essere creati (avere un campo autore) e/o tenancyable (avere un campo tenant). Quindi, ho scritto preoccupazioni per entrambi.Condivisione di tratti tra diversi factory

Il problema è nei test. Avevo utilizzato il blocco shared_examples_for per scrivere test per i dubbi e includerli nei test del mio modello. In ogni caso, per fare questo, ho diversi tratti e dopo i blocchi, per esempio:

after(:build) do |authorable| 
    authorable.author = build(:user, tenant: authorable.tenant) 
end 

trait :no_author do 
    after(:build) do |authorable| 
    authorable.author = nil 
    end 
end 

trait :no_tenant do 
    tenant nil 
end 

Questo pezzo di codice dovrebbe essere uguale nelle fabbriche di tutti i modelli che sono tenancyable e authorable.

Non ho trovato alcun modo per farlo. È possibile?

risposta

4

Tratti possono essere registrati a livello globale, in modo che possano essere utilizzati in qualsiasi altra fabbrica senza usare l'ereditarietà di factorygirl:

FactoryGirl.define do 
    trait :no_author do 
    after(:build) { |authorable| authorable.author = nil } 
    end 

    trait :no_tenant do 
    tenant nil 
    end 

    factory :model do 
    tenant { build(:tenant) } 
    end 
end 

Si può poi semplicemente costruire oggetti come questo:

FactoryGirl.build(:model, :no_tenant) 
FactoryGirl.build(:model, :no_author) 

after le callback possono anche essere registrate globalmente, ma ciò significherebbe che sono attivate per qualsiasi oggetto creato da FactoryGirl, il che può causare effetti collaterali indesiderati:

FactoryGirl.define do 
    after(:build) do |authorable| 
    authorable.author = build(:user, tenant: authorable.tenant) 
    end 

    factory :model do 
    tenant { build(:tenant) } 
    end 

    factory :other_model 
end 

FactoryGirl.build(:model)  # Happiness! 
FactoryGirl.build(:other_model) # undefined method `tenant' 

Per evitare questo, è possibile avvolgere il callback in un tratto, come avete fatto nel :no_author tratto, oppure è possibile utilizzare fabbrica eredità:

FactoryGirl.define do 
    factory :tenancyable do 
    trait :no_tenant do 
     tenant nil 
    end 

    factory :authorable do 
     after(:build) do |authorable| 
     authorable.author = build(:user, tenant: authorable.tenant) 
     end 

     trait :no_author do 
     after(:build) do |authorable| 
      authorable.author = nil 
     end 
     end 
    end 
    end 

    factory :model, parent: :authorable, class: 'Model' do 
    tenant { build(:tenant) } 
    end 

    factory :other_model 
end 

nota come la classe per i model esigenze di fabbrica per essere esplicitamente specificato qui per far funzionare questo. Ora puoi creare oggetti:

FactoryGirl.build(:model, :no_author) # Happiness! 
FactoryGirl.build(:other_model)  # More Happiness! 

Con il secondo approccio, i tratti e le callback sono più contenuti. Questo può effettivamente causare sorprese meno indesiderate quando si dispone di un grande numero di codice con molte fabbriche.

Problemi correlati