Page Not Found

Episode #404 by Teacher's Avatar David Kimura

Summary

In this episode, we take a few different approaches in how we display error pages in our Rails application. We'll also look at a few potential problems with each approach that we need to be aware of.
rails error view 12:55

Chapters

  • Introduction (0:00)
  • Consider All Requests Local (0:58)
  • Custom Routing (2:30)
  • Custom Layouts File (3:52)
  • Problems when using Rails to render error pages (4:56)
  • Setting up the views for the Errors controller (6:12)
  • Different approach to minimize risk (8:21)
  • Static pages (9:16)
  • Using a CDN for the styling pages (11:07)
  • Final Thoughts (12:14)

Resources

This episode is sponsored by Honeybadger
Download Source Code

Summary

# Terminal
touch tmp/errors-dev.txt
rails g controller errors not_found unprocessable_entity internal_server_error
cp app/views/layouts/application.html.erb app/views/layouts/errors.html.erb

# config/environments/development.rb
if Rails.root.join("tmp/errors-dev.txt").exist?
  config.consider_all_requests_local = false
else
  config.consider_all_requests_local = true
end

# config/application.rb
config.exceptions_app = self.routes

# config/routes.rb
match "/404", to: "errors#not_found", via: :all
match "/422", to: "errors#unprocessable_entity", via: :all
match "/500", to: "errors#internal_server_error", via: :all

# app/controllers/errors_controller.rb
class ErrorsController < ActionController::Base
  # layout "errors"

  def not_found
  end

  def unprocessable_entity
  end

  def internal_server_error
  end
end

# app/views/layouts/errors.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title>Drifting Ruby</title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
  </head>

  <body class='bg-light'>
    <div class="container d-flex flex-column justify-content-center align-items-center" style="height: 100vh;">
      <%= yield %>
    </div>
  </body>
</html>

# app/views/errors/internal_server_error.html.erb
<%= image_tag "500.png", class: "img-fluid" %>

<p class="lead text-muted">It's not you. Something went wrong on our end.</p>
<%= link_to "Back to home", root_path, class: "btn btn-primary" %>

# app/views/errors/not_found.html.erb
<%= image_tag "404.png", class: "img-fluid" %>

<p class="lead text-muted">
  We're sorry, but the page you were looking for doesn't exist.
</p>
<%= link_to "Back to home", root_path, class: "btn btn-primary" %>

# public/404.html
<!DOCTYPE html>
<html>

<head>
  <title>404 Not Found</title>
  <link href="/bootstrap.min.css" rel="stylesheet">
</head>

<body class="bg-light">
  <div class="container d-flex flex-column justify-content-center align-items-center" style="height: 100vh;">
    <img class="img-fluid" src="/404.png">
    <p class="lead text-muted">We're sorry, but the page you were looking for doesn't exist.</p>
    <a href="/" class="btn btn-primary">Back to Home</a>
  </div>
</body>

</html>

# public/500.html
<!DOCTYPE html>
<html>

<head>
  <title>500 Internal Server Error</title>
  <link href="/bootstrap.min.css" rel="stylesheet">
</head>

<body>
  <div class="container">
    <img src="/500.png" class="img-fluid">
    <p>We're sorry, but something went wrong.</p>
    <a href="/">Back to Home</a>
  </div>
</body>

</html>