Заводы Singleton в factory_girl/машинисте?

Есть ли какая-то конфигурация в factory девушки/машиниста factory, которая заставляет его создавать объекты с тем же именем factory только один раз во время тестового случая и все время возвращать один и тот же экземпляр? Я знаю, я могу сделать что-то вроде:

def singleton name
    @@singletons ||= {}
    @@singletons[name] ||= Factory name
end
...
Factory.define :my_model do |m|
   m.singleton_model { singleton :singleton_model }
end

но, возможно, есть лучший способ.

Ответ 1

Вы можете использовать макрос initialize_with внутри вашего factory и проверить, существует ли объект, но не создавать его снова. Это также работает, когда упомянутый factory ссылается на ассоциации:

FactoryGirl.define do
  factory :league, :aliases => [:euro_cup] do
    id 1
    name "European Championship"
    owner "UEFA"
    initialize_with { League.find_or_create_by_id(id)}
  end
end

Здесь есть аналогичный вопрос с большим количеством альтернатив: Использование factory_girl в Rails с ассоциациями, которые имеют уникальные ограничения. Получение повторяющихся ошибок

Ответ 2

Не уверен, что это может быть полезно для вас.

С помощью этой установки вы можете создать n продуктов с помощью factory 'singleton_product'. Все эти продукты будут иметь одну и ту же платформу (например, платформу FooBar).

factory :platform do
  name 'Test Platform'
end

factory :product do
  name 'Test Product'
  platform

  trait :singleton do
    platform{
      search = Platform.find_by_name('FooBar')
      if search.blank?
        FactoryGirl.create(:platform, :name => 'FooBar')
      else
        search
      end
    }
  end

  factory :singleton_product, :traits => [:singleton]
end

Вы можете использовать стандартный продукт factory "продукт" для создания продукта с платформой "Test Platform", но он будет терпеть неудачу, когда вы вызываете его для создания второго продукта (если имя платформы задано как уникальное).

Ответ 3

@CubaLibre ответ с версией 5 FactoryBot:

FactoryGirl.define do
  factory :league do
    initialize_with { League.find_or_initialize_by(id: id) }
    sequence(:id)
    name "European Championship"
  end
end