【问题标题】:Why is Rails displaying an invalid URL after a validation error为什么 Rails 在验证错误后显示无效的 URL
【发布时间】:2021-09-29 04:52:03
【问题描述】:

我觉得我在许多 Rails 应用程序中都看到过这种情况,但对我来说从来没有意义(但也许那是因为已经过了午夜,我的大脑一片混乱)。

当我编辑(例如)/admin/users/20/edit 的用户时,我收到验证错误,控制器代码如下所示:

  def update
    if @user.update(user_params)
      redirect_to(some_path, notice: 'Record updated')
    else
      render("edit")   # <<<<<<<<<<<<<<<<<<<
    end
  end

它没有转到/admin/users/20/edit,而是在浏览器中显示/admin/users/20

这看起来一切都很好,但是没有/edit,它不是一个有效的 GET URI,所以其他使用 HTTP_REFERER 的代码,并且(自然)期望它是一个有效的 GET URI 将把用户带到错误页面。

在我的例子中,有一个内部 gem 可以处理管理员用户对用户的模拟。结束模拟会将管理员用户带回引用者,如果他们通过验证错误修改了引用者,则会收到错误。

我可以

  1. 修改 gem 来处理这种情况(麻烦,但可能是必要的)
  2. 添加一个路由以使此 URL 在没有 /edit 的情况下有效编辑(似乎没有必要,而且似乎有点笨拙),

但我想知道发生这种情况是否有原因。这实际上是标准的 Rails 行为还是我忽略了什么?如果这是标准的,是否有一个很好的被广泛接受的解决方案?如果不是标准的 Rails 行为,我应该在哪里寻找罪魁祸首?

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-6


    【解决方案1】:

    这是很正常的行为,因为当您更新用户时,您会将 PUTPATCH 更改为 /admin/users/20。因此,如果出现验证错误,您将呈现 edit 模板并且 url 保持不变 (/admin/users/20)

    您可以执行重定向而不是渲染,但在这种情况下,您会丢失一些有关验证错误的信息。或者您应该使用重定向发送很长的内容。

    【讨论】:

      【解决方案2】:

      这是一个常见的 Rails 初学者挂断,这里的关键是真正理解 HTTP 动词、幂等性的概念和 Rails 风格的 REST。

      Rails 中的 /new/edit 操作响应 GET 请求。它们是幂等的——页面对任何访问者来说都是一样的,如果你重新加载页面,你会得到完全相同的页面。它们仅用于在经典应用程序中显示表单。

      使用PATCH /users/1(或旧版Rails 应用程序中的PUT)更新资源。这些动词在修改资源时是非幂等的。与许多其他框架不同,Rails 使用 HTTP 方法来区分不同的操作,而不是使用 POST /users/1/updatePOST /users/1/delete

      当您调用 render("edit") 时,您所做的并不是将用户重定向回表单。您正在渲染视图并显示执行非幂等操作的结果。这不是可以链接的东西,因为结果取决于请求正文中传递的输入,并且您也不能在不重新发送完全相同的请求的情况下重新加载页面 - 在这种情况下,不能保证再次发送结果相同结果。有些浏览器根本不允许这样做,几乎所有浏览器都会警告您。

      这看起来一切都很好,但是没有 /edit 它不是一个有效的 GET URI,所以其他使用 HTTP_REFERER 并且(自然)期望它是一个有效的 GET URI 的代码会将用户带到一个错误页面。

      这是一个 X & Y 问题。编辑记录的结果不是幂等的,因此无法链接。使用HTTP_REFERER 本身也是有问题的,因为它不能保证由客户端发送。

      虽然您可以创建一个方案来重定向回,并将用户输入填充到查询字符串或会话中,但这是对错误问题的错误答案。

      我应该在哪里寻找罪魁祸首?

      您使用的任何 gem 都可能不是解决原始问题的好方法 - 甚至根本不是好方法。模拟用户可能比仅仅为管理员创建一个单独的端点来直接编辑用户更麻烦。

      这听起来确实是一个非常脆弱的解决方案。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-05-09
        • 2019-12-31
        • 2012-12-30
        • 2012-04-03
        • 2020-07-07
        • 1970-01-01
        • 2017-07-12
        • 1970-01-01
        相关资源
        最近更新 更多