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 without the user knowing about that one new version of the register they're updating was updated some seconds ago by another user.
- Optimistic lock
- Pessimistic lock (available soon)
The example created for this article is available at Github
You can use optimistic lock when you can assume that users are allowed to edit a register on the same time. In order to this, we need to add a versioning to the table that we'll need to lock.
To 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 tab's on our browser to update the article on the same time.
On the first tab, I'll update the title and hit update article, while in the second, after the first tab finishes to load, I'll update the title too.
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 trying to update the version as
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 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 newest article's version 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 into the new version + 1, otherwise, the user will be locked (bad joke?).
Now, the user should be seen this:
And when the user hits the update again, it'll be able to update the registry, finally 🙌😌
Rails is fantastic, and how it handle lots of problems for you is incredible. Sometimes we don't know some of these awesome features that Rails deliver to us. This is one thing that now should 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 you, what are your thoughts? Have you ever used this? Why? I'd love to hear you, please comment bellow and share with your friends.