ruby-on-rails – rails中的PUT请求不会更新respond_with呼叫的状态

前端之家收集整理的这篇文章主要介绍了ruby-on-rails – rails中的PUT请求不会更新respond_with呼叫的状态前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
给定以下控制器:
class AccountsController < ApplicationController
    respond_to :json,:xml
    def update
        @account = Account.where(uuid: params[:id]).first
        unless @account.nil?
            if @account.update_attributes params[:account]
                respond_with @account,location: account_url(@account)
            else
                respond_with error_hash,status: :unprocessable_entity,root: :error,location: api_account_url(@account)
            end
        else
            respond_with error_hash,status: :not_found,location: accounts_url
        end
    end

    def error_hash
        { :example => "Example for this question",:parameter => 42 }
    end
end

我会期望一个PUT请求/ accounts / update /来执行以下操作

>如果id存在,并且update_attributes调用成功,则提供204(无内容)成功消息. (我有它返回@account,这将是不错的,但没有什么大不了的204在这里很好)
>如果id存在但数据不正确,则会传递一个422(Unprocessible Entity)错误消息以及xml / json来表示错误.
>如果id不存在,请传送404(Not Found)错误消息以及xml / json以表示错误.

实际发生的是:

提供一个没有身体的204.
提供一个没有身体的204.
提供一个没有身体的204.

为什么它忽略了我的身份和身体?我已经有一个类似的设置GET请求,工作很好(正确的状态,正确的身体).

示例CURL请求(对于不存在的ID):

PUT请求

curl -i --header "Accept: application/xml" --header "Content-type: application/json" -X PUT -d '{"name": "whoop"}' http://localhost:3000/api/accounts/3d2cc5d0653911e2aaadc82a14fffee9
HTTP/1.1 204 No Content 
Location: http://localhost:3000/api/accounts
X-Ua-Compatible: IE=Edge
Cache-Control: no-cache
X-Request-Id: bf0a02f452fbace65576aab6d2bd7c1e
X-Runtime: 0.029193
Server: WEBrick/1.3.1 (Ruby/1.9.3/2013-01-15)
Date: Thu,24 Jan 2013 08:01:31 GMT
Connection: close
Set-Cookie: _bankshare_session=BAh7BkkiD3Nlc3Npb25faWQGOgZFRkkiJWFmNmI2MmU0MzViMmE3N2YzMDIzOTdjMDJmZDhiMzEwBjsAVA%3D%3D--133e394eb760a7fce07f1fd51349dc46c2d51626; path=/; HttpOnly

GET请求

curl -i --header "Accept: application/json" --header "Content-type: application/json" -X GET http://localhost:3000/api/accounts/3d2cc5d0653911e2aaadc82a14fffee9
HTTP/1.1 404 Not Found 
Content-Type: application/json; charset=utf-8
X-Ua-Compatible: IE=Edge
Cache-Control: no-cache
X-Request-Id: 9cc0d1cdfb27bb86a206cbc38cd75473
X-Runtime: 0.005118
Server: WEBrick/1.3.1 (Ruby/1.9.3/2013-01-15)
Date: Thu,24 Jan 2013 08:19:45 GMT
Content-Length: 116
Connection: Keep-Alive

{"friendly-status":"not-found","status":404,"message":"No account with id '3d2cc5d0653911e2aaadc82a14fffee9' found"}

解决方法

根据 this讨论,这种相当非直观的行为是由于希望保持与脚手架的兼容性.

In general we keep the responder the same implementation as the
scaffold. This allows us to say: replace respond_to by respond_with
and everything will work exactly the same.

josevalim

您有两个选择来覆盖默认行为.

A)将一个块传递给respond_with

unless @account.nil?
  if @account.update_attributes params[:account]
    respond_with @account do |format|
      format.json { render json: @account.to_json,status: :ok }  
      format.xml  { render xml: @account.to_xml,status: :ok }
    end
  else
    respond_with error_hash do |format|
      format.json { render json: error_hash.to_json(root: :error),status: :unprocessable_entity }
      format.xml { render xml: error_hash.to_xml(root: :error),status: :unprocessable_entity }
    end
  end
else
  respond_with error_hash do |format|
    format.json { render json: error_hash.to_json(root: :error),status: :not_found }
    format.xml { render xml: error_hash.to_xml(root: :error),status: :not_found }
  end
end

不幸的是,我们必须重新出现每种格式的重复,但这似乎是迄今为止Rails 4.0的当前建议;见here.

如果您返回更新的对象,或者不返回任何东西并让您的客户端代码“GET”更新的对象,则应返回200 – OK,而不是204 – 否. :位置在api上下文中无意义,它用于重定向html响应.

B)创建一个自定义响应者

respond_with @account,status: :ok,responder: MyResponder

我自己也没有这样做,所以我不能举个例子,但是这似乎也是过分的.

查看Railscasts Episode:224有关response_with的一些讨论,包括自定义响应者.

猜你在找的Ruby相关文章