Optimistic locking of ActiveRecord models30th May 2018
Did you know that Rails can help avoid data overwrite when multiple users are editing the same record?
Yes, you can use optimistic locking on models, and it turns out it's pretty easy to enable it too.
To be honest, I've never heard about this functionality until recently while browsing the Active Record Basics Guide looking for info on a totally different problem that I had.
When I read about the
lock_version field, I was curious and surprised by what I found.
It basically works like this:
If you add the
lock_version field to any ActiveRecord model, every time that record is saved it will be checked for modifications after the record was loaded.
So, if for some reason the record changed in the database while you were editing it, when you try to save it an
ActiveRecord::StaleObjectError exception will be raised.
require 'active_record' ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:') ActiveRecord::Base.logger = Logger.new(STDOUT) ActiveRecord::Schema.define do create_table :orders do |t| t.integer :total t.string :lock_version end end class Order < ActiveRecord::Base ; end Order.create object_1 = Order.find(1) object_2 = Order.find(1) object_1.total = 100 object_1.save # Succeeds! object_2.total = 200 object_2.save # Raises ActiveRecord::StaleObjectError
You can see from the example that both
object_2 were loaded at the same time.
When you modify and change the first object, it will be saved without any problem and the
save method will return true as expected, but when you try and save the second one (
ActiveRecord::StaleObjectError will be raised because the object has been modified already.
You can read more about this feature directly on its API documentation.
It is worth mentioning that there is a more aggressive way to lock records by using