13

When user clicks a specific item, I use jQuery's post method to update something in the database:

$.post("/posts/" + post_id + "/update_something", 
       { some_param: some_value }, 
       success_handler);

where update_something looks like this:

def update_something
  post = Post.find(params[:id])
  post.update_attributes(:some_field => params[:some_param])
  render :nothing => true
end

The problem is if update_attributes fails, the request still succeeds and success_handler is executed.

How could I cause the request to fail when update_attributes fails such that success_handler won't be executed?

Misha Moroshko
  • 166,356
  • 226
  • 505
  • 746

2 Answers2

28

You can either do render :status => 400 (or some other error code) in Rails, which will trigger the error callback of $.ajax(), or you can render some JSON with an error message:

render :json => { :success => false }

Then in your success_handler function you would:

function success_handler (response) {
    if (response.success) {
        // do stuff
    }
}

Edit:

Oh, and update_attributes returns false when it fails. So you can render your response based on that.

Edit 2 years later:

After a couple years and seeing that this has a few upvotes, I'd highly recommend using the status: 400 method instead of rendering 200. It's what the error handler in AJAX requests are for, and should be used that way.

Calvin
  • 8,697
  • 7
  • 43
  • 51
6

Well, you have to add an error handler, and give it an error to handle. So, in your JavaScript:

$.post( "/posts/" + post_id + "/update_something",
        { some_param : some_value }
      )
  .done( successHandler )
  .fail( errorHandler )      // define errorHandler somewhere, obviously
;

And in Rails:

def update_something
  post    = Post.find params[ :id ]

  success = post.update_attributes :some_field => params[ :some_param ]

  head success ? :ok : :internal_server_error
end

Note: 500 may or may not be the appropriate error code here—choose whichever among the 400s and 500s is appropriate.

Jordan Running
  • 102,619
  • 17
  • 182
  • 182
  • Thanks! I wasn't familiar with jQuery's `success` and `error` methods. Tried to look for docs but no success. Could you provide a pointer please? – Misha Moroshko Feb 16 '12 at 05:28
  • 1
    +1 You could also just return a success/fail header. Your last line in Rails would look like `head success ? :ok : :internal_server_error`, where `head :ok` will return status 200, and `head :internal_server_error` will return status 500. – Substantial Feb 16 '12 at 05:31
  • Misha: `post`, `get`, and `ajax` return a jqXHR object which is (poorly) [documented here](http://api.jquery.com/jQuery.ajax/#jqXHR). Reading that closer I noticed that `error` and `success` are deprecated and now you should use [Deferred](http://api.jquery.com/category/deferred-object/)'s `done` and `fail`. I've updated my code to reflect this, as well as incorporate @gg_s's advice, which is a good tip. – Jordan Running Feb 16 '12 at 05:38