Locks are required for concurrency in multi-user scenarios (where one or more users could modify one register in the same time), and you need to avoid data to be overriden before the user can save their changes.
- Optimistic lock
- Pessimistic lock (available soon)
The example created for this article is available at Github
You can use optimistic locks when you can assume that users are allowed to edit a register at the same time. In order to this, we need to add versioning to the table that we'll need to lock.
For our examples, I've created a model called Article, and the columns are title:string text:text version:integer. By default, if you call our version column as lock_version, Rails will handle the optimistic lock for you automatically, but, for this example let's use a different name so you can see behind the magic.
Let's update our Article model to be as follows:
Now, on our view, let's fix one quick thing. We should send back to the server which version the user is updating, but you should not show this to the user, so let's update the view to hide our version input field. And for now, we should have something more or less like this:
Let's see how the optimistic lock works for real!
First, let's create a new article and then, let's open two tabs on our browser to update the article at the same time.
On the first tab, I'll update the title and hit update article, while on the second, after the first tab finishes loading, I'll update the title as well.
Wow, an error was raised, that was expected. But first, let me explain one thing: our tabs were holding our version number as 1, and after we updated the first tab, it was increased to 2, and on the second tab, we're still trying to update version 1. In other words, we're trying to update a stale object. Let's fix this and give a better error message to the user:
Disclaimer: I know updating Rails default methods is not the best approach, but it fits well for this example
Let's try to repeat the same scenario again and see how it should work now:
Fair enough... But let's polish this a little bit more.
On our controller, let's return the latest article version by doing the following:
On our form, let's update the view to show the fresh version, so the user would be able to compare the new article to the previous version, and let's increase the version to the new version + 1, otherwise, the user will be locked (bad joke?).
Now, the user should be seeing this:
And when the user hits the update again, he'll be able to update the registry, finally 🙌😌
Rails is fantastic, and how it handles a lot of the problems for you is incredible. Sometimes we don't know some of these awesome features that Rails delivers to us. This is one thing that should now be available on your toolbelt if you didn't know about it before. I hope that you enjoyed this article and I'm eager to hear from you. What are your thoughts? Have you ever used this feature? And why? I'd love to hear your opinions. Please comment bellow and share with your friends. Thank you!