1
0
Fork 0
mirror of https://github.com/thoughtbot/factory_bot.git synced 2022-11-09 11:43:51 -05:00
thoughtbot--factory_bot/lib/factory_bot/enum.rb
Daniel Colson 975fc4ff29
Add functionality for enum traits (#1380)
## Enum traits

Given a Rails model with an enum attribute:

```rb
class Task < ActiveRecord::Base
  enum status: {queued: 0, started: 1, finished: 2}
end
```

It is common for people to define traits for each possible value of the enum:

```rb
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
```

With this commit, those trait definitions are no longer necessary—they are defined automatically by factory_bot.

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` (see commit:  [Allow opting out of automatically defining traits](5a20017351)).

In that case, it is still possible to explicitly define traits for an enum attribute in a particular factory:

```rb
FactoryBot.automatically_define_enum_traits = false

FactoryBot.define do
  factory :task do
    traits_for_enum(:status)
  end
end
```

It is also possible to use this feature for other enumerable values, not specifically tied to ActiveRecord enum attributes:

```rb
class Task
  attr_accessor :status
end

FactoryBot.define do
  factory :task do
    traits_for_enum(:status, ["queued", "started", "finished"])
  end
end
```

The second argument here can be an enumerable object, including a Hash or Array.

Closes #1049 

Co-authored-by: Lance Johnson <lancejjohnson@gmail.com>
Co-authored-by: PoTa <pota@mosfet.hu>
Co-authored-by: Frida Casas <fridacasas.fc@gmail.com>
Co-authored-by: Daniel Colson <danieljamescolson@gmail.com>
2020-05-01 17:50:51 -04:00

27 lines
608 B
Ruby

module FactoryBot
# @api private
class Enum
def initialize(attribute_name, values = nil)
@attribute_name = attribute_name
@values = values
end
def build_traits(klass)
enum_values(klass).map do |trait_name, value|
build_trait(trait_name, @attribute_name, value || trait_name)
end
end
private
def enum_values(klass)
@values || klass.send(@attribute_name.to_s.pluralize)
end
def build_trait(trait_name, attribute_name, value)
Trait.new(trait_name) do
add_attribute(attribute_name) { value }
end
end
end
end