Простой response_with в рельсах, который позволяет избежать 204 из PUT
Я хочу PUT
на рельсы и не получаю 204
. Я использую этот шаблон:
class SomeController < ApplicationController
respond_to :json
def update
# ...
respond_with(some_object)
end
end
Однако, когда я обновляю PUT
, я получаю обратно 204
. Я понимаю, что это полностью допустимо и т.д., Но я явно хочу, чтобы содержимое было обратно. Я могу в некоторой степени переопределить это:
def update
respond_with(some_object) do |format|
format.json{render json: some_object}
end
end
но это кажется слишком практичным для рельсов. Есть ли более идиоматический способ избежать 204
и запроса полного содержимого для отправки? Это Rails 3.2.
Вкратце: я хочу максимально идиоматические рельсы, которые позволяют избежать 204
.
Ответы
Ответ 1
Я создал собственный ответчик, который всегда возвращает мой JSON-кодированный ресурс даже в PUT/POST.
Я помещаю этот файл в lib/responders/json_responder.rb
. Ваш каталог /lib
должен быть автоматически загружен.
module Responders::JsonResponder
protected
# simply render the resource even on POST instead of redirecting for ajax
def api_behavior(error)
if post?
display resource, :status => :created
# render resource instead of 204 no content
elsif put?
display resource, :status => :ok
else
super
end
end
end
Теперь, явно измените контроллер, который требует такого поведения, или поместите его в контроллер приложения.
class ApplicationController < ActionController::Base
protect_from_forgery
responders :json
end
Теперь вы должны получить JSON-закодированные ресурсы на PUT.
Ответ 2
Такое поведение кажется преднамеренным в соответствии с спецификацией HTTP, и "в идеале" вы должны уволить дополнительный запрос GET, чтобы увидеть результаты. Тем не менее, я согласен в реальном мире, я бы предпочел вернуть JSON.
Решение @jpfuentes2 выше должно делать трюк (он очень похож на запрос на вытягивание ниже), но я не решаюсь применять все, что исправляет внутренности рельсов, так как это может быть настоящей болью для обновления между основными версиями, особенно если у вас нет тестов для этого (и пусть сталкиваются с этим, разработчики часто экономят тесты контроллера).
Ссылки
Ответ 3
В качестве менее инвазивной альтернативы вы можете передать опцию json:
для вызова метода respond_with
внутри вашего действия с контроллером update
, например:
def update
# ...
respond_with some_object, json: some_object
end
Конечно, кажется, что бит unDRY должен повторить объект дважды в аргументах, но он даст вам то, что вы хотите, json-представление объекта в ответе запроса PUT, и вам не нужно используйте способ render json:
, который не даст вам преимуществ респондентов.
Однако, если у вас много контроллеров с этой ситуацией, то настраивать респондентов, как показано jpfuentes2 в принятом андерсере, - это путь. Но для быстрого одиночного случая эта альтернатива может быть проще.
Источник: https://github.com/plataformatec/responders/pull/115#issuecomment-72517532
Ответ 4
Чтобы уточнить, вам не нужен камень-ответчик, чтобы сделать это... Вы можете просто сделать:
конфиг/Инициализаторы/responder_with_put_content.rb
class ResponderWithPutContent < ActionController::Responder
def api_behavior(*args, &block)
if put?
display resource, :status => :ok
else
super
end
end
end
а затем либо (для всех действий, которые будут затронуты):
class ApplicationController < ActionController::Base
def self.responder
ResponderWithPutContent
end
end
или в вашем действии:
def update
foo = Foo.find(params[:id])
foo.update_attributes(params[:foo])
respond_with foo, responder: ResponderWithPutContent
end
Ответ 5
Что не так просто:
def update
some_object = SomeObject.update()
render json: some_object
end
Ответ 6
Не большой поклонник такого поведения. Чтобы обойти это, мне пришлось избегать использования метода respond_with
:
class SomeController < ApplicationController
respond_to :json
def update
# ...
respond_to do |format|
format.json { render(json: some_object, status: 200) }
end
end
end