[Ruby on Rails (RoR)] Optimistic Locking in Rails
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::StaleObjectError
exception is thrown if that has occurred and the update is ignored.
Check out ActiveRecord::Locking::Pessimistic
for an alternative.
Usage
Active Record supports optimistic locking if the lock_version field is present. Each update to the record increments the lock_version
column and the locking facilities ensure that records instantiated twice will let the last one saved raise a StaleObjectError if the first was also updated. Example:
1 | p1 = Person.find(1) |
Optimistic locking will also check for stale data when objects are destroyed. Example:
1 | p1 = Person.find(1) |
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_version
as a hidden field to your form.
1 | <%= form.hidden_field :lock_version %> |
In our controller, we need to permit the version column so that it is included in the params used to update the user.
1 | # Only allow a list of trusted parameters through. |
This behavior can be turned off by setting ActiveRecord::Base.lock_optimistically = false
. To override the name of the lock_version
column, set the locking_column
class attribute:
1 | class Person < ActiveRecord::Base |
You can override the name of the locking column globally in environment.rb
:
1 | # config/environment.rb: |