It's a little known fact that you can easily substitute the default Rails HTML error pages with something more pleasant. You may have noticed the
500.html files that are generated with every new Rails project and wondered if there's a clean way to style them like the rest of your application. There is, and it's surprisingly simple.
The default status code templates are served by a Rack exception application. You can override this to be any Rack compatible app, including your applications router:
# config/application.rb config.exceptions_app = self.routes
This will route any exceptions caught to your router Rack app. Now you'll want to define routes to display those errors yourself:
# config/routes.rb get "/404", :to => "errors#not_found" get "/422", :to => "errors#unacceptable" get "/500", :to => "errors#internal_error"
This will route each error code to it's respective action in
ErrorsController. Now we'll want to define those actions:
class ErrorsController < ApplicationController def not_found render :status => 404 end def unacceptable render :status => 422 end def internal_error render :status => 500 end end
We tell each action to render the appropriate HTTP status code related to the error that's been caught. All that's left to do now is create the view related to each action and you're done:
# app/views/errors/not_found.html.haml %h1 404 - Not Found
When we visit
404 - Not Found view should render as expected. Now you can style your error pages without having to duplicate any styles into the public directory of your application.
Optimising Our Errors Controller
Let's start by changing our routes:
# config/routes.rb %w( 404 422 500 ).each do |code| get code, :to => "errors#show", :code => code end
Now we need to ensure our
ErrorsController uses the
code parameter we're passing through:
class ErrorsController < ApplicationController def show render status_code.to_s, :status => status_code end protected def status_code params[:code] || 500 end end
To clean things up even more I've created a
status_code method which defaults to a
500, this will protect any cases where we might not have the code present in the
The final alteration as part of this refactor is to rename our view files to use status codes rather than our previous naming scheme:
# app/views/errors/404.html.haml %h1 404 - Not Found
And that's it. We've now got a reusable errors controller which is flexible enough for us to add new error types to in the future (by adding a new code to the error codes array and a corresponding view file).
It's worth noting that you shouldn't be doing anything fancy in these views. The reason these pages are rendered is because something has most likely gone wrong in your application, so you should probably stray away from making calls to the database or performing more complex actions.