Этот вопрос является продолжением вопроса, поднятого здесь:
Использование factory_girl в Rails с ассоциациями, которые имеют уникальные ограничения. Получение дубликатов ошибок
Предлагаемый ответ отлично сработал для меня. Вот как это выглядит:
# Creates a class variable for factories that should be only created once.
module FactoryGirl
class Singleton
@@singletons = {}
def self.execute(factory_key)
begin
@@singletons[factory_key] = FactoryGirl.create(factory_key)
rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotUnique
# already in DB so return nil
end
@@singletons[factory_key]
end
end
end
Проблема, которая возникла у меня, заключается в том, что мне нужно вручную создать ассоциацию для поддержки полиморфной ассоциации с ограничением уникальности в ловушке. Например:
class Matchup < ActiveRecord::Base
belongs_to :event
belongs_to :matchupable, :polymorphic => true
validates :event_id, :uniqueness => { :scope => [:matchupable_id, :matchupable_type] }
end
class BaseballMatchup < ActiveRecord::Base
has_one :matchup, :as => :matchupable
end
FactoryGirl.define do
factory :matchup do
event { FactoryGirl::Singleton.execute(:event) }
matchupable { FactoryGirl::Singleton.execute(:baseball_matchup) }
home_team_record '10-5'
away_team_record '9-6'
end
factory :baseball_matchup do
home_pitcher 'Joe Bloe'
home_pitcher_record '21-0'
home_pitcher_era 1.92
home_pitcher_arm 'R'
away_pitcher 'Jack John'
away_pitcher_record '0-21'
away_pitcher_era 9.92
away_pitcher_arm 'R'
after_build do |bm|
bm.matchup = Factory.create(:matchup, :matchupable => bm)
end
end
end
Моя текущая одноэлементная реализация не поддерживает вызов FactoryGirl::Singleton.execute(:matchup, :matchupable => bm)
, только FactoryGirl::Singleton.execute(:matchup)
.
Как бы вы порекомендовали изменить фабрику синглтона для поддержки вызова, такого как FactoryGirl::Singleton.execute(:matchup, :matchupable => bm)
ИЛИ FactoryGirl::Singleton.execute(:matchup)
?
Поскольку прямо сейчас приведенный выше код будет выдавать ошибку проверки уникальности («событие уже выполнено») каждый раз, когда перехват выполняется на фабрике: baseball_matchup. В конечном счете, это то, что необходимо исправить, чтобы в БД не более одного matchup или baseball_matchup.