Custom Error Pages in Ruby on Rails
Tags: ruby, rails, tutorial, video
Published: 2020-11-18 15:02:37

---
title: Custom Error Pages in Ruby on Rails
published: true
date: 2020-11-11 20:23:00 UTC
tags: ruby, rails, tutorial, video
canonical_url: https://web-crunch.com/posts/custom-error-page-ruby-on-rails
---

{% youtube _laCIdQmOr4 %}

Ruby on Rails ships with default error pages for more popular requests you might encounter including `404`, `500`, and `422`. Each request has an associated static `HTML` page that lives inside every new Ruby on Rails app's `public` directory.

There may come a time where those static pages are a bit cumbersome to work with or you want to add a little more flair to yours using assets that already exist in your app. The public folder by design lives outside of the bound of what Rails and serve so you will see that each `html` page has embedded styles and content.

This works for basic error pages but in my own case I wanted to leverage Tailwind CSS that I was already using inside my application. We can do this in a few steps but that means tweaking some configuration and telling your app how to handle errors in a new custom way.

### Start with a controller

Generating a new `ErrorsController` that inherits from `ApplicationController` is a good first step in creating your custom error pages. With this controller we can render specific statuses that will ultimately render the corresponding views instead of those `html` templates in the `public` directory.

```bash
$ rails g controller errors not_found internal_server_error
```

The command above generates the controller and views we need. It also creates a helper file, basic routing, and some test files. Note the new methods `not_found` and `internal_server_error` in the controller.

Within those, we can tell our app what to render as a response. Each method maps to a different response.

```ruby
# app/controllers/errors_controller.rb

class ErrorsController < ApplicationController
  def not_found
    render status: 404
  end

  def internal_server_error
    render status: 500
  end
end
```

### Configuring routes

While our controller is set up for success we still need to add the appropriate routing to handle our new error pages.

```ruby
# config/routes.rb
Rails.application.routes.draw do
  ...
  match "/404", to: "errors#not_found", via: :all
  match "/500", to: "errors#internal_server_error", via: :all
  ...
end
```

Using the `match` methods we can pass in a relative path to the request we passed down from the controller. If that path is matched in the request cycle we instruct our app to target the methods on our `ErrorController` class. The `via: :all` essentially means match all requests.

### Adjusting our configuration

Even with our new controller and routes set up we still need to turn off the default way Rails will handle errors. You can append the following to your main `application.rb` file.

```ruby
module YourAppName
  class Application < Rails::Application
    config.load_defaults 6.0 # I'm using Rails 6 at the time of this article
    config.exceptions_app = self.routes # Add this line
  end
end
```

The main line we need to add is `config.exceptions_app = self.routes`. This essentially bypasses the internal error logic and tells the application to head to `config/routes.rb` for further instruction.

### Testing things out locally

While the code we have so far should work in the production environment you might want to test it out locally. To do this you need to disable a configuration in `config/environments/development.rb` first.

```ruby
# config/environments/development.rb
Rails.application.configure do
  # Show full error reports.
  config.consider_all_requests_local = false
end
```

Look for the line `config.consider_all_requests_local = true` and swap that to `false` temporarily. At this point you should restart your server (`rails server`) and proceed to some unknown URL on your app. I went to `localhost:3000/asdf` for example.

You should now see the corresponding error view templates in your browser instead of those found in the `public` folder. We can now use our app's styling (Tailwind CSS in my case) to edit and adjust the views within `app/views/errors`.

### Success!

Now that you have custom error templates you can proceed to style those to match the design of your application in a much more efficient way. This took a little set up and can be extended much further but I hope you found it useful.