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

Простой 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.

4b9b3361

Ответ 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