What is Optimistic Locking

Optimistic locking allows multiple users to access the same record for edits, and assumes a minimum of conflicts with the data. It does this by checking whether another process has made changes to a record since it was opened, an ActiveRecord::StaleObjectErrorexception is thrown if that has occurred and the update is ignored.

Check out ActiveRecord::Locking::Pessimisticfor an alternative.

Usage

Active Records support optimistic locking if the field lock_versionis present. Each update to the record increments the lock_versioncolumn and the locking facilities ensure that records instantiated twice will let the last one saved raise a StaleObjectErrorif the first was also updated. Example:

p1 = Person.find(1)
p2 = Person.find(1)

p1.first_name = "Michael"
p1.save

p2.first_name = "should fail"
p2.save # Raises a ActiveRecord::StaleObjectError

Optimistic locking will also check for stale data when objects are destroyed. Example:

p1 = Person.find(1)
p2 = Person.find(1)

p1.first_name = "Michael"
p1.save

p2.destroy # Raises a ActiveRecord::StaleObjectError

You're then responsible for dealing with the conflict by rescuing the exception and either rolling back, merging, or otherwise apply the business logic needed to resolve the conflict.

This locking mechanism will function inside a single Ruby process. To make it work across all web requests, the recommended approach is to add lock_versionas a hidden field to your form.

You must ensure that your database schema defaults the lock_versioncolumn to 0.

This behavior can be turned off by setting ActiveRecord::Base.lock_optimistically = false. To override the name of the lock_versioncolumn, invoke the set_locking_columnmethod. This method uses the same syntax as set_table_name

Namespace