2015-12-01 21 views
6

Mam dość grubą cechę Factory Girl, która akceptuje parametry i tworzy zależność has_many. Mogę nazwać tę cechę jako część innej cechy, aby wysuszyć cechy lub ułatwić łączenie cech w czasie przekazywania ich do fabryk. To, czego nie wiem, jak to zrobić, to przekazać paramy do cechy, gdy nazywam ją inną cechą lub zamiast tego zrobić.Zadzwoń do cech innej cechy z parametrami w factory_girl

np.

FactoryGirl.define do 
    factory :currency do 
    name Forgery::Currency.description 
    sequence(:short_name) { |sn| "#{Forgery::Currency.code}#{sn}" } 
    symbol '$' 
    end 

    factory :price do 
    full_price { 6000 } 
    discount_price { 3000 } 
    currency 
    subscription 
    end 

    sequence(:base_name) { |sn| "subscription_#{sn}" } 

    factory :product do 
    name { generate(:base_name) } 
    type { "reading" } 
    duration { 14 } 


    trait :reading do 
     type { "reading subscription" } 
    end 

    trait :maths do 
     type { "maths subscription" } 
    end 

    trait :six_month do 
     name { "six_month_" + generate(:base_name) } 
     duration { 183 } 
    end 

    trait :twelve_month do 
     name { "twelve_month_" + generate(:base_name) } 
     duration { 365 } 
    end 

    factory :six_month_reading, traits: [:six_month, :reading] 
    factory :twelve_month_reading, traits: [:twelve_month, :reading] 

    trait :with_price do 
     transient do 
     full_price 6000 
     discount_price 3000 
     short_name 'AUD' 
     end 

     after(:create) do |product, evaluator| 
     currency = Currency.find_by(short_name: evaluator.short_name) || 
        create(:currency, short_name: evaluator.short_name) 
     create_list(
      :price, 
      1, 
      product: product, 
      currency: currency, 
      full_price: evaluator.full_price, 
      discount_price: evaluator.discount_price 
     ) 
     end 
    end 

    trait :with_aud_price do 
     with_price 
    end 

    trait :with_usd_price do 
     with_price short_name: 'USD' 
    end 
    end 
end 

create(:product, :with_aud_price) # works 
create(:product, :with_usd_price) # fails "NoMethodError: undefined method `with_price=' for #<Subscription:0x007f9b4f3abf50>" 

# What I really want to do 
factory :postage, parent: :product do 
    with_aud_price full_price: 795 
    with_usd_price full_price 700 
end 

Odpowiedz

6

:with_price cecha musi być w osobnej linii od innych atrybutów jesteś ustawień, to znaczy zamiast:

trait :with_usd_price do 
    with_price short_name: 'USD' 
end 

Użyj tego:

trait :with_usd_price do 
    with_price 
    short_name: 'USD' 
end 
+0

Nie bardzo rozumiem, dlaczego to działa, ale bardzo się cieszę, że tak. – jim

+0

Wydaje się, że pod maską nazywającą cechę A w obrębie cechy B cecha B jest podklasą cech A. Co oznaczałoby, że obsługuje ona wiele dziedziczenia i kto wie, co się stanie, jeśli obie cechy definiują te same właściwości przejściowe itd. Itd. domyślam się, że pierwszy lub ostatni zwany po prostu ma pierwszeństwo. Wydaje się nieco zaskakujące zdefiniowanie dziedziczenia jak wywołanie metody, a nie coś podobnego do składni 'parent:: foo' używanej w fabrykach. – jim

+0

Ok. Spojrzałem na to dalej, jest to dobre, o ile idzie, ale nadal nie mogę zrobić przykładu na samym dole próbki kodu w OP. Jeśli spróbuję w tej formie, otrzymam 'FactoryGirl :: AttributeDefinitionError: Attribute już zdefiniowany: full_price'. Hmm ... Być może będę w stanie pracować z tablicami dla właściwości przejściowych. – jim

0

I m na factory_bot 4.8.2 i działa następująco:

trait :with_usd_price do 
    with_price 
    short_name 'USD' 
end