简体   繁体   English

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

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

In my app, multiple users can edit the same object in the database.在我的应用程序中,多个用户可以在数据库中编辑相同的 object。 If user1 loads data into a form, yet user2 writes data to the database AFTER user1 loads the form but before user1 submits the data, I would like to prevent the save of user1's data.如果 user1 将数据加载到表单中,而 user2 在 user1 加载表单但在 user1 提交数据之前将数据写入数据库,我想阻止保存 user1 的数据。

Is there anything built-in to Rails, or available in the Ruby/Rails community libraries that aims to solve this problem? Rails 中是否有任何内置的东西,或者 Ruby/Rails 社区库中是否有任何东西可以解决这个问题?

I could attempt it myself, by having a virtual attribute on all models read_at that all UI elements send back.我可以自己尝试,通过在所有模型read_at上设置一个所有 UI 元素发回的虚拟属性。 But I know problems can be more complicated than they seem, and if there's a built-in solution, I'd like to know.但我知道问题可能比看起来更复杂,如果有内置的解决方案,我想知道。

Barring a pre-built solution, are there Rails-specific characteristics I might consider using?除非使用预先构建的解决方案,否则我可能会考虑使用特定于 Rails 的特性吗? I know there is a form token?我知道有一个表单令牌? I wonder if I could get time info from that?我想知道我是否可以从中获取时间信息?

The link to ActiveRecord::Locking::Optimistic in the answer by Andreas Gebhard technically says all you need to know. Andreas Gebhard 的回答中指向ActiveRecord::Locking::Optimistic的链接从技术上说你需要知道的一切。 However, it might be more clear if I spelled it out for you.但是,如果我为您拼写出来,可能会更清楚。

If you add a field named lock_version in your table, by default ActiveRecord will enable optimistic locking.如果在表中添加一个名为lock_version的字段,默认情况下 ActiveRecord 将启用乐观锁定。 However you are not done yet.但是,您还没有完成。

The problem you are having is called "The Lost Update Problem" where a second person's update clobbers an earlier person's update.您遇到的问题称为“丢失的更新问题”,即第二个人的更新破坏了之前个人的更新。 If all you do is enable optimistic locking in the database layer you will still have a lost update problem in your web application if you program it normally and do not take the necessary steps.如果您所做的只是在数据库层中启用乐观锁定,如果您正常编程并且不采取必要的步骤,您的 web 应用程序仍然会出现丢失更新问题。

Normally your update action does a find of a record, then replaces all the fields with values sent from the form.通常,您的更新操作会查找记录,然后将所有字段替换为从表单发送的值。 As far as the database and ActiveRecord know, you started with a fresh recent record and updated it.据数据库和 ActiveRecord 所知,您从最近的新记录开始并对其进行了更新。 Thus optimistic locking will be satisfied with allowing the update but you still have a lost update problem.因此乐观锁定将满足于允许更新,但您仍然有丢失更新的问题。

What you need to do is include the lock_version field as a hidden input in your form.您需要做的是在表单中包含lock_version字段作为隐藏输入。 Then when the second person doing an update tries to update, setting the lock_version to the old value before the prior update was done will cause optimistic locking to fail.然后当第二个更新的人尝试更新时,将 lock_version 设置为之前更新完成之前的旧值将导致乐观锁定失败。

In pessimistic locking, the key to avoiding the lost update problem is to get the edit form you must first get the lock.在悲观锁中,避免丢失更新问题的关键是获取编辑表单必须首先获取锁。 If someone else has it locked, you cannot edit.如果其他人将其锁定,您将无法编辑。 A very important key to solving the lost update problem is the human in the loop by presenting the values in the database before their edit so only the human makes a decision to change them.解决丢失更新问题的一个非常重要的关键是循环中的人,通过在编辑之前呈现数据库中的值,这样只有人才能决定更改它们。 In the lost update someone did not know about someone else's update and so saved the previous value unaware that it had been updated.在丢失的更新中,有人不知道其他人的更新,因此保存了先前的值而不知道它已被更新。

In reality there is no solution to the problem.实际上,问题没有解决办法。 Someone will always lose.总会有人输的。 In the lost update problem the first person to save loses.在丢失更新问题中,第一个保存的人会失败。 In pessimistic (aka exclusive locking) the second person to try to get the lock loses.在悲观(又名排他锁)中,第二个尝试获得锁的人会失败。 In optimistic locking the second person to save loses.在乐观锁定第二个人保存失败。

The downside with pessimistic/exclusive locking is someone trying to get the edit form is denied because someone else has the lock.悲观/排他锁定的缺点是有人试图获取编辑表单被拒绝,因为其他人拥有锁定。 Also locks might not get released when they should and you can have deadlocks.此外,锁可能不会在应该释放的时候被释放,并且您可能会遇到死锁。

The downside with optimistic locking is someone can do all the work on their edit and be denied when they try to save.乐观锁定的缺点是有人可以在编辑时完成所有工作,但在尝试保存时会被拒绝。

In any case it is a surprise to someone just trying to edit.无论如何,对于试图编辑的人来说,这都是一个惊喜。 The downside of the lost update problem which makes it the worst is the surprise happens quietly without anyone noticing.丢失更新问题的缺点是最糟糕的情况是惊喜悄然发生,没有人注意到。 At least with exclusive or optimistic locking the user gets informed.至少通过排他或乐观锁定,用户会得到通知。 With optimistic locking they have to "merge" possibly having to redo the work of their edit starting from fresh data.使用乐观锁定,他们必须“合并”,可能不得不从新数据开始重做他们的编辑工作。 With exclusive locking they never have that problem but they may have to wait and might not understand why.使用独占锁定,他们永远不会遇到这个问题,但他们可能不得不等待并且可能不明白为什么。 The general preference for optimistic locking is that most of the time there is no contention for the update and it just works whereas for exclusive locking there is always the step of going into edit mode and refreshing the data on the edit form.乐观锁定的普遍偏好是,大多数时候没有更新争用,它只是工作,而对于独占锁定,总是需要进入编辑模式并刷新编辑表单上的数据。

Rails has two mechanisms baked right-in for your issue: optimistic and pessimistic locking. Rails 为您的问题提供了两种机制:乐观锁定和悲观锁定。 Personally, I find the optimistic flavor much easier to use.就个人而言,我发现乐观的味道更容易使用。 There is lots of documentation on the web, so this is just a starting point . web 上有很多文档,所以这只是一个起点 It already covers most of the caveats like multi-process race conditions and hidden form fields to deal with them!它已经涵盖了大多数警告,例如多进程竞争条件和处理它们的隐藏表单字段!

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

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