问题
What is the purpose of transient do
in FactoryBot factories?
I've seen a lot of factories that begin with something like below.
factory :car do
owner nil
other_attribute nil
end
...
I've found some information on this blog: http://blog.thefrontiergroup.com.au/2014/12/using-factorygirl-easily-create-complex-data-sets-rails/
But I still don't fully understand how and why to do this. My experience with FactoryBot is minimal.
Could anyone with some experience using FactoryBot share some insight?
回答1:
transient
attributes allow you to pass in data that isn’t an attribute on the model.
Say you have a model called car
with the following attributes:
- name
- purchase_price
- model
You want to capitalize the name of the car when you create the car model in the factory. What we can do is:
factory :car do
transient do
# capitalize is not an attribute of the car
capitalize false
end
name { "Jacky" }
purchase_price { 1000 }
model { "Honda" }
after(:create) do |car, evaluator|
car.name.upcase! if evaluator.capitalize
end
end
Hence, whenever you create the car factory and you want to capitalize the name. You can do
car = FactoryGirl.create(:car, capitalize: true)
car.name
# => "JACKY"
Hope it helps.
回答2:
Transient attributes are essentially variables local to the factory that do not persist into the created object.
I have seen two main uses of transient attributes:
- Controlling/altering the creation of related objects (e.g. accident_count).
- Altering values assigned to other attribute assignments (e.g. unsold).
You could, of course, use these transient attributes for anything else you need to code during the object creation.
factory :car do
transient do
accident_count 0
unsold false
end
owner unsold ? 'new inventory' : nil
after(:create) do |car, evaluator|
create_list(:police_report, evaluator.accident_count, vehicle: car)
end
end
This lets your test express a concept (similar to a trait), without knowing anything about the implementation:
FactoryBot.create(:car, make: 'Saturn', accident_count: 3)
FactoryBot.create(:car, make: 'Toyota', unsold: true)
IMO, I would stick with traits when they work (e.g. unsold, above). But when you need to pass a non-model value (e.g. accident_count), transient attributes are the way to go.
来源:https://stackoverflow.com/questions/38573131/what-is-the-purpose-of-a-transient-do-block-in-factorybot-factories