繁体   English   中英

Rails 上的 Ruby 中是否有内置方法可以避免将过时的 forms 中的数据写入数据库?

[英]Is there a built-in approach in Ruby on Rails to avoid writing data in stale forms to the database?

在我的应用程序中,多个用户可以在数据库中编辑相同的 object。 如果 user1 将数据加载到表单中,而 user2 在 user1 加载表单但在 user1 提交数据之前将数据写入数据库,我想阻止保存 user1 的数据。

Rails 中是否有任何内置的东西,或者 Ruby/Rails 社区库中是否有任何东西可以解决这个问题?

我可以自己尝试,通过在所有模型read_at上设置一个所有 UI 元素发回的虚拟属性。 但我知道问题可能比看起来更复杂,如果有内置的解决方案,我想知道。

除非使用预先构建的解决方案,否则我可能会考虑使用特定于 Rails 的特性吗? 我知道有一个表单令牌? 我想知道我是否可以从中获取时间信息?

Andreas Gebhard 的回答中指向ActiveRecord::Locking::Optimistic的链接从技术上说你需要知道的一切。 但是,如果我为您拼写出来,可能会更清楚。

如果在表中添加一个名为lock_version的字段,默认情况下 ActiveRecord 将启用乐观锁定。 但是,您还没有完成。

您遇到的问题称为“丢失的更新问题”,即第二个人的更新破坏了之前个人的更新。 如果您所做的只是在数据库层中启用乐观锁定,如果您正常编程并且不采取必要的步骤,您的 web 应用程序仍然会出现丢失更新问题。

通常,您的更新操作会查找记录,然后将所有字段替换为从表单发送的值。 据数据库和 ActiveRecord 所知,您从最近的新记录开始并对其进行了更新。 因此乐观锁定将满足于允许更新,但您仍然有丢失更新的问题。

您需要做的是在表单中包含lock_version字段作为隐藏输入。 然后当第二个更新的人尝试更新时,将 lock_version 设置为之前更新完成之前的旧值将导致乐观锁定失败。

在悲观锁中,避免丢失更新问题的关键是获取编辑表单必须首先获取锁。 如果其他人将其锁定,您将无法编辑。 解决丢失更新问题的一个非常重要的关键是循环中的人,通过在编辑之前呈现数据库中的值,这样只有人才能决定更改它们。 在丢失的更新中,有人不知道其他人的更新,因此保存了先前的值而不知道它已被更新。

实际上,问题没有解决办法。 总会有人输的。 在丢失更新问题中,第一个保存的人会失败。 在悲观(又名排他锁)中,第二个尝试获得锁的人会失败。 在乐观锁定第二个人保存失败。

悲观/排他锁定的缺点是有人试图获取编辑表单被拒绝,因为其他人拥有锁定。 此外,锁可能不会在应该释放的时候被释放,并且您可能会遇到死锁。

乐观锁定的缺点是有人可以在编辑时完成所有工作,但在尝试保存时会被拒绝。

无论如何,对于试图编辑的人来说,这都是一个惊喜。 丢失更新问题的缺点是最糟糕的情况是惊喜悄然发生,没有人注意到。 至少通过排他或乐观锁定,用户会得到通知。 使用乐观锁定,他们必须“合并”,可能不得不从新数据开始重做他们的编辑工作。 使用独占锁定,他们永远不会遇到这个问题,但他们可能不得不等待并且可能不明白为什么。 乐观锁定的普遍偏好是,大多数时候没有更新争用,它只是工作,而对于独占锁定,总是需要进入编辑模式并刷新编辑表单上的数据。

Rails 为您的问题提供了两种机制:乐观锁定和悲观锁定。 就个人而言,我发现乐观的味道更容易使用。 web 上有很多文档,所以这只是一个起点 它已经涵盖了大多数警告,例如多进程竞争条件和处理它们的隐藏表单字段!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM