FactoryBot 工厂中“transient do”块的用途是什么?

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

FactoryBot 工厂中 transient do 的用途是什么?

我见过很多以下面这样开头的工厂。

factory :car do
  owner nil
  other_attribute nil
end
...

我在这个博客上找到了一些信息:
Using FactoryGirl to easily create complex data sets in Rails

但我仍然不完全理解如何以及为什么要这样做。我对 FactoryBot 的经验很少。

有使用 FactoryBot 经验的人可以分享一些见解吗?

transient 属性允许您传入 不是模型属性 的数据。

假设您有一个名为 car 的模型,它具有以下属性:

  • 名字
  • purchase_price
  • 型号

您想在工厂创建汽车模型时将汽车名称大写。我们能做的是:

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

因此,每当您创建汽车工厂并希望将名称大写时。你可以做到

car = FactoryGirl.create(:car, capitalize: true)
car.name
# => "JACKY"

希望对您有所帮助。

瞬态属性本质上是工厂的局部变量,不会保留到创建的对象中。

我见过瞬态属性的两个主要用途:

  • Controlling/altering创建相关对象(例如accident_count)。
  • 更改分配给其他属性分配的值(例如未售出)。

当然,您可以将这些临时属性用于在对象创建期间需要编码的任何其他内容。

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

这让您的测试可以表达一个概念(类似于特征),而无需对实现一无所知:

FactoryBot.create(:car, make: 'Saturn', accident_count: 3)
FactoryBot.create(:car, make: 'Toyota', unsold: true)

IMO,当它们起作用时,我会坚持使用特征(例如,未售出,上图)。但是当你需要传递一个非模型值时(例如 accident_count),瞬态属性是可行的方法。