aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib
diff options
context:
space:
mode:
authorJeremy Kemper <jeremy@bitsweat.net>2007-05-25 21:31:44 +0000
committerJeremy Kemper <jeremy@bitsweat.net>2007-05-25 21:31:44 +0000
commitc4a31560bd686cbd16b4af20e764a9a0660cd170 (patch)
tree348ad796c4b80d0a227640bf135141c417f4dfbf /activerecord/lib
parent38deb0ed83c54444e091d39382dcfe58e1c0bd05 (diff)
downloadrails-c4a31560bd686cbd16b4af20e764a9a0660cd170.tar.gz
rails-c4a31560bd686cbd16b4af20e764a9a0660cd170.tar.bz2
rails-c4a31560bd686cbd16b4af20e764a9a0660cd170.zip
Optimistic locking: revert the lock version when an update fails. Closes #7840. Also return the number of affected rows instead of true.
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@6843 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
Diffstat (limited to 'activerecord/lib')
-rw-r--r--activerecord/lib/active_record/locking/optimistic.rb39
1 files changed, 23 insertions, 16 deletions
diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb
index 23e7239d5e..d8f9dee372 100644
--- a/activerecord/lib/active_record/locking/optimistic.rb
+++ b/activerecord/lib/active_record/locking/optimistic.rb
@@ -2,7 +2,7 @@ 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
+ # 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.
#
@@ -16,10 +16,10 @@ module ActiveRecord
#
# 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
#
@@ -53,16 +53,16 @@ module ActiveRecord
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
@@ -73,18 +73,25 @@ module ActiveRecord
previous_value = send(lock_col)
send(lock_col + '=', previous_value + 1)
- 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))}
- WHERE #{self.class.primary_key} = #{quote_value(id)}
- AND #{self.class.quoted_locking_column} = #{quote_value(previous_value)}
- end_sql
+ 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))}
+ 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
+ unless affected_rows == 1
+ raise ActiveRecord::StaleObjectError, "Attempted to update a stale object"
+ end
- return true
+ affected_rows
+
+ # If something went wrong, revert the version.
+ rescue Exception
+ send(lock_col + '=', previous_value)
+ raise
+ end
end
module ClassMethods