Как выбрать где ID в массиве рельсов ActiveRecord без исключения - PullRequest
122 голосов
/ 18 сентября 2009

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

ids = [2,3,5]

и я исполняю

Comment.find(ids)

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

current_user.comments.find(ids)

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

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

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

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

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

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

Ответы [ 6 ]

195 голосов
/ 18 сентября 2009

Если вы просто избегаете исключений, о которых вы беспокоитесь, семейство функций 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])
144 голосов
/ 12 июля 2012

Обновление: этот ответ более актуален для 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"])
18 голосов
/ 25 сентября 2014

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

Model.joins(:another_model_table_name)
  .where('another_model_table_name.id IN (?)', your_id_array)
10 голосов
/ 12 июня 2014

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

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

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

user.comments.where(id: avoided_ids_array)

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

Comment.where.not(id: [2, 3, 5])
1 голос
/ 18 сентября 2009

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

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

Вот больше информации об исключениях в ruby.

0 голосов
/ 08 сентября 2010

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

например, включают в себя некоторые другие модели:

named_scope 'get_by_ids', lambda {| ids | {: include => [: comments],: условие => ["comments.id IN (?)", идентификаторы]}}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...