Rails 3.2 error routing error. Error ID conflicts with another object ID
We just upgraded our application to Rails 3.2.2 and now we have a routing issue for error handling.
In the José Valim blog post , we added the following: config.exceptions_app = self.routes
in config / application.rb match "/404", :to => "errors#not_found"
in config / routes.rb
(and the corresponding controller / views).
The problem is what we need ourdomain.com/id
to display the index page for the product category id
.
So now it ourdomain.com/404
shows our 404 page when it should be showing our category listing page for a category id
from 404.
How can we get around this?
Is there a way for the app to add each bug with error_
before it was evaluated with routes
?
Or maybe somehow set config.exceptions_app
to reference the namespace in the file routes
?
Or can I create a second set of routes and install config.exceptions_app = self.second_set_of_routes
?
Thank!
source to share
There is one solution I have found so far:
# application_controller.rb
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
rescue_action_in_public
is the method that Rails calls to handle most errors. local_request?
the method tells Rails to stop sucking if it's a local request
# config/routes.rb
match '*path', controller: 'application', action: 'rescue_404' \
unless ::ActionController::Base.consider_all_requests_local
It just says that it cannot find any other route to handle the request (i.e. *path
), it must invoke an action rescue_404
on the application controller (first method above).
EDIT
This version worked well for me! Try adding toapplication.rb
# 404 catch all route
config.after_initialize do |app|
app.routes.append{ match '*a', to: 'application#render_not_found' } \
unless config.consider_all_requests_local
end
See: https://github.com/rails/rails/issues/671#issuecomment-1780159
source to share
We had the same problem - error codes colliding with resource IDs at the root level (for example collisions between ourdomain.com/:resource_id
and ourdomain.com/404
).
We've modified José Valim's solution to add a route restriction that only applies when handling an exception:
# Are we handling an exception?
class ExceptionAppConstraint
def self.matches?(request)
request.env["action_dispatch.exception"].present?
end
end
MyApp::Application.routes.draw do
# These routes are only considered when there is an exception
constraints(ExceptionAppConstraint) do
match "/404", :to => "errors#not_found"
match "/500", :to => "errors#internal_server_error"
# Any other status code
match '*a', :to => "errors#unknown"
end
...
# other routes, including 'match "/:resource_id"'
end
(We just stumbled upon this solution last night, so it didn't have a lot of recording time. We're using Rails 3.2.8)
source to share
This route seems to be hardcoded with show_exceptions method ( see source )
Sorry, but I don't think of how to do this, other than changing line 45 on the source above:
env["PATH_INFO"] = "/error_#{status}"
(which, of course, no solution at all).
It doesn't hurt to ask: if you think it would be nice if your own error controller was so easy to implement and desperate to have, than it wouldn't be even more "RESTful" if your route were your home. com / product /: id
source to share