我有一段代码,通过id获取关联对象,否则它将初始化一个新对象。
def pick_for_game(game_id)
picks.find_or_initialize_by_game_id(game_id)
end
picks集合通常包含数百个条目。这两个用例是:
我想在15-30个游戏中调用这个方法
我想在所有游戏中调用这个方法
似乎当前的方法对于用例a来说是可以的,但是对于用例b来说是绝对糟糕的。我可以根据是否已经急切地加载了拾取,使这个方法变得复杂,如下所示:
def pick_for_game(game_id)
if picks.loaded?
new_pick = proc {
Pick.new do |p|
p.game_id = game_id
end
}
picks.detect(new_pick) do |p|
p.game_id == game_id
end
else
picks.find_or_initialize_by_game_id(game_id)
end
end
然而,在所有情况下选择一种方法而不是另一种方法除了使代码更干净之外还有什么优点吗?这个问题还有别的解决办法吗?
假设Pick是一个模型,如果你知道game_ids列表,你可以在一个查询中获取指定游戏的所有现有Pick,并且只初始化剩余game_ids的新Pick:
def picks_for_games( game_ids )
existing_picks = Pick.all( :conditions => { :game_id => game_ids } )
game_ids_without_picks = game_ids - existing_picks.map{ |x| x.game_id }
new_picks = game_ids_without_picks.map {
|game_id| Pick.initialize_by_game_id( game_id )
}
return picks + new_picks
end
你可以在两种实现之间切换,取决于:
if game_ids.is_a?( Array )
b)的一个选项是在Game上为任何引用它的pick添加一个关联,这样你就可以快速查询没有pick的游戏,并为每个Game初始化一个pick。
Game.all( :conditions => { :picks => nil } ).map { |game| Pick.initialize_by_game_id( game.id ) }