Ensure enum traits only get expanded once
Ensure enum traits only get expanded once

Fixes #1411

Before this commit, anybody with Active Record enum attributes using
factory_bot 6.0 would have seen an increase in memory every time they
used any trait.

This behavior can be seen with the following benchmark:

```rb
require "bundler/inline"

gemfile(true) do
  source "https://rubygems.org"
  git_source(:github) { |repo| "https://github.com/#{repo}.git" }
  gem "factory_bot", "~> 6.0.1"
  gem "activerecord"
  gem "sqlite3"
end

require "active_record"
require "factory_bot"
require "logger"

ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Base.logger = Logger.new(STDOUT)

ActiveRecord::Schema.define do
  create_table :posts, force: true do |t|
    t.integer :status
  end
end

class Post < ActiveRecord::Base
  enum status: ("a".."z").to_a
end

FactoryBot.define do
  factory :post do
    trait :x
  end
end

require "benchmark"

TIMES = 50

FactoryBot.build(:post)

Benchmark.bm do |bm|
  bm.report("false, false") do
    FactoryBot.automatically_define_enum_traits = false

    TIMES.times do
      FactoryBot.build(:post)
    end
  end

  bm.report("true, false") do
    FactoryBot.automatically_define_enum_traits = true

    TIMES.times do
      FactoryBot.build(:post)
    end
  end

  bm.report("false, true") do
    FactoryBot.automatically_define_enum_traits = false

    TIMES.times do
      FactoryBot.build(:post, :x)
    end
  end

  bm.report("true, true") do
    FactoryBot.automatically_define_enum_traits = true

    TIMES.times do
      FactoryBot.build(:post, :x)
    end
  end
end
```

The first three cases work as expected, but in the last case, with
` FactoryBot.automatically_define_enum_traits = true` and the `:x` trait
passed in at run time, the behavior before this commit was as follows:

1. When passing in traits, the [factory runner] calls
  [factory.with_traits], which clones the factory and then applies the
  traits to the clone.

2. Cloning the factory also clones the factory's definition
3. The cloned definition retains some of the state of the original
  definition, most notably [`@defined_traits` and
  `@registered_enums`][shared state], but it sets `@compiled` back to false.
4. When the [definition recompiles], it [re-registers enums] into
  `@register_enums`, duplicating what is already there. For each
  registered enum, it [adds the relevant traits] to @defined_traits,
  again duplicating what was already there.
5. This gets worse and worse every time a trait gets used, increasing
 the size of `@defined_traits` exponentially until the program grids
 to a halt.

With this commit, we keep an additional piece of state to ensure we only
register and apply enum traits in the original definition. When any
cloned definitions recompile, they will skip these steps.

[factory runner]: https://github.com/thoughtbot/factory_bot/blob/0785796f0823528fd36d1c3e4a3df4511b9876e4/lib/factory_bot/factory_runner.rb#L16-L18
[factory.with_traits]: https://github.com/thoughtbot/factory_bot/blob/0785796f0823528fd36d1c3e4a3df4511b9876e4/lib/factory_bot/factory.rb#L93-L97
[shared state]: https://github.com/thoughtbot/factory_bot/blob/master/lib/factory_bot/definition.rb#L47-L4://github.com/thoughtbot/factory_bot/blob/0785796f0823528fd36d1c3e4a3df4511b9876e4/lib/factory_bot/definition.rb#L10-L11
[definition recompiles]: https://github.com/thoughtbot/factory_bot/blob/0785796f0823528fd36d1c3e4a3df4511b9876e4/lib/factory_bot/definition.rb#L47-L49
[re-registers enums]: https://github.com/thoughtbot/factory_bot/blob/0785796f0823528fd36d1c3e4a3df4511b9876e4/lib/factory_bot/definition.rb#L146-L148
[adds the relevant traits]: https://github.com/thoughtbot/factory_bot/blob/0785796f0823528fd36d1c3e4a3df4511b9876e4/lib/factory_bot/definition.rb#L150-L153

thoughtbot/factory_girl