w3ghqq
15.08K
· September 2012 ·
Dsc 0061

Rails 3.2 error handling with exceptions_app

Render cool error pages in production with Rails 3.2
Since Rails 3 you cannot directly handle exceptions in the middleware layer, like RoutingError, in your controller (e.g. with the rescuefrom helper). Rails 3.2. lets you configure an exceptionsapp, which will be used in production mode to handle you're exceptions.

Use Routes Engine as exceptions_app
You can use the Routes Engine as exceptions_app with a simple setting in application.rb

class Application < Rails::Application
   ...
   config.exceptions_app = self.routes
   ...
end

Now you can simply route your exceptions to your ExceptionController

MyApp::Application.routes.draw do
   ...
   match '/404', :to => "exceptions#render_404"
   ...
end

Use custom Rack application as exceptions_app
You can use any Rack application as exceptionsapp. Since a Rails controller is basically a Rack application, you can also use your ExceptionController directly as exceptionsapp. Use a lambda expression, because the controller name constant is not yet available in the initialization stage.

class Application < Rails::Application
   ...
   config.exceptions_app = lambda do |env|
        ExceptionController.action(:render_error).call(env)
   end
   ...
end

Get exception diagnostics in your controller
In your controller you can easily get the exception's properties (e.g. statuscode).

 class ExceptionController < ActionController::Base
     layout 'application'

     def render_error
         @exception = env["action_dispatch.exception"]
         @status_code = ActionDispatch::ExceptionWrapper.new(env, @exception).status_code
         render :error_page, status: @status_code, layout: true
     end
 end
Sign in or sign up to add your response.

6 Responses

102
Dsc 0061

Note that the ExceptionController does not extend ApplicationController to keep it as simple as possible and limit the possibility of other exceptions

over 1 year ago ·
6412
Dsc 0061

@turadg Very cool :) thanks for sharing

over 1 year ago ·
8658
Photo on 08.01.2013 at 04.15

I wrote little more enhanced version of this (layouts, fallback to generic error page, hiding of 500 error messages in production): https://github.com/sheerun/rails4-bootstrap/commit/5c2df5a108ad204bc407183b959bb355ff5ed53d

over 1 year ago ·
10059
Photo on 08.01.2013 at 04.15

It's probably better to look at my pull-request, because I made some fixes: https://github.com/sheerun/rails4-bootstrap/issues/26

over 1 year ago ·
15712
8feb5b9d82b88d334d2342ae950af804

This is a much better way to do this

config.exceptions_app = proc{|env|
  ErrorsController.action(:render_error).call(env)
}
over 1 year ago ·
15713
8feb5b9d82b88d334d2342ae950af804

For some more context: We have an app where with a

get '/:username' => "…"

route which was raising a second exception to an obscure status code route.

I highly recommend anyone who needs to render errors this way either use controller exception catching or bypass the rails router all together.

over 1 year ago ·