This sample is just a slight modification of this post 'Handling AJAX errors and displaying friendly error messages to users'. Basically I wanted to maintain the existing rails error handling for non-ajax pages and then have good handling for errors in both development and production mode; i.e. get errors in the browser when in development mode and show a nice message when in production mode.
Modify /app/controllers/application.rb; add the rescue_from macro and the handler_exception method
class ApplicationController < ActionController::Base | |
helper :all # include all helpers, all the time | |
# ... | |
rescue_from Exception, :with => :handler_exception | |
# ... | |
def handler_exception(exception) | |
if request.xhr? then | |
message = "Error: #{exception.class.to_s}" | |
message += " in #{request.parameters['controller'].camelize}Controller" if request.parameters['controller'] | |
message += "##{request.parameters['action']}" if request.parameters['action'] | |
message += "\n#{exception.clean_message}" | |
message += "\n\nFull Trace:\n#{exception.clean_backtrace.join("\n")}" | |
message += "\n\nRequest:\n#{params.inspect.gsub(',', ",\n")}" | |
# log the error | |
logger.fatal "#{message}" | |
message = "ajaxError, check the server logs for details" unless local_request? | |
respond_to do |wants| | |
wants.js { render :text => message, :status => :internal_server_error } | |
end | |
else | |
# not an ajax request, use the default handling; | |
# actionpack-2.2.2/lib/action_controller/rescue.rb | |
rescue_action_without_handler(exception) | |
end | |
return # don't risk DoubleRenderError | |
end | |
end |
Then add a global javascript method for presenting the errors; most likely in application.js
function defaultAjaxErrorHandler(result, isAjaxError) { | |
// do stuff, hide spinner etc... | |
var defaultAjaxError = "Your friendly error message"; | |
var errorToken = "Error:"; | |
if(!isUndefinedOrNull(result) && !isUndefinedOrNull(result.responseText)) { | |
if(result.responseText.startsWith(errorToken)) { | |
// localhost | |
var x = (result.responseText.length > 350) ? 350 : result.responseText.length; | |
alert(result.responseText.substring(0, x) + "...\n\n - Check firebug console for more info.\n - This message for localhost only."); | |
} | |
else { | |
// production error | |
alert(defaultAjaxError); | |
} | |
} | |
else { | |
// production error | |
alert(defaultAjaxError); | |
} | |
} | |
function isUndefinedOrNull(x) { | |
var u; // undefined var | |
if(x === u) { // similar to [typeof x == "undefined"] | |
return true; | |
} | |
// else | |
return x === null; | |
} |
Then a sample usage, jquery making an ajax post to a rails controller action
$j.ajax({ | |
type: "POST", | |
url: "/some_controller/some_action", | |
data: { | |
first_name: $j("#first_name").val(), | |
last_name: $j("#last_name").val(), | |
}, | |
success: function(data, textStatus) { | |
// do what you like | |
}, | |
error: function(result) { defaultAjaxErrorHandler(result, true); } | |
}); |
in development mode the error message is returned in an easier to read view in the firebug console and an alert message is presented that has a truncated version of the error

in production mode just a friendly error message.

Resources
- Handling AJAX errors and displaying friendly error messages to users
- Rails source code rescue.rb
- Rails views source on your install lib/action_controller/templates/rescues
- jquery ajax
No comments:
Post a Comment