Kyle Boon
Kyle Boon

Reputation: 5231

Redirecting to a 500 page when an AJAX call fails in Ruby on Rails

I'm working with an application built in Ruby on Rails with very poor error handling right now. If a controller method is executed via ajax, and that method results in a 500 (or 404 or any other response) the 500.html page is rendered and returned as the result to the AJAX request. Obviously the javascript doesn't know what to do with that HTML and the web page looks like it's just waiting for a response.

Is there an easy way in rails to render an error.rjs template anytime an error occurs during an AJAX call?

Upvotes: 6

Views: 2431

Answers (4)

Neelesh
Neelesh

Reputation: 1478

You can do like below :

in allpication.js

$(document).ready(function(){
    $(document).ajaxError( function(e, xhr, options){
    if("500" == xhr.status)
    {
       $(location).attr('href','/users/sign_in');
    }
  });
}) 

Its working for me.....

Upvotes: 0

Kyle Boon
Kyle Boon

Reputation: 5231

This was my final solution:

def rescue_action_in_public(exception)
  response_code = response_code_for_rescue(exception)
  status = interpret_status(response_code)
  respond_to do |format|
    format.html { render_optional_error_file response_code}
    format.js { render :update, :status => status  do |page| page.redirect_to(:url => error_page_url(status)) end}
  end
end

This basically forwards to the correct static HTML page no matter if the request was via AJAX or normal GET/POST.

This is NOT used for normal error handling like validation etc. It's only used when something really bad happens - like an unhandled exception.

Upvotes: 1

Christopher Hazlett
Christopher Hazlett

Reputation: 326

I solved a similar problem with authorization. I created a simple authorization controller with this action:

  def unauthorizedxhr
    render :update do |page|
      page.replace_html("notice", :partial=>"unauthorizedxhr")
      page.show("notice")       
    end
  end

Here's the template:

<% if flash[:notice] -%>
    <div id="noticexhr"><%= flash[:notice] %></div>
<% end -%>

When the authorization failed in the controller, I'd redirect to the :controller=>"authorization", :action=>"unauthorizedxhr" after setting the flash[:notice] value. This allowed me to customize the message I sent to the user, and it handled the display of the message through the render :update code above.

You could adapt this to your problem by creating an errors controller, catching any raised errors in your other controllers, then simply redirecting to :controller=>"errors", :action=>"displayxhr" when the call fails. That way, you'll have standardized your error communication mechanism but allowed yourself the ability to customize error messages by each action.

You can still use cpm's idea above, but the error's display will be handled by separate and distinct controller logic. that should make it a little easier to maintain.

Hope that helps. -Chris

Upvotes: 3

cpm
cpm

Reputation: 1533

You can use respond_to inside a controller's rescue_action or rescue_action_in_public method. Consider the following controller:

class DefaultController < ApplicationController

  def index
    raise "FAIL"
  end

  def rescue_action(exception)
    respond_to do |format|
      format.html { render :text => "Rescued HTML" }
      format.js { render :action => "errors" }
    end
  end
end

Upvotes: 3

Related Questions