Как сбой запроса Ajax в Rails?

Когда пользователь нажимает на определенный элемент, я использую метод jQuery post для обновления чего-либо в базе данных:

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

где update_something выглядит следующим образом:

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

Проблема в том, что если update_attributes не работает, запрос все еще выполняется и success_handler выполняется.

Как я могу заставить запрос терпеть неудачу, если update_attributes не работает, так что success_handler не будет выполняться?

Ответ 1

Вы можете либо сделать render :status => 400 (или какой-либо другой код ошибки) в Rails, который вызовет обратный вызов error $.ajax(), либо вы можете отобразить сообщение JSON с сообщением об ошибке:

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

Затем в вашей функции success_handler вы должны:

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

Edit:

О, а update_attributes возвращает false, когда он терпит неудачу. Таким образом, вы можете сделать свой ответ на основе этого.

Редактировать 2 года спустя:

Через пару лет и, увидев, что у этого есть несколько upvotes, я настоятельно рекомендую использовать метод status: 400 вместо рендеринга 200. Это то, что обрабатывает обработчик error в запросах AJAX и должен использоваться таким образом.

Ответ 2

Ну, вы должны добавить обработчик ошибок и дать ему ошибку для обработки. Итак, в вашем JavaScript:

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

И в 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

Примечание: 500 может быть или не быть соответствующим кодом ошибки здесь - выберите, что бы ни было 400s и 500s.