What is the purpose of a `transient do` block in FactoryBot factories?

前端 未结 2 1055
-上瘾入骨i
-上瘾入骨i 2021-02-11 12:35

What is the purpose of transient do in FactoryBot factories?

I\'ve seen a lot of factories that begin with something like below.

factory :c         


        
相关标签:
2条回答
  • 2021-02-11 13:02

    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.

    0 讨论(0)
  • 2021-02-11 13:07

    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.

    0 讨论(0)
提交回复
热议问题