【问题标题】:Rails Best Practices for RESTful controller CREATE and UPDATE methodsRESTful 控制器 CREATE 和 UPDATE 方法的 Rails 最佳实践
【发布时间】:2010-09-03 04:18:57
【问题描述】:

好的,我正在尝试了解 HTML 和 XML 格式的 CREATE 和 UPDATE 方法的最佳实践。 rails 生成器生成的控制器的默认代码对我来说有点不清楚。

对于 CREATE 方法,如果保存良好,生成器会说“redirect_to(@whatever)”用于 HTML 和“render :xml => @whatever, :status => :created, :location => @whatever" 用于 XML。

如果保存错误,生成器会说“render :action => 'new'” 用于 HTML 和“render :xml => @whatever.errors, :status => :unprocessable_entity" 用于 XML。

但是,对于 UPDATE 方法,如果更新良好,生成器会说 HTML 为“redirect_to(@whatever)”,XML 为“head :ok” .

而且,如果更新不正确,生成器会说“render :action => 'edit'” 用于 HTML 和“render :xml => @whatever.errors, :status => :unprocessable_entity" 对于 XML。

我明白这一点,这对我来说很有意义,而且效果很好 - 但是,我有两个问题:

首先,对于成功的 CREATE 和 UPDATE,HTML 格式,为什么使用“redirect_to(@whatever)”而不是“render :action => 'show'”?我了解重定向和渲染之间的区别,只是对你们倾向于使用哪种方式以及为什么这样做更好奇。看来重定向对于浏览器来说是不必要的额外行程。

其次,为什么在通过 XML 成功更新时“head :ok”,但是“render :xml => @whatever, :status => :created, :location => @whatever " 在通过 XML 成功创建后?这对我来说似乎不一致。似乎通过 XML 的成功 UPDATE 应该与通过 XML 的成功 CREATE 相同。似乎您需要返回新的/更新的对象,以便您可以对其进行测试。你们是怎么做到的,为什么?

【问题讨论】:

    标签: ruby-on-rails rest


    【解决方案1】:

    Sam C 回复的时候我已经把它写出来了,但无论如何都在这里 :-)

    对于第一部分 - 为什么重定向而不是渲染?我能想到的两个原因:

    1) 它是一致的。如果您呈现了显示操作并且用户稍后在返回该页面时使用了后退按钮,则用户将看到意外行为。某些版本的 IE 会给你一些会话超时错误 IIRC,其他浏览器可能会更优雅地处理它。

    如果用户将该页面添加为书签并在以后使用 GET 请求返回到该页面,情况也是如此——他们不会看到显示操作。您的应用可能会抛出错误或呈现索引操作,因为用户正在请求像 http://my.app.com/users 这样的 URL,当使用 GET 请求时,该 URL 将映射到索引操作。

    2) 如果您在未重定向到 GET 请求的情况下呈现显示操作并且用户点击刷新,您的浏览器将使用所有相同的数据重新提交 POST 请求,可能会创建与您正在创建的任何内容的重复实例。浏览器会就此向用户发出警告,以便他们可以中止,但这可能会造成混淆和不必要的不​​便。

    至于你问题的第二部分,不太确定是否诚实。我的猜测是,由于您已经在更新相关对象,因此您已经拥有它的副本,因此不需要返回它的另一个实例。话虽如此,更新对象可能会触发修改对象其他属性的各种回调,因此返回具有这些修改的更新对象可能是有意义的。

    【讨论】:

    • 我同意你对我问题第二部分的回答。您对我的问题第一部分的回答是有道理的,但这又引出了另一个问题:为什么在创建或更新不成功后,由于您提到的相同原因,使用了 render 而不是 redirect_to?如果用户想要为编辑或新页面添加书签怎么办?如果使用了渲染,那么它们仍然会在“/whatevers”页面上(这是错误的)。
    • 如果用户被重定向到 new/edit 操作,所有提交的 POST 数据都将丢失,呈现的表单将为空白。您是正确的,用户可以为呈现的错误页面添加书签,并且它会指向错误的 URL。没有办法阻止这种 AFAIK。
    • 哦,是的,呃。我错误地认为您可以重定向到新页面或编辑页面并传递@object。我错了。谢谢你让我直截了当!
    【解决方案2】:

    在创建或更新时,redirect_to(@whatever) 清除帖子,这样用户就不会通过刷新重新提交。它还在地址栏中显示了创建案例的正确 url,该 URL 发布到集合路径 (/whatevers)。

    head :ok 在更新时做出最小的响应,而通常您已经在 dom 中拥有该对象。如果你在更新后更新页面,标准的方法是使用 rjs 视图来更新 dom 元素并渲染部分。

    【讨论】:

    • 我同意您对#1 的回答,但我不太确定#2。就像 Sidane 在下面所说的那样,对象可以通过回调来更改。此外,由于 update_attributes 奇怪的“默默地忽略”默认行为,有时即使将一些无效的键或值传递给它(或者如果某些属性受到保护或只读),它也会返回 true。在这种情况下,您在 DOM 中的对象与更新后对象在后端的实际外观不同。 “Head :ok” 可能没问题,但出于测试目的,我想我可能希望在更新后拥有真实对象的副本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-09
    • 2012-08-12
    • 1970-01-01
    • 2013-11-08
    • 1970-01-01
    相关资源
    最近更新 更多