Rescue errors in a Rails controller

Ruby on Rails / Refactoring

Sometimes you have to rescue from errors in your Ruby on Rails controller. You mostly would need to rescue from ActiveRecord::RecordNotFound exception raised when you did a query but your record was not present in the database.

Let’s build a sample controller:

class UsersController < ApplicationController
  def show
    @user = User.find(params[:id])
  rescue ActiveRecord::RecordNotFound => e
    redirect_to :root, alert: 'User not found'
  end

  def edit
    @user = User.find(params[:id])
  rescue ActiveRecord::RecordNotFound => e
    redirect_to :root, alert: 'User not found'
  end
end

We have two methods and in both methods, we handle the same exception in the same way. To make the code more reusable we can use rescue_from method ActiveSupport module:

class UsersController < ApplicationController
  rescue_from ActiveRecord::RecordNotFound do |exception|
    redirect_to :root, alert: 'User not found'
  end

  def show
    @user = User.find(params[:id])
  end

  def edit
    @user = User.find(params[:id])
  end
end

We can also refactor show and edit methods by using before_action filter but let’s not focus on it now. Our controller now is more readable and we didn’t use the same code twice - nice! We can also pass a method name instead of block:

class UsersController < ApplicationController
  rescue_from ActiveRecord::RecordNotFound, with: :redirect_to_homepage

  def show
    @user = User.find(params[:id])
  end

  def edit
    @user = User.find(params[:id])
  end

  protected

  def redirect_to_homepage
    redirect_to :root, alert: 'User not found'
  end
end

We can even use one method across few controllers using concerns. It depends on the logic you use to rescue from given exception. rescue_method is very useful when you want to show nice page to the user when an error occurs - without it, he would see default error page which is not nice.