是否应该在RESTful Rails中删除404中不存在的资源?

Bra*_*rad 18 ruby rest usability ruby-on-rails http

在带有支架RESTful模型的全新Rails应用程序中,生成的删除代码如下所示:

class BeersController < ApplicationController
  # DELETE /beers/1
  # DELETE /beers/1.xml
  def destroy
    @beer = Beer.find(params[:id])
    @beer.destroy

    respond_to do |format|
      format.html { redirect_to(beers_url) }
      format.xml  { head :ok }
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

如果用户尝试删除相同的Beer两次(可能是快速双击,或者在两个不同的浏览器选项卡中执行操作),则会得到RecordNotFound错误,从而导致404页面.这是一个非常不友好的经历; 似乎最好将重定向完成,beers_url无论是否有flash错误,因为用户无法做任何关于第二次删除失败的事情.

另一种方法就是像删除一样成功,如下所示:

def destroy
  @beer = Beer.find_by_id(params[:id])
  destroyed = @beer.try(:destroy)        

  respond_to do |format|
    format.html { redirect_to(beers_url) }
    format.xml  { destroyed ? head(:ok) : head(:not_found) }
  end
end
Run Code Online (Sandbox Code Playgroud)

我可以理解API用例中出现硬404错误的愿望,但是我很难为Web应用程序辩护.任何人都可以提供一个很好的理由为什么我们应该以RESTfulness的名义向用户抛出一个可怕的错误?

(这个问题并不是Rails特有的,但我不知道其他框架如何处理这种情况).

Gil*_*ili 8

更新:事实证明我错了:https://stackoverflow.com/a/24713946/14731


上一个答案: HTTP DELETE是一个幂等操作.连续多次调用它必须导致与第一次相同的行为.含义:您不应该返回HTTP 404.

  • 必须导致目标资源的服务器状态相同.这并不意味着您需要返回相同的状态代码.如果先前发生故障,您似乎会重复请求.那些普通的不存在的资源呢?试图删除那些应该清楚地表明不存在,不应该吗? (4认同)

Dav*_*ave 5

我认为您不应该为了维护某些标准而向用户抛出错误 - 特别是如果这是面向消费者的应用程序(而不是 B2B)。但是您也不应该让您的 api 仅针对这种情况更改其状态代码。该资源不再存在;所以 404 是正确的响应。

我认为这里有一条最少(或出租人 - 甚至是一个词???)阻力的路径。我还没有探索 ruby​​,所以我不能提供任何可用的实现;但我对使用 html/css/js 的网络应用程序有一定的经验。

如果用户单击按钮两次存在合法问题;为什么不设置按钮,使其在提交请求时禁用,并在条件合适时重新启用(请求已返回)?换句话说,通过使您无法进入您所看到的情况来避免 if(这种非常具体的情况)逻辑。我假设 ruby​​ 有一些专门用于处理请求和为不同状态代码添加函数处理程序的东西;或至少非 200 状态代码。

  • 我喜欢尽可能防止非幂等操作的双重提交的想法。这不是万无一失的(想象一下,用户在两个选项卡中打开了您的应用程序的两个副本,并尝试删除它们中的同一个项目),但这绝对是可用性的改进。 (2认同)

jdl*_*jdl 2

Rails 脚手架代码充其量只是一个建议。您本能地让错误消息变得更加用户友好是一件好事。

  • 我认为你是对的,但我提出了更强有力的主张;根本不应该有错误消息,并且该操作应该完成_就像_销毁已成功一样。 (2认同)