27 Apr 2012
rescue_from RoutingError in Rails 3
Rails 3.0 handles routing errors (ActionController::RoutingError) differently than Rails 2.3. The middleware addition means the error is passed to ActionDispatch, instead of ApplicationController. A bit ago, I actually removed the catch-all route at the bottom of routes.rb because I thought the ApplicationController::rescue_from handled any routing errors. Not true. Rails 3.2 doesn't resolved it either.
There is an open GitHub issue for it: "Can no longer rescue_from ActionController::RoutingError". (In fact, it's old enough to be an issue migrated from Lighthouse.) There are several solutions posted inline in the issue's comments. JosÃ© Valim from the Rails core team suggests simply adding the catch-all route back to routes.rb; others suggest overriding ActionDispatch::ShowExceptions::render_exception. All seem focused on rendering the 404 page manually. However, I wanted to make rescue_from work. My solution is the catch-all route and raising the exception manually.
# routes.rb # Any other routes are handled here (as ActionDispatch prevents RoutingError from hitting ApplicationController::rescue_action). match "*path", :to => "application#routing_error"
# application_controller.rb rescue_from ActionController::RoutingError, :with => :render_not_found def routing_error raise ActionController::RoutingError.new(params[:path]) end def render_not_found render :template => "misc/404" end