Well, I’ve got good news and I’ve got bad news. As of Rails 3.0.1, using rescue_from in your ApplicationController to recover from a routing error is broken! That’s the bad news.
The good news is I have a solution that will keep you in unison with the Rails Core Team. The Rails team has promised a fix some time in Rails 3.1. Until then, I’ve got readers and I’ve got customers and I shudder at the thought of showing them a generic error page.
The Situation
It’s bad enough an error has occurred in the first place. At that point I want to take control of the situation and rescue my audience from a bad experience back to enjoyment!
Previously in Rails 2.3.8 and below you could handle routing errors elegantly using rescue_from ActionController::RoutingError:
However, things are a little different in Rails 3. The reality is, as of Rails 3.0.1, ApplicationController can’t catch ActionController::RoutingError and thus, we cannot take advantage of rescue_from like we used to.
Now, for those of you who don’t know, I’m a realist. So, I’m not expecting the Rails team to spring a solution overnight.
Personally, I’m going to wait for the Official fix from the Rails Core Team. In the meantime, I need a simple, no side effects solution that I can use right now!
Simple Solution
This is one of those times when it’s great to be a developer. There is nothing we can’t solve with a little elbow grease and ingenuity.
Expanding on the suggestion given by the Rails core team, here’s the solution I use to handle routing errors in Rails 3.0:
config/routes.rb
This code should go to the end of your routes.rb file. That way it will be given the least priority and therefore, act as a wildcard catchall for all those rogue url resources.
NOTE: The “a” is actually a parameter in the Rails 3 Route Globbing technique. For example, if your url was /this-url-does-not-exist, then params[:a] equals “/this-url-does-not-exist”. So be as creative as you’d like handling that rogue route.
app/controllers/errors_controller.rb
Here, I handle my routing errors. I leverage previous 404 handling code from my original ApplicationController mentioned above. So, my errors_controller.rb looks like this:
However, feel free to modify to fit your individual needs. Everyone’s situation will be slightly different. For example, if you’re not going to reuse your 404 error handling logic, then here’s the full ErrorsController without inheritance:
I’m big on keeping things simple. I believe solutions should be simple without being simplistic. Like I said earlier, I look forward to an Official solution from the Rails Core Team. Until then, this gets the job done!
Well, I encourage you to dig into Rails 3 and have a little fun. And if you have another solution, post here so we can discuss. Until next time Beloved, take care!