Тот факт, что вы делаете много ручной проверки на наличие исключений, говорит о том, что вы просто неправильно их используете. На самом деле, ни один из ваших примеров не является исключительным.
Что касается несуществующего поста - вы должны ожидать, что ваши пользователи API (например, пользователь, использующий ваш интернет через браузер) будут запрашивать несуществующие посты.
Ваш второй пример (Post.find (5) .comments [0] .created_at) также не является исключительным. Некоторые посты просто не имеют комментариев, и вы знаете это заранее. Так почему же это исключение?
То же самое в случае с примером ActiveRecord :: RecordInvalid. Там просто нет причин обрабатывать этот случай с помощью исключения. То, что пользователь вводит в форму некоторые недействительные данные, довольно обычное дело, и в этом нет ничего исключительного.
Использование механизма исключений для подобных ситуаций может быть очень удобным в некоторых ситуациях, но это неверно по причинам, указанным выше.
С учетом сказанного это не означает, что вы не можете СУШИТЬ код, который инкапсулирует эти ситуации. Существует довольно большой шанс, что вы сможете сделать это хотя бы до некоторой степени, поскольку это довольно распространенные ситуации.
Итак, что насчет исключений? Что ж, первое правило на самом деле таково: используйте их как можно реже.
Если вам действительно нужно их использовать, есть два вида исключений в целом (на мой взгляд):
исключений, которые не нарушают общий рабочий процесс пользователя в вашем приложении (представьте исключение в подпрограмме генерации миниатюр изображения профиля), и вы можете либо скрыть их от пользователя, либо просто уведомить его о проблеме и ее последствия при необходимости
исключения, которые вообще не позволяют пользователю использовать приложение. Они являются последним средством и должны обрабатываться через 500 внутренних ошибок сервера в веб-приложениях.
Я склонен использовать метод rescue_from
в ApplicationController только для последнего, поскольку есть более подходящие места для первого типа, и ApplicationController как верхний из классов контроллера, кажется, является правильным местом для возврата к в таких обстоятельствах (хотя в настоящее время какое-то промежуточное программное обеспечение Rack может быть даже более подходящим местом для размещения таких вещей).
- РЕДАКТИРОВАТЬ -
Конструктивная часть:
Что касается первого, я бы посоветовал начать использовать find_by_id вместо find, поскольку он не выдает исключение, а возвращает nil в случае неудачи. Ваш код будет выглядеть примерно так:
unless @p = Post.find_by_id(params[:id])
flash[:error] = "Can't find Blog Post"
end
что гораздо менее болтливо.
Другая распространенная идиома для СУШКИ в подобных ситуациях - использование контроллера before_filters для установки часто используемых переменных (например, @p в данном случае). После этого ваш контроллер может выглядеть следующим образом
controller PostsController
before_filter :set_post, :only => [:create, :show, :destroy, :update]
def show
flash[:error] = "Can't find Blog Post" unless @p
end
private
def set_post
@p = Post.find_by_id(params[:id])
end
end
Что касается второй ситуации (несуществующего последнего комментария), одно очевидное решение этой проблемы - перевести все это в помощника:
# This is just your way of finding out the time of the last comment moved into a
# helper. I'm not saying it's the best one ;)
def last_comment_datetime(post)
comments = post.comments
if comments.empty?
"No comments, yet."
else
"Last comment for this post at: #{comments.last.created_at}"
end
end
Тогда, по вашему мнению, вы просто позвоните
<%= last_comment_datetime(post) %>
Таким образом, крайний случай (публикация без каких-либо комментариев) будет обрабатываться на своем месте, и это не будет загромождать представление.
Я знаю, что ни один из них не предлагает какого-либо шаблона для обработки ошибок в Rails, но, возможно, с некоторыми рефакторингами, такими как эти, вы обнаружите, что большая часть потребности в какой-то стратегии для обработки исключений / ошибок просто исчезает.