Read more

Custom error pages in Rails

Tobias Kraze
November 30, 2012Software engineer at makandra GmbH

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.

Illustration online protection

Rails Long Term Support

Rails LTS provides security patches for old versions of Ruby on Rails (2.3, 3.2, 4.2 and 5.2)

  • Prevents you from data breaches and liability risks
  • Upgrade at your own pace
  • Works with modern Rubies
Read more Show archive.org snapshot

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
  1. 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
  1. Add the corresponding views.

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

  3. 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"
    
  4. (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
November 30, 2012Software engineer at makandra GmbH
Posted by Tobias Kraze to makandra dev (2012-11-30 18:10)