h2. Errors and Environments Rails has the concept of [[Environments|environment]] to represent the stages of an application's lifecycle (test, development, and production are the defaults). Errors are handled as appropriate for the deployment target. The *test and development environments provide developer-relevant error handling whereas the production environment returns an error page with HTTP status 500* (Application Error). "ActionController::Rescue":http://rails.rubyonrails.com/classes/ActionController/Rescue.html is the module responsible for error handling. h2. Error Pages in your Application It is possible to configure the error page returned by your Rails application, in either a global or controller specfifc way. By combining these approaches you can have a global default and override it in individual controllers. h3. Globally Navigate to your apps /controller directory and edit application.rb:
def rescue_action_in_public(exception)
render_text "There was a global error processing your request.
"
end
def local_request?
false
end
h3. Controller specific
Edit the controller you would like to have respond to errors differently to include it own implementation of rescue_action_in_public:
def rescue_action_in_public(exception)
render_text "There was a controller specfic error processing your request.
"
end
These examples show simple text rendering for error pages, but there are many other possibilities(such as email, logging, redirects, etc.) in the @rescue_action_in_public@ method(see HowtoSendEmailWhenRailsThrowsAnException, for example).
h3. Pre-controller
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 seperate 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
end
end
h3. Pre-Pre-controller
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 independant 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
Application Error
Application Error
#{e.class}: #{e.message}
#{e.backtrace.join("\n")}
RESPONSE
end
end
ensure
reset_application
end
end
end
h2. Notes
h3. Set @consider_all_requests_local@ to @false@
When working on this functionality locally you will need to make sure that your @/config/environments/development.rb@ has the following set in it:
ActionController::Base.consider_all_requests_local = false
h3. Request the real IP
Also, despite defining @local_request?@ as above, you may have to change the address used to make the request. Neither @localhost@, not @127.0.0.1@ work, instead use the actual IP address of your machine.