summaryrefslogtreecommitdiff
path: root/vendor/rails/activerecord/lib/active_record/locking/optimistic.rb
Side-by-side diff
Diffstat (limited to 'vendor/rails/activerecord/lib/active_record/locking/optimistic.rb') (more/less context) (ignore whitespace changes)
-rw-r--r--vendor/rails/activerecord/lib/active_record/locking/optimistic.rb144
1 files changed, 0 insertions, 144 deletions
diff --git a/vendor/rails/activerecord/lib/active_record/locking/optimistic.rb b/vendor/rails/activerecord/lib/active_record/locking/optimistic.rb
deleted file mode 100644
index 799309c..0000000
--- a/vendor/rails/activerecord/lib/active_record/locking/optimistic.rb
+++ b/dev/null
@@ -1,144 +0,0 @@
-module ActiveRecord
- module Locking
- # == 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 is thrown if that has occurred and the update is ignored.
- #
- # Check out ActiveRecord::Locking::Pessimistic for an alternative.
- #
- # == Usage
- #
- # Active Records support optimistic locking if the field <tt>lock_version</tt> 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 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.
- #
- # You must ensure that your database schema defaults the lock_version column to 0.
- #
- # This behavior can be turned off by setting <tt>ActiveRecord::Base.lock_optimistically = false</tt>.
- # To override the name of the lock_version column, invoke the <tt>set_locking_column</tt> method.
- # This method uses the same syntax as <tt>set_table_name</tt>
- module Optimistic
- def self.included(base) #:nodoc:
- base.extend ClassMethods
-
- base.cattr_accessor :lock_optimistically, :instance_writer => false
- base.lock_optimistically = true
-
- base.alias_method_chain :update, :lock
- base.alias_method_chain :attributes_from_column_definition, :lock
-
- class << base
- alias_method :locking_column=, :set_locking_column
- end
- end
-
- def locking_enabled? #:nodoc:
- self.class.locking_enabled?
- end
-
- private
- def attributes_from_column_definition_with_lock
- result = attributes_from_column_definition_without_lock
-
- # If the locking column has no default value set,
- # start the lock version at zero. Note we can't use
- # locking_enabled? at this point as @attributes may
- # not have been initialized yet
-
- if lock_optimistically && result.include?(self.class.locking_column)
- result[self.class.locking_column] ||= 0
- end
-
- return result
- end
-
- def update_with_lock #:nodoc:
- return update_without_lock unless locking_enabled?
-
- lock_col = self.class.locking_column
- previous_value = send(lock_col).to_i
- send(lock_col + '=', previous_value + 1)
-
- begin
- affected_rows = connection.update(<<-end_sql, "#{self.class.name} Update with optimistic locking")
- UPDATE #{self.class.table_name}
- SET #{quoted_comma_pair_list(connection, attributes_with_quotes(false, false))}
- WHERE #{self.class.primary_key} = #{quote_value(id)}
- AND #{self.class.quoted_locking_column} = #{quote_value(previous_value)}
- end_sql
-
- unless affected_rows == 1
- raise ActiveRecord::StaleObjectError, "Attempted to update a stale object"
- end
-
- affected_rows
-
- # If something went wrong, revert the version.
- rescue Exception
- send(lock_col + '=', previous_value)
- raise
- end
- end
-
- module ClassMethods
- DEFAULT_LOCKING_COLUMN = 'lock_version'
-
- def self.extended(base)
- class <<base
- alias_method_chain :update_counters, :lock
- end
- end
-
- # Is optimistic locking enabled for this table? Returns true if the
- # #lock_optimistically flag is set to true (which it is, by default)
- # and the table includes the #locking_column column (defaults to
- # lock_version).
- def locking_enabled?
- lock_optimistically && columns_hash[locking_column]
- end
-
- # Set the column to use for optimistic locking. Defaults to lock_version.
- def set_locking_column(value = nil, &block)
- define_attr_method :locking_column, value, &block
- value
- end
-
- # The version column used for optimistic locking. Defaults to lock_version.
- def locking_column
- reset_locking_column
- end
-
- # Quote the column name used for optimistic locking.
- def quoted_locking_column
- connection.quote_column_name(locking_column)
- end
-
- # Reset the column used for optimistic locking back to the lock_version default.
- def reset_locking_column
- set_locking_column DEFAULT_LOCKING_COLUMN
- end
-
- # make sure the lock version column gets updated when counters are
- # updated.
- def update_counters_with_lock(id, counters)
- counters = counters.merge(locking_column => 1) if locking_enabled?
- update_counters_without_lock(id, counters)
- end
- end
- end
- end
-end