在一个带有支架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
如果用户尝试删除同一啤酒两次(可能是快速双击,或在两个不同的浏览器选项卡中执行操作),他们将收到一个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
我可以理解在API用例中出现硬404错误的愿望,但我很难为Web应用程序辩护。有谁能提供一个很好的理由,为什么我们应该以RESTful的名义向用户抛出一个可怕的错误?
(这个问题并不是Rails所特有的,但我不知道其他框架是如何开箱即用地处理这个问题的)。
5条答案
按热度按时间hec6srdp1#
更新:原来我错了:https://stackoverflow.com/a/24713946/14731
上一个答案:
HTTP DELETE
是一个幂等运算。连续多次调用它必须产生与第一次相同的行为。含义:不应返回HTTP 404。8ljdwjyq2#
我认为你不应该为了坚持某种标准而向用户抛出错误--特别是如果这是一个面向消费者的应用程序(而不是B2B)。但您也不应该仅针对这一种情况让您的API更改其状态代码。该资源已不存在;因此,404是一个合适的响应。
我认为有一条路是最少的(或出租人--这是一个词吗?)这里有抵抗力量。我还没有研究过ruby,所以我不能提供任何可用的实现;但我对使用html/css/js的Web应用程序有一定的经验。
如果用户点击两次按钮有一些合法的问题;为什么不设置按钮,使其在提交请求时禁用,并在条件合适时重新启用(请求已返回)?换句话说,避免假设(这种非常具体的情况)的逻辑,让它不可能进入你所看到的情况。我假设Ruby有一些专门用于处理请求和为不同状态代码添加函数处理程序的东西;或者至少是非200个状态代码。
eanckbw93#
Rails scaffold代码充其量只是一个建议。您的本能是使错误消息更加用户友好,这一点很好。
jv4diomz4#
你没有理由不能在回复中返回一个格式良好的404页面。状态代码可能是相同的,只是呈现方式比典型的404页面更加用户友好。您甚至可以在响应正文中返回“重定向”页面。其中一个可能的问题是浏览器支持。已经有好几年了,但我似乎还记得IE(6?)在接收404时完全忽略响应正文内容。你必须进行实验,看看哪种方法最适合你。
wsewodh25#
我在考虑提供给客户端的响应的安全方面。如果你得到204,你就知道资源确实存在,但在404上,你可以告诉你没有这样的资源。
不过,我不确定如何利用这一点。