我想使用FactoryBot这样随机返回特征:
FactoryBot.define do
factory :user do
[:active, inactive].sample
trait :active do
active { true }
...
end
trait :inactive do
active { false }
...
end
end
end
要这样做:
(1..5).map{ |e| FactoryBot.build(:user) }.map(&:active?)
=> [true, false, false, true, false]
实际上就是这样:
FactoryBot.define do
factory :user do
active { [true, false].Sample }
name { "name-#{SecureRandom.uuid}" }
birthday { active == true ? rand(18..99).years.ago - rand(0..365).days.ago : nil }
preferred_contact_method { active == true ? %w(phone email).sample : nil }
activated_at { active == true ? rand(1..200).days.ago : nil }
contact_phone_number { preferred_contact_method == "phone" ? "+33XXXXXXXXX" : nil }
contact_email { preferred_contact_method == "email" ? "toto@tati.com" : nil }
end
end
有可能这样做吗?
答案 0 :(得分:0)
在研究最终答案时,我遇到了一个事实,即trait
仅在给出块之后才执行。我将暂时分享我正在使用的代码示例,尽管如果您对其进行测试,则将只有活动用户或不活动用户,而不会同时拥有这两个用户。
您可以将特征的逻辑导出为两个lambda,然后随机选择一个:
trait_active = lambda do |context|
context.active { true }
#...
end
trait_inactive = lambda do |context|
context.active { false }
# ...
end
FactoryBot.define do
factory :user do
trait :active do
trait_active.call(self)
end
trait :inactive do
trait_inactive.call(self)
end
trait :schrodinger do
[trait_active, trait_inactive].sample.call(self)
end
end
end
lambda中的context
属性在这里非常重要,您可以了解更多
关于in this answer。
答案 1 :(得分:0)
这是一个很老的问题,但与 OP 有相同的需求,我想我找到了解决方案,可惜它不漂亮:
FactoryBot.define do
factory :user do
active { nil }
initialize_with do
if active.nil?
build :user, %i[active inactive].sample, attributes
else
User.new(attributes)
end
end
trait :active do
active { true }
...
end
trait :inactive do
active { false }
...
end
end
end
FactoryBot.create_list(:user, 5).map(&:active) #=> random array of booleans
FactoryBot.create_list(:user, 5, :active).all?(&:active?) #=> true