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. In both cases, they let a test create an object by expressing concepts (similar to a trait), without knowing anything about the implementation. These two examples are easy to understand, without knowing any object internals:
FactoryBot.create(:car, make: 'Saturn', accident_count: 3)
FactoryBot.create(:car, make: 'Toyota', unsold: true)
These two examples use transients for in distinct ways:
- Controlling/altering the creation of related objects (e.g. accident_count).
- Altering values assigned to other attribute assignments (e.g. unsold).
Inside the factory, those two transients are used like this:
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
The two attributes in the create
call (accident_count
and unsold
) are not part of the model and are not explicitly saved...but both have effects on the resulting objected created for the test. That is the essential distinction of a transient, vs a trait or explicit attribute value.
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.
transient
. Do you have a factory that usestransient
that you want to understand? – Agamemnon