Rescuing a RoutingError in Rails - ruby-on-rails

So, I followed José Valim's blogpost, adding
config.exceptions_app = self.routes
to my application.rb for routing HTTP errors to my own controller.
Everything works just as it's supposed to, my custom error pages work and such, but it throws an ActionController::RoutingErrorthough, which gets logged as FATAL. Is there anyway to get around that FATALmessage? I've been trying to rescue from the error both in the application controller and in my error controller, but to no avail.
2012-06-27 12:19:33.908 [FATAL] [127.0.0.1]
ActionController::RoutingError (No route matches [GET] "/3489423u4023ho")

Did you add a route like match "/404", :to => "errors#not_found"?
Are you using the production mode, or the development mode?
You won’t be able to see your custom exceptions in development unless you set config.consider_all_requests_local to false in your config/environments/development.rb. The reason is, if the request is considered local, Rails will always favor to show the debug exceptions page;

Related

Testing Rails 404 and 500 JSON reponse

I am building a JSON backend API with Rails, and I can't seem to figure this out: How can one test using RSpec the Rails default error responses? For example, for a generic 404 request, I currently have the following request spec:
require 'rails_helper'
RSpec.describe '404 errors' do
let(:json) { JSON.parse(response.body) }
before { get '/noexistent', headers: headers }
# examples
end
Rails, however, refuses to render the 404 response that it would normally yield, instead simply raising:
ActionController::RoutingError:
  No route matches [GET] "/404"
I've tried removing config.consider_all_request_local = true from config/environments/test.rb, with no results.
Note that I've seen this question (it's where I got the idea for consider_all_requests_local), but it applies to development, not testing.
EDIT: I am using config.exceptions_app = self.routes to redirect errors to an ErrorsController. This works fine in development or production, but not while testing. When testing, I still get the above error. Any ideas?
It turns out the answer was rather simple. I had to change this line in config/environments/test.rb:
# Raise exceptions instead of rendering exception templates.
config.action_dispatch.show_exceptions = false
to:
# Do not raise exceptions instead of rendering exception templates.
config.action_dispatch.show_exceptions = true

Rails error routing issue (blank page)

having a weird issue with Rails (3.2.15)
I messed around with nicer error pages, but as that was suppressing ALL errors at one point I needed to revert so I can see errors in the log files.
I had:
installed gem: 'exception_notification'
added initialisation code for that in the relevant environment file (config.middleware...)
added routes to catch errors 'get '/500', :to => 'errors#server_error' ', same for 404/422
added rescue statements in application controller "rescue_from Exception, with: lambda { |exception| render_error 500, exception }" etc, same for 404 and render method to render custom pages
Now, I didn't want any of that any more as stated, so I have removed all of the above, ran bundle install, etc. and deployed to my staging environment.
However, NOW I get blank pages on any errors (500 or 404), I don't see that standard rails 'Something went wrong page' at all, (though it is still in /public)
I don't understand why I'm not back at the default error handling, I have no 'rescue' statements anywhere, and no routes that mess with errors.
The log file on 500 shows the full error that occurs and then just:
rendered [page I was trying to see] within layouts/application (50.4ms)
"Completed 500 Internal Server Error in 184.9ms"
[error details]
Why am I not getting my default Rails error behaviour, I'm not sure what I'm missing here??
Any suggestions greatly appreciated!!
turned out I had forgotten to remove this line in config/application.rb :
config.exceptions_app = self.routes
since I removed any routes to do with errors it was therefore showing blank pages.
d'oh

How do I prevent unwanted routing errors in production

ActionController::RoutingError (No route matches [GET] "/google83362a7a0f381ff0.html"):
I see the above logs in production, how should I prevent it.
If user mistypes a URL, how should I re-direct to a common error page
You can redirect the user to the desire page you want if no route matchs
Write down the following code at the bottom of your routes.rb file
In /config/routes.rb
#If no route matches
match ":url" => "application#redirect_user", :constraints => { :url => /.*/ }
Then redirect the user to the error page in the application_controller.rb file
*In /app/controllers/application_controller.rb*
def redirect_user
redirect_to '/404'
end
You don't need to trigger a controller to do that.
Just add this as the last rule in routes.rb:
match '*path', via: :all, to: redirect('/404')
Rails does this automatically when application running in production mode.When uploading application to live server, Rails takes care of handling those exceptions and rendering the correct error pages with the correct header status.You can directly find the files inside public folder.
Whenever you set up your Rails application on a live server, you give the site root as the /public folder in your application. Then, whenever a request is made to that server address, Web server first looks in that public folder and tries to serve a static asset (this is a configurable option in config/environment.rb). If it can't find the requested page, then the request is forwarded through the Ruby stack.
When in production mode, if Rails encounters an error that isn't handled, it throws the error to the stack, which then tells Web server to render an appropriate error.
Here are some common errors that you'll see in development mode and what they render in production mode:
ActiveRecord::RecordNotFound => 404 (page not found)
nil.method => 500 (server error) unless you turn off whiny nils
ActionController::RoutingError => 404 (page not found)

