By Myles Eftos

Preparing for Rails 2.0: Controller-based exception handling

By Myles Eftos
Help us help you! You'll get a... FREE 6-Month Subscription to SitePoint Premium Plus you'll go in the draw to WIN a new Macbook SitePoint 2017 Survey Yes, let's Do this It only takes 5 min

Since Ruby is a pure Object-Oriented Language, exceptions play a big role in the flow of control. Previously, you had the choice of rescuing exceptions at a local level or you could override the rescue_action method in your controller.

The former method gave you really fine-grained control of what to do in the case of an exception:

rescue ActiveRecord::RecordInvalid
    render :action => 'new'

In this case, if the ActiveRecord::RecordInvalid exception is raised (the save! method will raise this if validation fails) Rails will render the ‘new’ action. It became clear, though that adding begin/rescues around the same methods is pretty time consuming and not very DRY – which is where the rescue_action became helpful:

def rescue_action(exception)
  if exception == ActionView::TemplateError
    render :template => 'errors/404'

This (rather contrived) example will trap any ActionView::TemplateError and render the 404.erb file in the /app/views/errors directory. You are able to drop that method into any controller (including app_controller), but again, there is a lot of work involved in setting them up, making sure each controller performs the correct action for a given exception, which is why Rails 2.0 introduces rescue_from.

rescue_from is an attribute of each controller, and allows you to define a method to run when a particular exception is called. So the above example would become:

rescue_from ActionView::TemplateError, :with => :render_404

def render_404(exception)
   render :template => 'errors/404'

or if you prefer to use a inline block:

rescue_from ActionView::TemplateError do { render :template => 'errors/404' }

In the current PR release, the rescue_from technique can only catch exceptions of an exact type, so it wouldn’t catch sub-classed exceptions – if you had a custom exception called MyTemplateError that extends ActionView::TemplateError the above code won’t work. The good news is a patch to edge rails fixes this issue, so the release version of Rails 2.0 will work as expected.

Login or Create Account to Comment
Login Create Account
Get the most important and interesting stories in tech. Straight to your inbox, daily.Is it good?