aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/persistence.rb
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib/active_record/persistence.rb')
-rw-r--r--activerecord/lib/active_record/persistence.rb28
1 files changed, 21 insertions, 7 deletions
diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb
index a1e1073792..466175690e 100644
--- a/activerecord/lib/active_record/persistence.rb
+++ b/activerecord/lib/active_record/persistence.rb
@@ -148,7 +148,7 @@ module ActiveRecord
# Attributes marked as readonly are silently ignored if the record is
# being updated.
def save!(*args)
- create_or_update(*args) || raise(RecordNotSaved.new(nil, self))
+ create_or_update(*args) || raise(RecordNotSaved.new("Failed to save the record", self))
end
# Deletes the record in the database and freezes this instance to
@@ -193,7 +193,7 @@ module ActiveRecord
# and #destroy! raises ActiveRecord::RecordNotDestroyed.
# See ActiveRecord::Callbacks for further details.
def destroy!
- destroy || raise(ActiveRecord::RecordNotDestroyed, self)
+ destroy || raise(RecordNotDestroyed.new("Failed to destroy the record", self))
end
# Returns an instance of the specified +klass+ with the attributes of the
@@ -205,7 +205,9 @@ module ActiveRecord
# instance using the companies/company partial instead of clients/client.
#
# Note: The new instance will share a link to the same attributes as the original class.
- # So any change to the attributes in either instance will affect the other.
+ # Therefore the sti column value will still be the same.
+ # Any change to the attributes on either instance will affect both instances.
+ # If you want to change the sti column as well, use +becomes!+ instead.
def becomes(klass)
became = klass.new
became.instance_variable_set("@attributes", @attributes)
@@ -428,7 +430,7 @@ module ActiveRecord
self
end
- # Saves the record with the updated_at/on attributes set to the current time
+ # Saves the record with the updated_at/on attributes set to the current time
# or the time specified.
# Please note that no validation is performed and only the +after_touch+,
# +after_commit+ and +after_rollback+ callbacks are executed.
@@ -477,11 +479,23 @@ module ActiveRecord
changes[column] = write_attribute(column, time)
end
- changes[self.class.locking_column] = increment_lock if locking_enabled?
-
clear_attribute_changes(changes.keys)
primary_key = self.class.primary_key
- self.class.unscoped.where(primary_key => self[primary_key]).update_all(changes) == 1
+ scope = self.class.unscoped.where(primary_key => _read_attribute(primary_key))
+
+ if locking_enabled?
+ locking_column = self.class.locking_column
+ scope = scope.where(locking_column => _read_attribute(locking_column))
+ changes[locking_column] = increment_lock
+ end
+
+ result = scope.update_all(changes) == 1
+
+ if !result && locking_enabled?
+ raise ActiveRecord::StaleObjectError.new(self, "touch")
+ end
+
+ result
else
true
end