I spent a couple of hours trying to figure out how to handle 404 and 500 errors in Rails. This is not simple and actually really annoying. Hopefully future versions clean this up because right now it sucks pretty badly. Anyways, I found a page on the wiki and some other blogs, but the issue was that they wouldn’t handle all the cases. So, here’s the solution:
1. Edit your app/controllers/application.rb file and add these three methods:
def rescue_404 rescue_action_in_public CustomNotFoundError.new end def rescue_action_in_public(exception) case exception when CustomNotFoundError, ::ActionController::UnknownAction then #render_with_layout "shared/error404", 404, "standard" render :template => "shared/error404", :layout => "standard", :status => "404" else @message = exception render :template => "shared/error", :layout => "standard", :status => "500" end end def local_request? return false end
The first method will be explained in the next step. The second method is the method that Rails calls to handle most errors. This method will not capture a certain class of errors where neither the controller nor the action requested exist. The third method tells rails to stop sucking. Normally Rails handles requests made to localhost or 127.0.0.1 differently than all others. This might be for debugging purposes, but it sucks when testing error handling.
2. Edit config/routes.rb and add this line TO THE END OF THE FILE:
map.connect '*path', :controller => 'application', :action => 'rescue_404' unless ::ActionController::Base.consider_all_requests_local
This tells Rails that if it can’t find any other route to handle the request (i.e. the *path) it should call the rescue_404 action on the application controller (the first method above).
3. Edit config/environments/development.rb and add this line:
ActionController::Base.consider_all_requests_local = false
This additionally tells Rails to stop sucking and stop handling requests to localhost and 127.0.0.1 differently.
Anyways, happy coding.