I have a fairly chunky FactoryBot trait that accepts params and creates a has_many relation. I can call that trait as part of another trait to dry up traits or make it easier to bundles traits together when passing them to factories. What I don't know how to do is how to pass params to a trait when I'm calling it from another trait, or what to do instead.
e.g.
FactoryBot.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
parent: :foo
syntax used for factories. – Selfassurance