How to override Rails 3.1 "Routing Error" when using engines with glob routes?

I'm converting a legacy app to Rails 3.1. The new app uses an engine that provides a glob route:
# myengine/config/routes.rb
Rails.application.routes.draw do
match 'foo/bar/*path' => 'myengine/foobar#index', :format => false
end
The legacy app used a final catchall wildcard route to provide custom handling (rather than the familiar Rails "Routing Error" page) for otherwise unmatched routes:
# myapp/config/routes.rb
Myapp::application.routes.draw do
# ...
match '*path' => 'failures#index', :format => false
end
Somehow this catchall route is interfering with the engine's route. If I comment out the app's catchall route, the engine's route works fine. But if I leave it in the engine route is never matched and the app's catchall route to failures#index is used instead:
Started GET "/foo/bar//projects/x/vol1/prod22/9907042031/9907042031.aff/ImageProperties.xml" for 10.71.1.136 at 2011-08-02 15:46:48 -0700
Processing by FailuresController#index as JS
Parameters: {"path"=>"foo/bar/projects/x/vol1/prod22/9907042031/9907042031.aff/ImageProperties.xml"}
Rendered failures/index.html.erb within layouts/application (0.0ms)
Completed 200 OK in 47ms (Views: 46.9ms)
How would one override the default Rails 3.1 routing error handler without breaking engine routes?
The right way to handle this used to be rescue_from and a custom error handler, rather than with an engines-hostile catchall route. However, custom error handlers are no longer supported in Rails 3.1 and this likely won't be fixed until Rails 3.2, if ever. If you need custom error handling and you use engines with routes, the vidibus-routing_error gem provides a workaround.
Another option is to put your custom error handler into a Rack endpoint at the bottom of your stack.

Why would I have to restart rails every time to test a 404.html page here?

I'm trying to work out why when working on a 404 page on a rails app I'm working, the only way to see changes I've made to the html on the page is to physically restart the webserver with a ctrl-C followed by a call to script/server.
As far as I can tell, I can't see anything particularly wrong with the development.rb config file here:
# Settings specified here will take precedence over those in config/environment.rb
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
# since you don't have to restart the webserver when you make code changes.
config.cache_classes = false
# Log error messages when you accidentally call methods on nil.
config.whiny_nils = true
# Show full error reports and disable caching
config.action_controller.consider_all_requests_local = true
config.action_view.debug_rjs = true
config.action_controller.perform_caching = false
# Don't care if the mailer can't send
config.action_mailer.raise_delivery_errors = false
config.action_mailer.perform_deliveries = false
# add rack bug
# config.middleware.use "Rack::Bug"
# this disables the caching for comatose, not the rest of the app
# config.disable_caching = true
config.action_mailer.default_url_options = { :host => "localhost:3000" }
config.gem "thoughtbot-factory_girl",
:lib => "factory_girl",
:source => "http://gems.github.com"
This alone won't display the error pages locally, so in application_controller.rb I've aliased rescue_action_locally to the rescue_action_in_public method, to stop me seeing the stacktrace:
# this method allows you to test 404 and 500 pages locally
alias_method :rescue_action_locally, :rescue_action_in_public
This here shows me the error page once, but then caches it so that future reloads show the state of the html file when the server was loaded.
The log output doesn't show me any weird caching behaviour - it's getting a request for a non-existent resource, not finding anything, then rendering the html page as required:
chrisadams#r220-101-174-100 ~/RailsApps/annoying_app > script/server --debugger
=> Booting Mongrel
=> Rails 2.3.2 application starting on http://0.0.0.0:3000
=> Debugger enabled
=> Call with -d to detach
=> Ctrl-C to shutdown server
SQL (0.2ms) SET SQL_AUTO_IS_NULL=0
Processing ApplicationController#index (for 127.0.0.1 at 2009-12-28 19:23:27) [GET]
ActionController::RoutingError (No route matches "/non-existent-resource" with {:method=>:get}):
Rendering /Users/chrisadams/RailsApps/annoying_app/public/404.html (404 Not Found)
The 404.html is totally static, without any ERB in there at all, and this static html page is what isn't changing between page refreshes.
What am I doing wrong here? This is driving me crazy!
I've noticed that not everything is reloaded on every request, even in development mode. Is your 404.html page completely static, or are you running it through ERB or something?
rescue_from is also becoming the generally preferred means of doing this nowadays.
I'm not sure if this might help you, but one time I accidentally uncommented the lines ENV['RAILS_ENV'] ||= 'production' in environment.rb and my app started in production mode even when I didn't specify the environment.
Could that be the case for you?

Resources