Как выбрать, где ID в Array Rails ActiveRecord без исключения

Когда у меня есть массив идентификаторов, например

ids = [2,3,5]

и я выполняю

Comment.find(ids)

все работает нормально. Но когда есть id, которого не существует, я получаю исключение. Это происходит вообще, когда я получаю список идентификаторов, которые соответствуют некоторому фильтру, и чем я делаю что-то вроде

current_user.comments.find(ids)

На этот раз у меня может быть действительный идентификатор комментария, который, однако, не принадлежит данному пользователю, поэтому он не найден, и я получаю исключение.

Я пробовал find(:all, ids), но он возвращает все записи.

Единственный способ сделать это сейчас -

current_user.comments.select { |c| ids.include?(c.id) }

Но это кажется мне супер-неэффективным решением.

Есть ли лучший способ выбрать ID в массиве, не получая исключения из несуществующей записи?

Ответ 1

Если вы просто избегаете того исключения, о котором вы беспокоитесь, семейство функций "find_all_by.." работает без каких-либо исключений.

Comment.find_all_by_id([2, 3, 5])

будет работать, даже если некоторые из идентификаторов не существуют. Это работает в

user.comments.find_all_by_id(potentially_nonexistent_ids)

.

Обновление: Rails 4

Comment.where(id: [2, 3, 5])

Ответ 2

Обновление: этот ответ более важен для Rails 4.x

Сделайте это:

current_user.comments.where(:id=>[123,"456","Michael Jackson"])

Более сильная сторона этого подхода состоит в том, что он возвращает объект Relation, к которому вы можете присоединиться к предложениям .where, .limit и т.д., что очень полезно. Он также допускает несуществующие идентификаторы без исключения исключений.

Новый синтаксис Ruby будет выглядеть следующим образом:

current_user.comments.where(id: [123, "456", "Michael Jackson"])

Ответ 3

Если вам нужно больше управления (возможно, вам нужно указать имя таблицы), вы также можете сделать следующее:

Model.joins(:another_model_table_name)
  .where('another_model_table_name.id IN (?)', your_id_array)

Ответ 4

Теперь методы .find и .find_by_id устарели в рельсах 4. Поэтому вместо этого мы можем использовать ниже:

Comment.where(id: [2, 3, 5])

Он будет работать, даже если некоторые из идентификаторов не существуют. Это работает в

user.comments.where(id: avoided_ids_array)

Также для исключения идентификаторов

Comment.where.not(id: [2, 3, 5])

Ответ 5

Чтобы избежать исключений, убивающих ваше приложение, вы должны поймать эти исключения и обработать их так, как вы пожелаете, определяя поведение для вашего приложения в тех ситуациях, когда идентификатор не найден.

begin
  current_user.comments.find(ids)
rescue
  #do something in case of exception found
end

Здесь подробнее об исключениях в ruby.

Ответ 6

Вы также можете использовать его в named_scope, если хотите добавить другие условия

например, включают некоторую другую модель:

named_scope 'get_by_ids', lambda {| ids | {: include = > [: comments],: conditions = > [ "comments.id IN (?)", ids]}}