Как выбрать где ID в массиве рельсов ActiveRecord без исключения
-
10-07-2019 - |
Вопрос
Когда у меня есть массив идентификаторов, например
ids = [2,3,5]
и я выполняю
Comment.find(ids)
все отлично работает. Но когда есть идентификатор, который не существует, я получаю исключение. Обычно это происходит, когда я получаю список идентификаторов, которые соответствуют какому-либо фильтру, а затем я делаю что-то вроде
current_user.comments.find(ids)
На этот раз у меня может быть действительный идентификатор комментария, который, однако, не принадлежит данному пользователю, поэтому он не найден, и я получаю исключение.
Я попытался найти (: все, идентификаторы)
, но он возвращает все записи.
Единственный способ сделать это сейчас -
current_user.comments.select { |c| ids.include?(c.id) }
Но мне кажется, что это супер неэффективное решение.
Есть ли лучший способ выбрать ID в массиве без исключения для несуществующей записи?
Решение
Если это просто исключение, о котором вы беспокоитесь, то " 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])
Другие советы
Обновление: этот ответ более актуален для 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"])
Если вам нужен больший контроль (возможно, вам нужно указать имя таблицы), вы также можете сделать следующее:
Model.joins(:another_model_table_name)
.where('another_model_table_name.id IN (?)', your_id_array)
Теперь методы .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])
Чтобы избежать исключений, убивающих ваше приложение, вы должны перехватывать эти исключения и обращаться с ними так, как вам нравится, определяя поведение вашего приложения в тех ситуациях, когда идентификатор не найден.
begin
current_user.comments.find(ids)
rescue
#do something in case of exception found
end
Вот дополнительная информация об исключениях в ruby.
Вы также можете использовать его в named_scope, если хотите поставить другие условия
например, включите другую модель:
named_scope 'get_by_ids', lambda {| ids | {: include = > [: комментарии],: условия = > [" comments.id IN (?) " ;, ids]}}