Ruby on rails 将#u重定向到';不适合RESTful应用程序?

Ruby on rails 将#u重定向到';不适合RESTful应用程序?,ruby-on-rails,rest,Ruby On Rails,Rest,作为一个长期使用Ruby和Rails的用户,直到今天我才真正想到Rails中的get和redirect模式。这方面的典型示例是调用create()操作,然后将用户重定向到show()操作以显示新创建的项: class JournalEntries def index @entries = JournalEntry.all end def create @entry = JournalEntry.new( :name => "to-do list" ) @e

作为一个长期使用Ruby和Rails的用户,直到今天我才真正想到Rails中的get和redirect模式。这方面的典型示例是调用create()操作,然后将用户重定向到show()操作以显示新创建的项:

class JournalEntries def index @entries = JournalEntry.all end def create @entry = JournalEntry.new( :name => "to-do list" ) @entry.save redirect_to :action => "index" end end 类日志 def索引 @entries=JournalEntry.all 结束 def创建 @entry=JournalEntry.new(:name=>“待办事项列表”) @entry.save 重定向到:action=>“index” 结束 结束 但是,这有一个固有的缺点,即您的网络流量将翻倍。这既降低了用户的网站体验,也增加了带宽费用

那么,为什么不干脆这样做呢:

def create @entry = JournalEntry.new( :name => "to-do list" ) @entry.save index def创建 @entry=JournalEntry.new(:name=>“待办事项列表”) @entry.save 指数 相同的输出,并且不需要额外的开销。但除此之外,还有一个更重要的问题:重定向到只能使用GET重定向。这会给使用四种不同HTTP方法的RESTful应用程序带来重大问题

在我的例子中,我希望用户能够调用/journals/8并检索具有该ID的日志。如果找不到,我希望创建一个新的空日志对象。在任何一种情况下,日志对象都会被发送给调用者

请注意,RESTful Rails中的create()方法是从“POST/players”路由的。但是由于redirect_to(以及底层HTTP redirect)只能发送GET请求,它实际上会重定向到“GET/players”,即index()方法。这种行为显然是错误的

我能想到的唯一解决方案是简单地调用create(),而不是像上面的例子那样将_重定向到()。它似乎工作得很好


有没有想过为什么重定向到比直接调用操作更可取?

我是Python/Django人,但重定向的原因与语言无关:

  • 如果他们进行页面刷新,就不会出现令人讨厌的“重新发送数据”弹出窗口
  • 这将为他们查看的页面提供一个完全干净、RESTful的URL。如果您使用POST,这可能没什么大不了的,但是如果GET用于更新,那么您肯定希望摆脱任何悬而未决的参数
  • 如果他们进行页面刷新,就不会出现令人讨厌的“重新发送数据”弹出窗口

    这不仅仅是因为弹出窗口很烦人(对大多数用户来说毫无意义)——如果用户单击“是的,重做文章”,他最终会创建另一个日记条目(或其他什么)


    此外,URL读取
    /posts/create
    而不是
    /posts
    也很烦人,因为用户无法复制/重复使用它。

    原因正如您所指出的。您重定向到GET请求,这在REST中是正确的(仅使用POST/PUT进行更新,使用GET仅获取数据)

    重定向肯定会给重定向带来一些开销,但由于除了POST数据和重定向(只将新url发送到浏览器)之外,浏览器和服务器之间实际上没有发送任何数据,因此我不认为bandwith的问题值得关注

    但是在另一点上,您不应该重定向到/journals(通过调用
    redirect\u to:index
    ),您应该将它重定向到新创建的日记条目(通过调用
    redirect\u to@entry
    ),如果您通过(例如
    map.resources:journals
    )正确设置了路由,它将起作用

    更新:

    我认为,在不存在日志的情况下创建日志,应该要求用户提供更多输入。您创建条目的原因是什么?条目应该有一些文本或来自用户的其他输入,因此我认为从REST(和rails)的角度来看,实际上应该将其重定向到
    new()
    方法(带有GET请求),用户可以在该方法中输入附加信息,然后发布输入并创建条目,然后重定向到新创建的条目


    如果您没有任何需要输入的额外信息,我不确定如何以RESTful方式执行,但我可能会将创建逻辑放在一个单独的方法中,我将从
    create()
    show()
    方法调用该方法,然后继续执行
    show()
    ,根本不重定向,也不调用资源方法。

    只是对第二点的评论。据我所知,REST的一点是永远不要对GET进行更新,所以这不应该成为一个问题。@Jimmy:同意,在适当的REST中,这不应该发生。所以根据你们两人的说法,听起来问题在于我试图做的事情本质上是非restful的——如果一个人想要返回一个对象(如果它存在)并创建它(如果它不存在),那就需要两个单独的调用:GET/journal/1(如果它不返回任何记录,那么客户端调用):POST/journals/[POST data:journal.id=5]对吗?也就是说,在REST中没有一次性调用可以作为一个操作同时执行这两项任务?@Jake2:不太可能。当然,休息不是一种宗教,它是一种在很多情况下都很有用的架构。遵循它会使向可能的消费者(其他程序)解释您的系统变得微不足道。您对最小化连接的关注可能表明您的系统中存在其他约束(例如通信资源消耗),这些约束覆盖了“纯RESTful”的好处。我想我应该先从我文章的后半部分开始——我的主要问题不是网络开销,而是调用的实际方法。从我的控制器的角度(根本不考虑如何调用这些方法),我希望调用Journal.show()来调用Journal.create(),如果找不到给定的日志,然后返回创建的对象。就我所见,在REST应用程序中使用redirect_to绝对没有办法做到这一点,原因是我在最初的帖子中提到的。我失踪了吗