在rails中简单的respond_with避免了PUT的204

时间:2012-03-31 07:17:19

标签: ruby-on-rails

我希望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

但是对于rails来说这似乎有点过分了。有没有更惯用的方法来避免204并要求发回全部内容?这是Rails 3.2。

总结:我想要避免204的最大惯用轨道。

6 个答案:

答案 0 :(得分:31)

我制作了一个自定义响应器,即使在PUT / POST上也会返回我的JSON编码资源。

我把这个文件放在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

您现在应该在PUT上重新获得JSON编码资源。

答案 1 :(得分:12)

作为一种侵入性较小的替代方法,您可以将respond_with选项传递给控制器​​update操作中的def update # ... respond_with some_object, json: some_object end 方法调用,如下所示:

render json:

当然,似乎有点unDRY不得不在参数中重复两次对象,但是它会给你你想要的东西,对象的json表示在PUT请求的响应中,你不需要使用Path.GetExtension方式,这不会给您带来响应者的好处。

但是,如果你有很多这种情况的控制器,那么定制响应者,就像jpfuentes2在接受的anwser中所显示的那样,是可行的方法。但对于快速单一案例,这种替代方案可能更容易。

来源:https://github.com/plataformatec/responders/pull/115#issuecomment-72517532

答案 2 :(得分:11)

这种行为似乎是故意与HTTP规范一致,并且“理想情况下”您应该触发额外的GET请求以查看结果。但是,我同意在现实世界中我宁愿让它返回JSON。

@ jpfuentes2上面的解决方案应该可以解决这个问题(它与下面的pull请求非常相似),但是我对应用任何修补rails内部结构的东西犹豫不决,因为在主要版本之间升级可能是一个真正的痛苦,特别是如果你没有对它进行测试(让我们面对它,开发人员通常会吝啬控制器测试)。

参考

答案 3 :(得分:9)

只是为了澄清,你不需要响应者宝石这样做......你可以这样做:

配置/初始化/ 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

答案 4 :(得分:3)

简单地做错了什么:

def update
  some_object = SomeObject.update()
  render json: some_object
end

答案 5 :(得分:1)

不是这种行为的忠实粉丝。为了解决这个问题,我不得不避免使用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