Подтвердить что ты не робот

Jquery не вызывает метод успеха на $.ajax для rails standard REST DELETE ответ

Может быть, такая проблема не нова, но я не нашел ничего подобного. У меня есть такой код jQuery:

$.ajax({ 
  url : ('/people/'+id), 
  type : 'DELETE', 
  dataType : 'json', 
  success : function(e) {
    table.getItems(currentPage);
  }
});

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

def destroy
    @person = Person.find(params[:id])
    @person.destroy

    respond_to do |format|
      format.html { redirect_to(people_url) }
      format.json  { render :json => @person, :status => :ok }
    end
end

Это работает.

Но когда я использую следующее (генерируемое стандартом), обратный вызов success не вызывается:

def destroy
    @person = Person.find(params[:id])
    @person.destroy

    respond_to do |format|
      format.html { redirect_to(people_url) }
      format.json  { head :ok }
    end
end

Протестировано под rails 3.0.3, jQuery 1.4.2 и Firefox 3.6.13.
Firebug говорит, что этот запрос запущен и в обоих случаях возвращает 200 OK, элемент также удаляется в обоих случаях. Но во втором случае обратный вызов не вызывается.

Есть ли существенная разница в REST, и есть ли способ использовать jQuery с помощью контроллера леса?

4b9b3361

Ответ 1

Я несколько раз сталкивался с этим, и ответ обманчиво прост.

Вы используете dataType : 'json' в вызове $.ajax, поэтому jQuery ожидает ответ JSON. С помощью head :ok Rails возвращает ответ, содержащий одно пробел (http://github.com/rails/rails/issues/1742), который не принят jQuery как действительный JSON.

Итак, если вы действительно ожидаете получить либо ошибку, либо пустой заголовок 200 OK, просто установите dataType : 'html' в свой запрос и он должен работать (если вы не установите dataType, jQuery попытается угадать, что тип основано на заголовках ответов и т.д., и все еще может угадать json, и в этом случае у вас все еще будет эта проблема). Если вы действительно ожидаете вернуть JSON, вместо того, чтобы использовать head :ok сделать что-то действительное с JSON (см. Комментарии) или просто использовать head :no_content, как предложено @Waseem

Ответ 2

GearHead корректен, за исключением того, что парсер jQuery на самом деле достаточно умен, чтобы обрабатывать пустой ответ строки как нулевой, а не пытаться его проанализировать.

Однако, если у вас есть вызовы, которые иногда получат json и иногда получают ответ head, и у вас нет доступа к серверу или вы не хотите изменять все ваши вызовы head, вы можете сделать это альтернативное решение

Проблема заключается в том, что Rails отправляет одиночное пространство как пустой ответ, когда вы используете head (см. здесь: Как вернуть по-настоящему пустое тело в rails? ie content-length 0)

Соответствующие части функции parseJSON jQuery выглядят так на момент написания этой статьи:

parseJSON: function( data ) {
    if ( typeof data !== "string" || !data ) {
        return null;
    }

    // Make sure leading/trailing whitespace is removed (IE can't handle it)
    data = jQuery.trim( data );

    // Attempt to parse using the native JSON parser first
    if ( window.JSON && window.JSON.parse ) {
        return window.JSON.parse( data );
    }

Как вы можете видеть, jQuery проверяет, являются ли данные пустой строкой перед ее обрезкой. Затем он пытается JSON.parse(""), который вы видите в своей консоли, приводит к ошибке, вызывая обратный вызов ошибки ajax с помощью инструкции catch.

Существует простое исправление. jQuery позволяет использовать преобразователи, когда запрашивается один тип данных, и возвращается другой. См. Здесь для более подробной информации: http://api.jquery.com/extending-ajax/

Поскольку рельсы head ответ отображается как текст, вы можете просто определить текст в json конвертер, который будет обрезать ответ до попытки его разбора. Просто добавьте этот фрагмент:

// deal with rails ' ' empty response
jQuery.ajaxSetup({
  converters: {
    "text json": function (response) {
      jQuery.parseJSON($.trim(response))
    }
  }
})

Ответ 3

Это иногда вызвано старой версией плагина jQuery Validate. Если вы используете этот плагин, это иногда приводит к этой проблеме. Существует обновление, которое исправляет это, если оно относится к вашему делу.

В качестве альтернативы вы, вероятно, можете выяснить, что не так, установив обработчик ошибок через:

$.ajaxSetup() или $.ajaxError()

Это, вероятно, вернет ошибку синтаксического анализа. Более новые версии jQuery известны тем, что очень строги в отношении разбора JSON.