在一个带有支架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
如果用户尝试删除相同的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
我可以理解在API用例中出现硬404错误的愿望,但是我很难为Web应用程序辩护。任何人都可以提供一个很好的理由我们应该以RESTfulness的名义向用户抛出一个可怕的错误吗?
(这个问题并不是Rails特有的,但我不知道其他框架如何处理这种情况的开箱即用)。
答案 0 :(得分:5)
更新:事实证明我错了:https://stackoverflow.com/a/24713946/14731
上一个回答:
HTTP DELETE
是一项idempotent操作。连续多次调用它必须导致与第一次相同的行为。含义:您不应该返回HTTP 404 。
答案 1 :(得分:4)
我认为你不应该为了保持一些标准而向用户抛出错误 - 特别是如果这是一个面向消费者的应用程序(而不是B2B)。但是你也不应该只为这种情况让你的api改变它的状态代码。资源不再存在;所以404是一个恰当的回应。
我认为这里有一条至少(或更少 - 甚至是一个词?)阻力的道路。我还没有探索ruby,所以我无法提供任何可用的实现;但我对使用html / css / js的网络应用程序有一定的经验。
如果用户点击两次按钮存在一些合法问题;为什么不设置按钮以便在提交请求时禁用它,并在条件正确后重新启用(请求已经返回)?换句话说,通过使得无法进入你所看到的情况来避免if(这种非常具体的情况)逻辑。我假设ruby专门用于处理请求和为不同的状态代码添加函数处理程序;或至少非200状态代码。
答案 2 :(得分:2)
Rails脚手架代码充其量只是一个建议。您使错误消息更加用户友好的直觉是一个很好的。
答案 3 :(得分:1)
您没有理由不能使用您的回复返回格式良好的404页面。状态代码可以是相同的,只是渲染比典型的404页面更加用户友好。您甚至可以在响应正文中返回“重定向”页面。一个可能的问题是浏览器支持。这已经有好几年了,但我似乎回忆起IE(6?)在收到404时完全无视响应主体内容。你必须尝试看看哪种方式最适合你。