I wanted to improve error handling In my Rails applications. Specifically, I wanted three things:
- a custom error page that matched the site's design
- the errors to appear in the error log (production.log)
- email notification of server errors
Note: these steps are for Rails 2.3.2–2.3.8. Other versions may require different instructions.
Custom error page
Normally, when server error occurs, Rails renders public/500.html. You can customize this. However, if you include your site's layout information here, you violate the DRY principle.
- Create a directory for error templates
mkdir app/views/errors
- Create the error file:
touch app/views/errors/500.html.erb
- Remove the static file:
rm public/500.html
- In
application_controller.rb
, overriderender_optional_error_file
:protected def render_optional_error_file(status_code) render :template => "errors/500", :status => 500, :layout => 'application' end
- To test your error handler in the development environment, in
application_controller.rb
, add this line:alias_method :rescue_action_locally, :rescue_action_in_public
be sure to comment this out when you're done, so you can see backtraces.
Logging errors
Because we overrode render_optional_error_file
instead of using rescue_from
(2), errors still go to the log (production.log
).
Email notification
There's a terrific exception notification plugin that handles this for you.
This is a bit confusing, because there are three versions of the plugin floating around:
- The master version on github, for Rails 3
- A branch on github, for Rails 2.3
- The old version, which also works with Rails 2
Important If you install via the standard method (script/plugin install
), you'll get an old version of the plugin, and the current instructions (on github) won't work. (See below for legacy instructions.)
If you install from github, you'll get a version for Rails 3 by default, and that won't work, either.
Here's what to do:
- Install the plugin from the 2-3-stable branch from github:
script/plugin install git://github.com/rails/exception_notification.git -r 2-3-stable
- In
application_controller.rb
, place this at the top:include ExceptionNotification::Notifiable
- In
environment.rb
, add these lines at the very end, after the|config|
block:ExceptionNotification::Notifier.exception_recipients = %w([email protected]) ExceptionNotification::Notifier.sender_address = %("Application Error" <[email protected]>) ExceptionNotification::Notifier.email_prefix = "[Fancy App] "
-
To have sendmail send email (instead of using raw SMTP), add this line to
environment.rb
:ActionMailer::Base.delivery_method = :sendmail
Legacy exception_notification instructions
- Install the plugin:
script/plugin install exception_notification
- In
application_controller.rb
, place this at the top:include ExceptionNotifiable
- In
environment.rb
, add these lines at the very end, after the|config|
block:ExceptionNotifier.exception_recipients = %w([email protected]) ExceptionNotifier.sender_address = %("Application Error" <[email protected]>) ExceptionNotifier.email_prefix = "[Fancy App] "
Thanks for the post! After you put this in place, did you find that exception notification emailed you for 404s? I used what you did, but overwrote render_optional_error_file in a slightly different way and started getting notifications on 404s. Here’s what I did:
Oh, I had effectively disabled 404s by redirecting everyone home:
map.connect '*path', :controller => :home, :action => :error
Your idea seems better.
Ah, gotcha. The problem with my approach was that I would get emailed on all 404s as well, which was driving me crazy. I narrowed the problem down to a method in exception notification:
def deliver_exception_notification?
!self.class.skip_exception_notifications? && ![404, "404 Not Found"].include?(response.status)
end
I overrode this method in my application_controller by simply changing 404 (int) to “404” (string). That worked (I’m getting emails on all errors now except for 404s), but I’m trying to figure out if that’s really a bug in exception notification and, if so, if I handled it correctly.
Thanks Paul and Jeremy for this post. It’s exactly what I was looking for
not working at all, I try to put an error on my apps in order to test it.
but it never send any email
What version of Rails are you using?