2014-04-21 7 views
5

Ich habe viele Modelle, die authorable (haben ein Autorfeld) und/oder vermietbar sein können (haben Sie ein Mieterfeld). Also habe ich Bedenken für beide geschrieben.Teilen Sie Merkmale über verschiedene Fabriken hinweg

Das Problem besteht in Tests. Ich hatte den shared_examples_for Block benutzt, um Tests für die Interessen zu schreiben und sie in meine Modellversuche einzuschließen. Wie auch immer, dies zu tun, habe ich mehrere Züge und nach Blöcken, zum Beispiel:

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 

Dieses Stück Code sollte in den Fabriken aller Modelle gleich sein, die tenancyable und authorable sind.

Ich habe keine Möglichkeit gefunden, dies zu tun. Ist es möglich?

Antwort

4

Traits kann global registriert werden, so dass sie in einem anderen Werk verwendet werden können, ohne factory der Vererbung:

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 

Sie können Objekte wie diese dann einfach bauen:

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

after Callbacks können auch global registriert werden, aber das würde bedeuten, dass sie für jedes Objekt ausgelöst werden, das FactoryGirl erstellt, was zu unerwünschten Nebenwirkungen führen kann:

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' 

Um dies zu vermeiden, können Sie entweder den Rückruf in einem Zug wickeln, wie Sie in der :no_author Eigenschaft haben, oder können Sie Fabrik Vererbung:

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 

Hinweis, wie die Klasse für die model Fabrik Bedürfnisse explizit hier angegeben werden, um diese Arbeit zu machen. Sie können jetzt Objekte erstellen:

Mit dem zweiten Ansatz sind die Merkmale und Rückrufe mehr enthalten. Dies kann tatsächlich zu weniger unerwünschten Überraschungen führen, wenn Sie eine große Codebase mit vielen Fabriken haben.