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 с помощью контроллера леса?
Ответы
Ответ 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.