Custom error pages in Rails

Updated . Posted . Visible to the public. Repeats.

Basic error pages

To add a few basic styles to the default error pages in Rails, just edit the default templates Show archive.org snapshot in public, e.g. public/404.html.

A limitation to these default templates is that they're just static files. You cannot use Haml, Rails helpers or your application layout here. If you need Rails to render your error pages, you need the approach below.

Advanced error pages

  1. Register your own app as the application responsible for showing error pages by adding

    config.exceptions_app = routes
    

    to your config/application.rb.

  2. Add routes for the error pages, by appending this to your config/routes.rb:

    match '/404' => 'errors#not_found', via: :all
    match '/422' => 'errors#server_error', via: :all
    match '/500' => 'errors#server_error', via: :all
    
  3. Add an ErrorsController like this one:

     class ErrorsController < ApplicationController
       skip_before_action :verify_authenticity_token
       
       def not_found
         render :status => 404, :formats => [:html]
       end
      
       def server_error
         render :status => 500, :formats => [:html]
       end
     end
    
  4. Add the corresponding views.

  5. Delete the static error pages 404.html, 422.html and 500.html from public/.

  6. Add some tests, for example a cucumber feature:

    @allow-rescue
    Scenario: 404 page
      When I go to the path "/foobar"
      Then the page should be titled "Page not found"
        And I should see "We're sorry, but couldn't find the page you requested"
        And the response status should be "404"
    
  7. (Optional) In a request spec, you'll need to stub a few config variables (in the cached Rails environment config):

    # spec/requests/error_pages_spec.rb
    describe "Error pages" do
      def handle_errors
        env_config = Rails.application.env_config
    
        show_exceptions = env_config['action_dispatch.show_exceptions']
        local_requests = env_config['action_dispatch.show_detailed_exceptions']
    
        # Disables Rails built-in error reports, so our custom error application
        # can handle them and render it's own templates. This overrides the cached
        # setting in Rails.application.config.consider_all_requests_local
        env_config['action_dispatch.show_detailed_exceptions'] = false
    
        # Render exception templates instead of raising exceptions.
        # This is the cached setting for
        # Rails.application.config.action_dispatch.show_exceptions
        env_config['action_dispatch.show_exceptions'] = true
    
        yield
    
        env_config['action_dispatch.show_exceptions'] = show_exceptions
        env_config['action_dispatch.show_detailed_exceptions'] = local_requests
      end
    
      around(:each) do |example|
        handle_errors(&example)
      end
    
     # ...
     end
    

Additional notes

  • You cannot modify headers, so you can't modify the session, cookies etc.
  • You won't see this in development, except if you set config.consider_all_requests_local = false in your config/development.rb.
  • Rails will automatically choose a particular error page for some types of unhandled exceptions
Tobias Kraze
Last edit
Michael Leimstädtner
License
Source code in this card is licensed under the MIT License.
Posted by Tobias Kraze to makandra dev (2012-11-30 17:10)