Как я могу пропустить ошибку, если find ничего не возвращает в рельсах?

Я пытаюсь создать систему, в которой пользователь может видеть только статьи, которые он написал.

В контроллере статей я помещаю ниже строки

@article = current_user.articles.find(params[:id])

где params [: id] - article_id.

Я просто хочу знать, как я могу пропустить ошибку из отображения и просто перенаправить на: действие индекса, если статья не существует, или если у пользователя нет разрешения на просмотр. Я положил @article.nil? условный оператор после инструкции find выше, но кажется, что вышеприведенный вывод вызывает ошибку, как показано ниже.

Не удалось найти статью с идентификатором = 1662 [ГДЕ (articles.user_id = 1)]

Как я могу решить эту проблему?

Ответы

Ответ 1

ActiveRecord:: Base.find всегда выдает исключение, если оно не находит запись, это преднамеренно. Вы должны использовать только find, если вы абсолютно ожидаете иметь то, что вы ищете. Если вы растеряете действие шоу и не можете найти статью, вы должны спасти это исключение и отобразить 404 (не найдено) вместо перенаправления на индекс (технически).

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

Edit:

У динамических искателей теперь есть другая подпись, find_by_id теперь должна быть:

find_by :id, id_to_find

Смотрите новый Rails Guide on Querying

Ответ 2

Вы должны использовать find_by_id или любой из методов, приведенных в этом question.

Ответ 3

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

begin
  @article = current_user.articles.find(params[:id])
rescue
  redirect_to articles_path
end

Ответ 4

Метод find() вызывает исключение RecordNotFound, тогда как методы, такие как find_by_id, возвращают значение nil. Таким образом, у вас есть пара опций, которые вы можете связать с вызовом метода start/rescue, добавьте блок rescue_from к контроллеру:

rescue_from(ActiveRecord::RecordNotFound) {|e| do something here }

или использовать метод find_by_id и обрабатывать условие, в котором возвращается nil.

На самом деле существует множество других альтернатив, но те, что выше, являются хорошим началом, причем find_by_id, вероятно, является самым легким.