Related to HowtoConfigureTheErrorPageForYourRailsApp.
Some errors can occur before any controller is loaded. In those cases, nothing defined in ApplicationController will help, since the controller isn’t around to deal with the exception. To deal with this you can redefine rescue_action_in_public in ActionController::Base in a separate file and pull it in through /config/environment.rb.
/config/environment.rb
# Include your app's configuration here:
require 'error_handler_basic' # defines AC::Base#rescue_action_in_public
/lib/error_handler_basic.rb
class ActionController::Base
def rescue_action_in_public(exception)
render :text => <<TOKEN
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
...
<!-- #{exception} --></body></html>
TOKEN
end
end
The above advice doesn’t always help, since in many cases where an error happens too early to be handled by your controller’s rescue_action_* method, it will also be too early to be handled by ActionController::Base#rescue_action_in_public. An example of such an error is if an error occurs while recreating the session object. Rails doesn’t seem to provide any clean way to handle these errors, they just result in an exception escaping the Dispatcher.dispatch method, which is handled in a different way depending what web server you’re running under. I override the Dispatcher.dispatch method with a version which has an extra level of error handling to catch more errors and handle them in a web-server independent way. Add this to your environment.rb, and modify to your taste:
class << Dispatcher
def dispatch(cgi = CGI.new,
session_options = ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS)
begin
request, response =
ActionController::CgiRequest.new(cgi, session_options),
ActionController::CgiResponse.new(cgi)
prepare_application
ActionController::Routing::Routes.recognize!(request).process(request, response).out
rescue Object => exception
begin
ActionController::Base.process_with_exception(request, response, exception).out
rescue
# The rescue action above failed also, probably for the same reason
# the original action failed. Do something simple which is unlikely
# to fail. You might want to redirect to a static page instead of this.
e = exception
cgi.header("type" => "text/html")
cgi.out('cookie' => '') do
<<-RESPONSE
<html>
<head><title>Application Error</title></head>
<body>
<h1>Application Error</h1>
<b><pre>#{e.class}: #{e.message}</pre></b>
<pre>#{e.backtrace.join("\n")}</pre>
</body>
</html>
RESPONSE
end
end
ensure
reset_application
end
end
end
Can this be used to redirect to a controller action?