ker*_*lin 9 ruby singleton rspec factory-bot
这个问题是对这里提出的问题的扩展:
在Rails中使用具有唯一约束的关联的factory_girl.获得重复的错误
提供的答案对我来说非常有用.这是它的样子:
# 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
Run Code Online (Sandbox Code Playgroud)
我遇到的问题是,当我需要手动构建关联以支持钩子中具有唯一性约束的多态关联时.例如:
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
Run Code Online (Sandbox Code Playgroud)
我目前单身实现不支持打电话FactoryGirl::Singleton.execute(:matchup, :matchupable => bm),只FactoryGirl::Singleton.execute(:matchup).
您如何建议修改单件工厂以支持FactoryGirl::Singleton.execute(:matchup, :matchupable => bm)OR之类的调用FactoryGirl::Singleton.execute(:matchup)?
因为现在,每次在工厂运行钩子时,上面的代码都会抛出唯一性验证错误("已经采取了事件"):baseball_matchup. 最终,这是需要修复的内容,以便DB中不会有多个matchup或baseball_matchup.
您需要做两件事才能使这项工作成功:
execute。请注意,步骤 1 不足以解决您的问题。即使您允许execute接受属性,第一次调用execute(:matchup, attributes)也会缓存该结果并在您随时返回它execute(:matchup),即使您尝试将不同的属性传递给execute。这就是为什么您还需要更改用作散列的散列键的内容@@singletons。
这是我测试过的一个实现:
module FactoryGirl
class Singleton
@@singletons = {}
def self.execute(factory_key, attributes = {})
# form a unique key for this factory and set of attributes
key = [factory_key.to_s, '?', attributes.to_query].join
begin
@@singletons[key] = FactoryGirl.create(factory_key, attributes)
rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotUnique
# already in DB so return nil
end
@@singletons[key]
end
end
end
Run Code Online (Sandbox Code Playgroud)
键是一个字符串,由工厂名称和属性哈希的查询字符串表示形式(类似于"matchup?event=6&matchupable=2")组成。我能够创建多个具有不同属性的不同匹配,但它尊重事件/可匹配组合的独特性。
> e = FactoryGirl.create(:event)
> bm = FactoryGirl.create(:baseball_matchup)
> m = FactoryGirl::Singleton.execute(:matchup, :event => e, :matchupable => bm)
> m.id
2
> m = FactoryGirl::Singleton.execute(:matchup, :event => e, :matchupable => bm)
> m.id
2
> f = FactoryGirl.create(:event)
> m = FactoryGirl::Singleton.execute(:matchup, :event => f, :matchupable => bm)
> m.id
3
Run Code Online (Sandbox Code Playgroud)
如果这对您不起作用,请告诉我。