【问题标题】:Preventing UPDATE of record in Rails app where no fields are changed防止在没有更改任何字段的 Rails 应用程序中更新记录
【发布时间】:2019-08-30 08:31:30
【问题描述】:

我正在寻找一种方法来防止用户在我的 Rails 应用程序中为 Update 方法单击更新,因为他们没有更改任何值。如果他们没有更改任何值,我的 UPDATE 方法将在某些字段中写入空值,因此如果用户没有更改任何详细信息而只是单击更新,我需要应用程序阻止更新记录。

任何建议将不胜感激。

仅供参考,这是标准的千篇一律更新方法:

def update
    if @client.update(client_params)
      redirect_to @client, notice: 'Client was successfully updated.'
    else
      render :edit
    end
  end

【问题讨论】:

  • 你能解释一下你的具体情况吗(最好有代码)。如果用户能够使用空值(您不想为空)更新记录,那么这是一个验证问题。
  • 也许您可以使用 ActiveRecord 回调来避免更新数据库中的记录。可以改用吗? (apidock.com/rails/ActiveRecord/Dirty/changed%3F) 在 before_update 回调和 throw :abort 中故意停止回调链。
  • @JamesLovesPython 你能验证答案吗?

标签: ruby-on-rails ruby


【解决方案1】:

默认情况下,Rails 中的 UPDATE 方法只有在任何一个值被修改时才会执行。如果没有修改字段值,UPDATE方法不会运行查询,只检查并返回结果。

我会给出同样的例子。我有一个组织模型,我最初使用相同的现有字段值更新了记录:

我刚刚修改了其中一个字段值 - 内部状态

注意:在更新中最好发送旧值以避免空值存储在数据库中。在您的情况下,更新需要“client_params”中定义的所有参数。如果发送了空参数,请包含 nil 检查或验证以避免相同的情况。您也可以为此编写自定义更新方法。

【讨论】:

  • 请不要写自定义更新方法:) There are bunch of ways you can update record with AR
  • 嗨,我相信这种行为的原因是我设置了包含不在数据库中的值的下拉字段。因此,当页面填充并单击更新客户端时,它会看到这些字段已更改(因为数据库中的实际值没有被填写,因为不在这些列表中)。这将允许更新查询运行。将更新我的列表以适应这一点。感谢所有的帮助。
【解决方案2】:

您可以结合使用attributes=changed? 方法来实现您的目标。

attributes= mass 将值从散列分配给模型的实例。 changed? 如果模型上的任何值改变了它的值,则返回 true。

举个例子:

[1] pry(main)> u = User.all.sample # this returns a random user
=> #<User id: 1319, email: "bob@test.com">
[2] pry(main)> u.changed?
=> false
[3] pry(main)> u.attributes = { email: "bob@test.com" }
=> {:email=>"bob@test.com"}
[4] pry(main)> u.changed?
=> false
[5] pry(main)> u.email
=> "bob@test.com"
[6] pry(main)> u.attributes = { email: "alice@test.com" }
=> {:email=>"alice@test.com"}
[7] pry(main)> u.changed?
=> true
[8] pry(main)> u.email
=> "alice@test.com"
[9] pry(main)> u.save
=> true

当应用于您的代码 sn-p.

def update
  @client.attributes = client_params

  if @client.changed? && @client.save
    redirect_to @client, notice: 'Client was successfully updated.'
  else
    render :edit
  end
end

【讨论】:

    【解决方案3】:

    您能否使用现有值预先填写表单?这样,如果按下更新,表单将发送之前的内容而不是空白值,并且记录不会填充空白数据。它也是很好的用户体验,可以向用户展示编辑表单中的现有值。

    【讨论】:

      【解决方案4】:

      无需添加自定义条件来检查您的属性是否已被修改,因为Rails 处理默认设置

      如果修改的 Active Record 对象已经被检索到,那么它将被保存到数据库中,否则不会执行任何操作。为了更好地理解,您可以通过运行这两个查询自行检查您的控制台。

      用于防止将空值存储在数据库中。请检查您是否使用“PATCH”方法类型来更新记录。

      因为只有在一种情况下才有可能:

      使用“PUT”方法更新记录并仅提供修改后的“密钥对”属性 铁轨。 Rails 将保存其他未指定的“键值” 具有空值的属性。

      在 Rails 中,“更新”方法有两种方法类型。

      (更新全部或部分记录。)

      1. 补丁

      只能更新部分记录

      为了遵循更好的 HTTP 语义,Rails 将使用 HTTP 动词 PATCH 进行更新。 PATCH 允许对资源进行全部和部分更新,并且更适合 Rails 更新资源的方式。如果您正在升级现有的 Rails 应用程序,HTTP 动词 PUT 仍将映射到更新操作 RESTful 路由,但建议继续使用 PATCH。

      【讨论】:

        猜你喜欢
        • 2012-02-03
        • 2016-07-26
        • 1970-01-01
        • 1970-01-01
        • 2013-03-19
        • 1970-01-01
        • 1970-01-01
        • 2016-10-26
        • 1970-01-01
        相关资源
        最近更新 更多