Не уверен, как оптимизировать активную ассоциацию записи - PullRequest
0 голосов
/ 11 апреля 2011

У меня есть фрагмент кода, который получает связанный объект по идентификатору, в противном случае он инициализирует новый объект.

def pick_for_game(game_id)
   picks.find_or_initialize_by_game_id(game_id)
end

В коллекции выбора обычно содержится несколько сотен элементов.Два варианта использования:

  1. Я хочу вызвать этот метод для 15-30 игр

  2. Я хочу вызвать этот метод для всех игр

Похоже, что текущий подход подходит для варианта использования 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

Однако, выбор одного подхода по сравнению с другим для всех случаев имел бы какую-то ценность, кроме как сделать коднемного чище?Любые другие решения этой проблемы?

1 Ответ

0 голосов
/ 12 апреля 2011

Предполагая, что Pick является моделью, если вы знаете список game_ids, вы можете выбрать все существующие Pick для указанных Игр в одном запросе и инициализировать только новые Pick для оставшихся game_ids:

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.all( :conditions => { :picks => nil } ).map { |game| Pick.initialize_by_game_id( game.id ) }
...