Этот вопрос является расширением вопроса, поднятого здесь:
Предложенный ответ отлично сработал для меня. Вот как это выглядит:
# 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(: совпадение)
.
Как бы вы рекомендовали модифицировать фабрику singleton для поддержки такого вызова, как FactoryGirl::Singleton.execute(:matchup, :matchupable => bm)
ИЛИ FactoryGirl::Singleton.execute( :matchup)
?
Потому что прямо сейчас приведенный выше код будет выдавать ошибку проверки уникальности («Событие уже занято») каждый раз, когда хук запускается на фабрике :baseball_matchup. В конечном счете, именно это необходимо исправить, чтобы в базе данных не было более одного matchup или baseball_matchup.