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

Pet*_*ter 50 ruby-on-rails

我想要PUT铁路,避免得到一个204.我正在使用这种模式:

class SomeController < ApplicationController
  respond_to :json

  def update
    # ...
    respond_with(some_object)
  end
end
Run Code Online (Sandbox Code Playgroud)

但是,当我做put更新时,我会204回来.我意识到这是完全有效的,但我明确地希望内容回来.我可以在某种程度上覆盖它,如下所示:

def update
  respond_with(some_object) do |format|
    format.json{render json: some_object}
  end
end
Run Code Online (Sandbox Code Playgroud)

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

总结:我想要最大限度地习惯于避免使用的轨道204.

jpf*_*es2 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
Run Code Online (Sandbox Code Playgroud)

现在,显式修改需要此行为的控制器,或将其放在应用程序控制器中.

class ApplicationController < ActionController::Base

  protect_from_forgery

  responders :json

end
Run Code Online (Sandbox Code Playgroud)

您现在应该在PUT上获取JSON编码资源.

  • 我想补充一点,你需要'responders'宝石才能在你的控制器中使用responders方法. (8认同)

Ern*_*sto 13

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

def update
  # ...
  respond_with some_object, json: some_object
end
Run Code Online (Sandbox Code Playgroud)

虽然看起来有点unDRY不得不在参数中重复两次对象,但是它会给你你想要的东西,在PUT请求的响应中对象的json表示,你不需要使用这种render json:方式,这不会给你响应者的好处.

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

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


Gab*_*esy 11

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

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

参考


pat*_*ick 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
Run Code Online (Sandbox Code Playgroud)

然后要么(对于要受影响的所有更新操作):

class ApplicationController < ActionController::Base
  def self.responder
    ResponderWithPutContent
  end
end
Run Code Online (Sandbox Code Playgroud)

或者在你的行动中:

def update
  foo = Foo.find(params[:id])
  foo.update_attributes(params[:foo])
  respond_with foo, responder: ResponderWithPutContent
end
Run Code Online (Sandbox Code Playgroud)