Простой response_with в рельсах, который избегает 204 из PUT - PullRequest
50 голосов
/ 31 марта 2012

Я хочу 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.

Ответы [ 6 ]

31 голосов
/ 10 апреля 2012

Я создал собственный респондент, который всегда возвращает мой JSON-кодированный ресурс даже в режиме PUT / POST.

Я положил этот файл в lib/responders/json_responder.rb. Ваш /lib dir должен быть автоматически загружен.

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.

12 голосов
/ 13 мая 2015

В качестве менее инвазивной альтернативы вы можете передать опцию json: в вызов метода respond_with внутри действия вашего контроллера update, например:

def update
  # ...
  respond_with some_object, json: some_object
end

Конечно, кажется немного странным повторять объект дважды в аргументах, но он даст вам то, что вы хотите, представление объекта в формате json в ответ на запрос PUT, и вам не нужно используйте способ render json:, который не даст вам преимущества респондентов.

Однако, если в этой ситуации у вас много контроллеров, то настройка ответчиков, как показал jpfuentes2 в принятом anwser, - это путь. Но для одного быстрого случая эта альтернатива может быть проще.

Источник: https://github.com/plataformatec/responders/pull/115#issuecomment-72517532

11 голосов
/ 08 мая 2013

Такое поведение кажется намеренным, чтобы соответствовать спецификации HTTP, и «в идеале» вы должны запустить дополнительный запрос GET, чтобы увидеть результаты. Тем не менее, я согласен, что в реальном мире я бы предпочел, чтобы он возвращал JSON.

Приведенное выше решение

@ jpfuentes2 должно сработать (оно очень похоже на приведенный ниже запрос на извлечение), но я не решаюсь применить все, что исправляет внутренние компоненты рельсов, так как обновление между основными версиями может оказаться реальной проблемой, особенно если у вас нет тестов для этого (и давайте посмотрим правде в глаза, разработчики часто экономят на тестах контроллеров).

Ссылки

9 голосов
/ 11 декабря 2014

Просто чтобы уточнить, вам не нужен гем респондентов, чтобы сделать это ... Вы можете просто сделать:

config / initializers / responseder_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
3 голосов
/ 14 февраля 2013

Что не так с простым делом:

def update
  some_object = SomeObject.update()
  render json: some_object
end
1 голос
/ 01 июня 2015

Не большой поклонник такого поведения. Чтобы обойти это, мне пришлось избегать использования метода 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...