Optimistic lock on Ruby on Rails

marcelobarreto

Marcelo Barreto

Posted on April 4, 2021

Optimistic lock on Ruby on Rails

What are locks and why you should be using them?

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.

Locks

The example created for this article is available at Github

Optimistic lock

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:

Article Model

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:

Article form

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.

Alt Text

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.

Stable object error

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:

Example

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:

Alt Text

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:

Alt Text

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?).

OMG

Now, the user should be seeing this:

New version available

And when the user hits the update again, he'll be able to update the registry, finally 🙌😌

Finally update registry

Final thoughts

Final thoughts
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!

References

https://api.rubyonrails.org/classes/ActiveRecord/Locking/Optimistic.html

💖 💪 🙅 🚩
marcelobarreto
Marcelo Barreto

Posted on April 4, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related