User-friendly 500 and 404 pages on Rails 3

This came in handy for me, so I wanted to share this particular way of handling 404 and 500 errors.

First, rescue errors and tell what to do in application_controller.rb.

  if Rails.env.production?
    unless Rails.application.config.consider_all_requests_local
      rescue_from Exception, with: :render_500
      rescue_from ActionController::RoutingError, with: :render_404
      rescue_from ActionController::UnknownController, with: :render_404
      rescue_from ActionController::UnknownAction, with: :render_404
      rescue_from ActiveRecord::RecordNotFound, with: :render_404
    end
  end

In the same application_controller.rb, then you create the methods specified above.

  def render_404(exception)
    @not_found_path = exception.message
    respond_to do |format|
      format.html { render template: 'errors/not_found', layout: 'layouts/application', status: 404 }
      format.all { render nothing: true, status: 404 }
    end
  end

  def render_500(exception)
    logger.info exception.backtrace.join("\n")
    respond_to do |format|
      format.html { render template: 'errors/internal_server_error', layout: 'layouts/application', status: 500 }
      format.all { render nothing: true, status: 500}
    end
  end

Since it’s using the application layout, you will see the error message you specify in the layout. The following is my 500 error page, /views/errors/internal_server_error.html.haml. For 404 page, you can also use @not_found_path instance variable in the view as well.

#errors-page
  .thumbnail.errors
    .errors-500
    .caption
      %h5 Sorry
  %h1 500 Internal Server Error

  - # Do not remove this line. It is used for development
  - # purposes. When an error is found. In development, it
  - # shows the logs, in production it is nil.
  .error-msg
    = @log

Cheers,