Exception Handling Approach - This is what I'm doing

Hi - Any feedback from people re how they handle exception handling in
RoR? Here’s what I’m doing…

I’ve ended up doing the following so far, some of which are adjustments
to
Jamis B.'some “Exception Notification” plugin. I’m still optimizing
this
for my own usage as I go. Hope this helps (any ideas/feedback welcome):

Usage:
if error_situation_occurs
raise Error.new( “Message to User Here - Will be shown on error page”,
“Additional message that will go to log file for
developers”,
Logger::ERROR)
end

Features:

  • Separate user & developer messages
  • Do not have to catch such errors back in controller or views as the
    below-mentioned rails rescue frame work will handle ( i.e. less work,
    cleaner code)
  • Just need to raise the Error exception which then
    triggers/implies/carries
    out:
    (a) appropriate email message to user
    (b) developer specific additional message to logs
    © severity of log entry raised
    (b) triggers Email/SMS alert based on severity of the error (use of
    Ruby
    Logger severity levels)

class Error < RuntimeError
attr :developer_message
attr :severity

def initialize(user, dev=nil, sev=Logger::FATAL)
super user # Use normal exception parameter
for
User Message
@developer_message = dev || user # Set developer focused message
@severity = sev
end
end

def rescue_action_in_public(exception) # Override this Rails method
case exception
when *exceptions_to_treat_as_404
render_404
else
if exception.instance_of?(Error) # Added by Greg
# Custom Error (caught)
render_custom_error
case (exception.severity)
when Logger::FATAL
# trigger an email/sms for FATALs
send_notification(exception)
else
# no emails/sms otherwise - future step: have this
configurable in
environment.rb
end
else
# 500 Error (not caught)
render_500
send_notification(exception)
end
end
end

def render_custom_error
respond_to do |type|
type.html { render :template => “error/custom_500_error”}
type.all { render :nothing => true, :status => “500 Error” }
end
end

def log_error(exception) #:doc: # Override this Rails method
ActiveSupport:: Deprecation.silence do
if ActionView::TemplateError === exception
logger.fatal(exception.to_s)
else
if exception.instance_of?(Error) # Added by Greg - logs the
User
Message, Log/Developer Message and limits stack trace to first 3 lines
# Custom Error (caught)
logger.error("#{exception.developer_message}\n" +
" Exception Class:#{exception.class}\n" +
" User Msg: #{exception.message }\n" +
" Backtrace:\n " + clean_backtrace(exception)[0…2].join("\n
“) + “\n\n”
)
else
logger.fatal(”#{exception.developer_message }\n" +
" Exception Class:#{exception.class}\n" +
" Backtrace:\n " + clean_backtrace(exception)[0…2].join("\n
") + “\n\n”
)
end
end
end
end

class SomethingsController < ApplicationController
def create
@something = Something.create!(params[:something])
flash[:success] = “Something was created!”
rescue ActiveRecord::RecordNotSaved, ActiveRecord::RecordInvalid
flash[:errors] = “Something could not be created.”
render :action => “new”
end
end

You did say any feedback.

This is currently what we’re doing and hopefully later on when other
exceptions are raised we will be notified by email.