2014-04-21 16 views
5

Mam wiele modeli, które mogą być autoryzowane (mają pole autora) i/lub dostępne do pobrania (mają pole dzierżawy). Napisałem więc obawy dla nich obu.Udostępnianie cech w różnych fabrykach

Problem dotyczy testów. Użyłem bloku shared_examples_for do napisania testów dla problemów i uwzględnienia ich w moich testach modelowych. W każdym razie, aby to zrobić, mam kilka cech i po blokach, na przykład:

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 

Ten kawałek kodu powinien być równy w fabrykach wszystkich modeli, które są tenancyable i authorable.

Nie znalazłem żadnego sposobu, aby to zrobić. Czy to możliwe?

Odpowiedz

4

Cechy mogą być rejestrowane na całym świecie, dzięki czemu można je stosować w każdym innym zakładzie bez użycia FactoryGirl za dziedziczenie:

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 

Następnie można po prostu zbudować obiekty tak:

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

after callbacks mogą być również rejestrowane globalnie, ale to oznacza, że ​​są one uruchamiane dla dowolnego obiektu FactoryGirl tworzy, co może powodować niepożądane efekty uboczne:

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' 

Aby tego uniknąć, można owinąć zwrotnego w cechy, jak to zrobiliśmy w cechy :no_author, lub użyć fabrycznego dziedziczenia:

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 

Zauważ, że klasa dla potrzeb fabryki model należy wyraźnie określić tutaj, aby to działało. Możesz teraz budować obiekty:

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

Przy drugim podejściu cechy i wywołania zwrotne są bardziej ograniczone. Może to w rzeczywistości spowodować mniej niechcianych niespodzianek, gdy masz duży kod z wieloma fabrykami.