- Extended by:
- Included in:
- Defined in:
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::StaleObjectError exception is thrown if that has occurred and the update is ignored.
ActiveRecord::Locking::Pessimistic for an alternative.
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:
p1 = Person.find(1) p2 = Person.find(1) p1.first_name = "Michael" p1.save p2.first_name = "should fail" p2.save # Raises an 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 an 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_version as a hidden field to your form.
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:
class Person < :: self.locking_column = :lock_person end
Defined Under Namespace
Instance Method Summary collapse
Instance Method Details
#increment! ⇒ Object
63 64 65 66 67 68 69 70
# File 'lib/active_record/locking/optimistic.rb', line 63 def increment!(*, **) # :nodoc: super.tap do if locking_enabled? self[self.class.locking_column] += 1 clear_attribute_change(self.class.locking_column) end end end
#locking_enabled? ⇒ Boolean
59 60 61
# File 'lib/active_record/locking/optimistic.rb', line 59 def locking_enabled? # :nodoc: self.class.locking_enabled? end