Ruby on Rails 中是否有内置方法来避免以陈旧的形式将数据写入数据库?
Is there a built-in approach in Ruby on Rails to avoid writing data in stale forms to the database?
在我的应用中,多个用户可以编辑数据库中的同一个对象。如果 user1 将数据加载到表单中,而 user2 在 user1 加载表单之后但在 user1 提交数据之前将数据写入数据库,我想阻止保存 user1 的数据。
Rails 或 Ruby/Rails 社区图书馆中是否有旨在解决此问题的内置内容?
我可以自己尝试,通过在所有模型 read_at
上设置所有 UI 元素发回的虚拟属性。但我知道问题可能比看起来更复杂,如果有内置的解决方案,我想知道。
除了预构建的解决方案,是否有我可以考虑使用的 Rails 特定特征?我知道有一个表单令牌?我想知道我是否可以从中获取时间信息?
Rails 有两种机制可以解决您的问题:乐观锁定和悲观锁定。就个人而言,我发现乐观的风格更容易使用。网上有很多文档,所以这只是一个starting point。它已经涵盖了大部分注意事项,例如多进程竞争条件和处理它们的隐藏表单字段!
Andreas Gebhard 的回答中的 link 到 ActiveRecord::Locking::Optimistic 从技术上讲,您需要知道的一切。不过,如果我拼写出来给你,可能会更清楚。
如果您在 table 中添加一个名为 lock_version
的字段,默认情况下 ActiveRecord 将启用乐观锁定。但是你还没有完成。
您遇到的问题称为“丢失更新问题”,即第二个人的更新破坏了较早的人的更新。如果您所做的只是在数据库层启用乐观锁定,如果您正常编程并且不采取必要的步骤,您的 Web 应用程序仍然会遇到更新丢失的问题。
通常您的更新操作会查找记录,然后将所有字段替换为从表单发送的值。就数据库和 ActiveRecord 所知,您从最近的新记录开始并更新了它。因此,乐观锁定将满足于允许更新,但您仍然有更新丢失的问题。
您需要做的是将 lock_version
字段作为隐藏输入包含在您的表单中。然后,当第二个执行更新的人尝试更新时,将 lock_version 设置为先前更新完成之前的旧值将导致乐观锁定失败。
在悲观锁中,避免丢失更新问题的关键是获取编辑表单必须先获取锁。如果其他人已将其锁定,则您无法编辑。解决丢失更新问题的一个非常重要的关键是循环中的人,通过在编辑之前在数据库中呈现值,这样只有人才能决定更改它们。在丢失的更新中,某人不知道其他人的更新,因此在不知道它已被更新的情况下保存了以前的值。
现实中没有解决问题的方法。总会有人输。在丢失更新问题中,第一个拯救的人失败了。在悲观(又名独占锁定)中,第二个试图获得锁的人失败了。乐观锁定第二个人救输。
pessimistic/exclusive 锁定的缺点是有人试图获取编辑表单被拒绝,因为其他人有锁。此外,锁可能不会在应该释放的时候释放,您可能会遇到死锁。
乐观锁定的缺点是有人可以在他们的编辑中完成所有工作,但在他们尝试保存时被拒绝。
无论如何,对于试图编辑的人来说,这都是一个惊喜。丢失更新问题的缺点是最糟糕的是意外悄悄发生,没有人注意到。至少在排他或乐观锁定的情况下,用户会得到通知。使用乐观锁定,他们必须“合并”,可能必须从新数据开始重新进行编辑工作。使用独占锁定,他们永远不会遇到这个问题,但他们可能不得不等待并且可能不明白为什么。乐观锁定的一般偏好是,大多数时候没有更新竞争,它只是工作,而对于独占锁定,总是有进入编辑模式并刷新编辑表单上的数据的步骤。
在我的应用中,多个用户可以编辑数据库中的同一个对象。如果 user1 将数据加载到表单中,而 user2 在 user1 加载表单之后但在 user1 提交数据之前将数据写入数据库,我想阻止保存 user1 的数据。
Rails 或 Ruby/Rails 社区图书馆中是否有旨在解决此问题的内置内容?
我可以自己尝试,通过在所有模型 read_at
上设置所有 UI 元素发回的虚拟属性。但我知道问题可能比看起来更复杂,如果有内置的解决方案,我想知道。
除了预构建的解决方案,是否有我可以考虑使用的 Rails 特定特征?我知道有一个表单令牌?我想知道我是否可以从中获取时间信息?
Rails 有两种机制可以解决您的问题:乐观锁定和悲观锁定。就个人而言,我发现乐观的风格更容易使用。网上有很多文档,所以这只是一个starting point。它已经涵盖了大部分注意事项,例如多进程竞争条件和处理它们的隐藏表单字段!
Andreas Gebhard 的回答中的 link 到 ActiveRecord::Locking::Optimistic 从技术上讲,您需要知道的一切。不过,如果我拼写出来给你,可能会更清楚。
如果您在 table 中添加一个名为 lock_version
的字段,默认情况下 ActiveRecord 将启用乐观锁定。但是你还没有完成。
您遇到的问题称为“丢失更新问题”,即第二个人的更新破坏了较早的人的更新。如果您所做的只是在数据库层启用乐观锁定,如果您正常编程并且不采取必要的步骤,您的 Web 应用程序仍然会遇到更新丢失的问题。
通常您的更新操作会查找记录,然后将所有字段替换为从表单发送的值。就数据库和 ActiveRecord 所知,您从最近的新记录开始并更新了它。因此,乐观锁定将满足于允许更新,但您仍然有更新丢失的问题。
您需要做的是将 lock_version
字段作为隐藏输入包含在您的表单中。然后,当第二个执行更新的人尝试更新时,将 lock_version 设置为先前更新完成之前的旧值将导致乐观锁定失败。
在悲观锁中,避免丢失更新问题的关键是获取编辑表单必须先获取锁。如果其他人已将其锁定,则您无法编辑。解决丢失更新问题的一个非常重要的关键是循环中的人,通过在编辑之前在数据库中呈现值,这样只有人才能决定更改它们。在丢失的更新中,某人不知道其他人的更新,因此在不知道它已被更新的情况下保存了以前的值。
现实中没有解决问题的方法。总会有人输。在丢失更新问题中,第一个拯救的人失败了。在悲观(又名独占锁定)中,第二个试图获得锁的人失败了。乐观锁定第二个人救输。
pessimistic/exclusive 锁定的缺点是有人试图获取编辑表单被拒绝,因为其他人有锁。此外,锁可能不会在应该释放的时候释放,您可能会遇到死锁。
乐观锁定的缺点是有人可以在他们的编辑中完成所有工作,但在他们尝试保存时被拒绝。
无论如何,对于试图编辑的人来说,这都是一个惊喜。丢失更新问题的缺点是最糟糕的是意外悄悄发生,没有人注意到。至少在排他或乐观锁定的情况下,用户会得到通知。使用乐观锁定,他们必须“合并”,可能必须从新数据开始重新进行编辑工作。使用独占锁定,他们永远不会遇到这个问题,但他们可能不得不等待并且可能不明白为什么。乐观锁定的一般偏好是,大多数时候没有更新竞争,它只是工作,而对于独占锁定,总是有进入编辑模式并刷新编辑表单上的数据的步骤。