Enum traits
Given an Active Record model with an enum attribute:
class Task < ActiveRecord::Base
enum status: {queued: 0, started: 1, finished: 2}
end
factory_bot will automatically define traits for each possible value of the enum:
FactoryBot.define do
factory :task
end
FactoryBot.build(:task, :queued)
FactoryBot.build(:task, :started)
FactoryBot.build(:task, :finished)
Writing the traits out manually would be cumbersome, and is not necessary:
FactoryBot.define do
factory :task do
trait :queued do
status { :queued }
end
trait :started do
status { :started }
end
trait :finished do
status { :finished }
end
end
end
If automatically defining traits for enum attributes on every factory is not
desired, it is possible to disable the feature by setting
FactoryBot.automatically_define_enum_traits = false
In that case, it is still possible to explicitly define traits for an enum attribute in a particular factory:
FactoryBot.automatically_define_enum_traits = false
FactoryBot.define do
factory :task do
traits_for_enum(:status)
end
end
To override the global setting for a single factory, pass the
automatically_define_enum_traits option. Child factories, whether nested or
declared with parent:, use their parent's setting unless they set their own.
FactoryBot.define do
factory :task, automatically_define_enum_traits: false do
status { :queued }
trait :in_progress do
status { :started }
end
trait :complete do
status { :finished }
end
end
end
Here only the :in_progress and :complete traits exist. Building with
:queued, :started, or :finished raises a KeyError. The option accepts
true or false.
It is also possible to use this feature for other enumerable values, not specifically tied to Active Record enum attributes.
With an array:
class Task
attr_accessor :status
end
FactoryBot.define do
factory :task do
traits_for_enum(:status, ["queued", "started", "finished"])
end
end
Or with a hash:
class Task
attr_accessor :status
end
FactoryBot.define do
factory :task do
traits_for_enum(:status, { queued: 0, started: 1, finished: 2 })
end
end