This project is archived and is in readonly mode.
Can no longer rescue_from ActionController::RoutingError
Reported by Luigi Montanez | April 20th, 2010 @ 04:50 PM | in 3.1
In Rails 2.3.x, one is able to stick this in ApplicationController to present the user with a custom 404 screen:
rescue_from(ActionController::RoutingError) { render :text => 'This is a custom 404.' }
Now in Rails 3, because routing is done as middleware (ActionDispatch), it seems that the ActionController::RoutingError that gets thrown by ActionDispatch no longer can be caught from ApplicationController -- the error is already thrown and ActionDispatch renders /templates/rescues/routing_error.erb before the controller can rescue_from the error.
Comments and changes to this ticket
-
Ben Marini April 27th, 2010 @ 03:38 AM
I verified this with a freshly generated rails app from the master branch. I haven't investigated too far, but at this point the best way I can see to do this in rails 3 is to subclass and swap out the
ActionDispatch::ShowExceptions
middleware. Or add a route that matches anything...is there a better way? -
Jean May 27th, 2010 @ 09:09 PM
- Tag changed from rails3 routes, 3.0.0.beta3 to rails3 routes, 3.0.0.beta3, rails3, rescue, routes, routingerror
I am also hitting this problem, but my understanding of the internals of rails3 is very limited atm ...
Couldn't we define the rescue handling as an option to the route ? (thus in route.rb)
-
Neeraj Singh May 28th, 2010 @ 04:35 AM
Put following code in an initializer in a rails3 app.
module ActionDispatch class ShowExceptions def render_exception(env, exception) if exception.kind_of? ActionController::RoutingError render(500, 'it was routing error') else render(500, "some other error") end end end end
There might be a better way but it works in my quick test.
-
José Valim July 13th, 2010 @ 08:58 PM
- Milestone set to 3.1
- Assigned user set to José Valim
- Importance changed from to Low
The best way to handle a missing route in Rails 3 is by adding the following line at the end of your router:
match "*", :to => "home#routing_error"
And add the routing_error action. We will be working on a better solution, but it is targeted for 3.1.
-
Hubert Łępicki July 25th, 2010 @ 05:47 PM
José, are you sure that your solution actually works? I think it's not working as you can't simply say match "*" to match everything in Rails 3 so far?
-
Hubert Łępicki July 25th, 2010 @ 05:52 PM
I mean, you have to do it like this:
match '/:anything', :to => "home#routing_error", :constraints => { :anything => /.*/ }
-
Hubert Łępicki July 26th, 2010 @ 08:14 AM
I was giving it a bit more thought since yesterday. The solution with match "/:anything" is also not perfect for some people, as it'll override all routes from plugins/engines. I now think that best solution is to use custom rack middleware for handling 404 pages in Rails.
-
Matthew Gibbons August 13th, 2010 @ 03:14 PM
The approach that I have adopted to solve this (for now) is to make a call back into the application (from ActionDispatch::ShowExcpetions#render_exception), specifically to a controller that is there for the purpose of rendering an error page. This has all the benefits of using the layout and styling of the host application. However, if a second exception occurs whilst handling the exception in this way, the original method is called, and the default is rendered.
It is better explained here: http://accuser.cc/posts/1-rails-3-0-exception-handling
For those who would rather copy and paste than read the above... ;)
-
Andre Pankratz August 17th, 2010 @ 06:11 PM
Here is a gem that may solve this issue: http://github.com/vidibus/vidibus-routing_error
-
gucki September 22nd, 2010 @ 02:34 PM
The easiest way for me was to add this very last route:
match ''=> lambda { |env| raise ActionController::RoutingError, env["PATH_INFO"] }
-
gucki September 22nd, 2010 @ 02:51 PM
Please ignore my previous comment, it does not work that way. Seems rails had some routes cached, so it seemed to work initially.
-
Tian Davis November 12th, 2010 @ 12:25 AM
Personally, I'm waiting for an Official solution from the Rails Core Team. Until then I need a simple, no side effect solution for catching rogue routes. For now, my solution is an elaboration on José Valim's recommendation:
http://techoctave.com/c7/posts/36-rails-3-0-rescue-from-routing-err...With this approach, you'll be in unison with the Rails Core Team. Moreover, I incorporate Rails 3 Route Globbing, so you get the added benefit of knowing exactly which rogue route was entered. As a result, you're free to handle routing errors as creatively as you'd like.
-
avocade (at gmail) December 19th, 2010 @ 02:50 AM
Issue for more than just rescuing from routing errors, CanCan::AccessDenied too:
http://www.tonyamoyal.com/2010/07/28/rails-authentication-with-devi...
-
Kevin Watt March 18th, 2011 @ 03:40 PM
This is a huge bug and I feel it's priority should be raised.
It's not acceptable for a broken link in a production app to result in a blank screen, this is why we make 404 handlers. But once the request is dispatched to rails it seems to be rails job to render the 404 page, which it can't do because of this bug.
-
Kevin Watt March 18th, 2011 @ 04:56 PM
Just to add,
match '/:anything', :to => "home#routing_error", :constraints => { :anything => /./ } or
match "", :to => "home#routing_error"Don't seem to work when the controller exists but the action doesn't. Exception log still just shows "AbstractController::ActionNotFound (The action 'rejsasdf' could not be found for HomeController):" and a blank page is rendered.
-
Andrew White March 19th, 2011 @ 06:48 AM
Are you using :action as the dynamic segment name? If so Rails will try to find the action in the controller. The following path works for me:
match '*path', :to => 'errors#not_found'
This won't catch a missing root path - but I'm guessing you're website is there.
-
Andre Pankratz March 19th, 2011 @ 08:36 AM
- Assigned user cleared.
A catch-all route at the end of your routes my seem like a simple fix, but it has a major drawback:
If your application relies on engines that extend your app with their own routes, things will break because those routes will never get fired!I've published a gem that solves the routing error. It basically catches the exception on Rack-level and re-raises it on application-level: https://github.com/vidibus/vidibus-routing_error
-
Andre Pankratz March 19th, 2011 @ 08:37 AM
- Assigned user set to José Valim
Oops, I removed José. Sorry.
-
Kevin Watt March 19th, 2011 @ 02:36 PM
I am using non-restful routes, which is perhaps why the catch-all doesn't work for me
match ':controller(/:action(/:id))', :constraints => {:id => /.*/}
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
<h2 style="font-size: 14px">Tickets have moved to Github</h2>
The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>
People watching this ticket
- avocade (at gmail)
- Andre Pankratz
- Andrew White
- brewster1134
- Chris Kottom
- Christos Trochalakis
- Cyrille
- gucki
- Jeremy Kemper
- José Valim
- Kevin Watt
- Luigi Montanez
- Manfred Stienstra
- Martin Stabenfeldt
- Michał Łomnicki
- Michel Pigassou
- Neeraj Singh
- Nirmit Patel
- Piotr Sarnacki
- Ryan Bigg
- Ryan Wallace
- Simon
- Stephan
- Tomasz
- Tsutomu Kuroda
- xds2000
- Łukasz Strzałkowski
Referenced by
- 4445 In production mode, the stock 404.html and 500.html don't get rendered Then, navigate to http://localhost:3000/junk. I expect th...
- 6275 AbstractController::ActionNotFound should be rescued This is essentially a duplicate of #4444. You've almost g...