rescue_from ActionController::RoutingError doesn't work
The ActionController::RoutingError
is raised when Rails tries to match the request with a route. This happens before Rails even initializes a controller - thus your ApplicationController never has a chance to rescue the exception.
Instead the Rails default exceptions_app
kicks in - note that this is an app in the Rack sense - it takes a ENV hash with a request and returns a response - in this case the static /public/404.html
file.
What you can do is have your Rails app handle rendering the error pages dynamically instead:
# config/application.rb
config.exceptions_app = self.routes # a Rack Application
# config/routes.rb
match "/404", :to => "errors#not_found", :via => :all
match "/500", :to => "errors#internal_server_error", :via => :all
You would then setup a specific controller to handle the error pages - don't do this in your ApplicationController class as you would be adding a not_found
and internal_server_error
method to all your controllers!
class ErrorsController < ActionController::Base
protect_from_forgery with: :null_session
def not_found
render(status: 404)
end
def internal_server_error
render(status: 500)
end
end
Code borrowed from Matt Brictson: Dynamic Rails Error Pages - read it for the full rundown.
How to use RoutingError ActionController::RoutingError
Try:
redirect_to root_path, notice: 'Unknown Route' if !model
Or:
if !model
params[:controller] = 'index'
IndexController.action('index').call(env)
else
...
end
Rails 4 Grape API ActionController::RoutingError
By specifying cascade false
you're saying Grape should be allowed to handle HTTP errors without interference from Rails. Consequently, when an unmatched URI beneath your API's mount point is requested, no ActionController::RoutingError
is generated (this would have been done by Rails) and instead the output from Grape's default "unmatched route" handler is returned verbatim. Somewhat unhelpfully, this handler generates a plain "Not Found" message even when format :json
has been specified, and that is the behaviour you're seeing.
The solution is to provide your own matchers to catch routes other than those specified in your V1
and V2
modules. Try adding this code to API::Base
beneath the three mount
statements:
# Generate a properly formatted 404 error for all unmatched routes except '/'
route :any, '*path' do
error!({ error: 'Not Found',
detail: "No such route '#{request.path}'",
status: '404' },
404)
end
# Generate a properly formatted 404 error for '/'
route :any do
error!({ error: 'Not Found',
detail: "No such route '#{request.path}'",
status: '404' },
404)
end
Naturally you'll want to edit the body of each route
block to suit your needs.
For some reason both blocks seem to be necessary to catch all unmatched routes; this is a limitation of either Grape's matcher syntax or my understanding.
Related Topics
Difference Between Require_Relative and Require in Ruby
Getting Output of System() Calls in Ruby
The Authorization Mechanism You Have Provided Is Not Supported. Please Use Aws4-Hmac-Sha256
Class ≪≪ Self Idiom in Ruby
Ruby, Difference Between Exec, System and %X() or Backticks
How to Change Default Timezone For Active Record in Rails
Can't Install Ruby Under Lion With Rvm - Gcc Issues
Cannot Load Such File - Zlib Even After Using Rvm Pkg Install Zlib
Is Ruby Pass by Reference or by Value
Why Do Ruby Setters Need "Self." Qualification Within the Class
How to Dynamically Create a Local Variable
Understanding the Rails Authenticity Token
How to Understand Nil Vs. Empty Vs. Blank in Ruby
Difference Between "And" and && in Ruby
Installed Ruby 1.9.3 With Rvm But Command Line Doesn't Show Ruby -V
Ruby 1.9: How to Properly Upcase & Downcase Multibyte Strings