diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb index 828a8b41b63b1..44264bec7fa3f 100644 --- a/activerecord/lib/active_record/persistence.rb +++ b/activerecord/lib/active_record/persistence.rb @@ -111,6 +111,7 @@ def update_attribute(name, value) if record_update_timestamps timestamp_attributes_for_update_in_model.each do |column| hash[column] = read_attribute(column) + @changed_attributes.delete(column.to_s) end end diff --git a/activerecord/lib/active_record/timestamp.rb b/activerecord/lib/active_record/timestamp.rb index 1075a60f07b32..5cddd07e82e9f 100644 --- a/activerecord/lib/active_record/timestamp.rb +++ b/activerecord/lib/active_record/timestamp.rb @@ -21,24 +21,22 @@ module Timestamp end # Saves the record with the updated_at/on attributes set to the current time. - # If the save fails because of validation errors, an - # ActiveRecord::RecordInvalid exception is raised. If an attribute name is passed, - # that attribute is used for the touch instead of the updated_at/on attributes. + # Please note that no validation is performed and no callbacks are executed. + # If an attribute name is passed, that attribute is updated along with + # updated_at/on attributes. # # Examples: # - # product.touch # updates updated_at - # product.touch(:designed_at) # updates the designed_at attribute + # product.touch # updates updated_at/on + # product.touch(:designed_at) # updates the designed_at attribute and updated_at/on def touch(attribute = nil) current_time = current_time_from_proper_timezone if attribute - write_attribute(attribute, current_time) + self.update_attribute(attribute, current_time) else - timestamp_attributes_for_update_in_model.each { |column| write_attribute(column.to_s, current_time) } + timestamp_attributes_for_update_in_model.each { |column| self.update_attribute(column, current_time) } end - - save! end private diff --git a/activerecord/test/cases/timestamp_test.rb b/activerecord/test/cases/timestamp_test.rb index 549c4af6b174f..f765540808703 100644 --- a/activerecord/test/cases/timestamp_test.rb +++ b/activerecord/test/cases/timestamp_test.rb @@ -25,16 +25,26 @@ def test_saving_a_unchanged_record_doesnt_update_its_timestamp end def test_touching_a_record_updates_its_timestamp + previous_salary = @developer.salary + @developer.salary = previous_salary + 10000 @developer.touch assert_not_equal @previously_updated_at, @developer.updated_at + assert_equal previous_salary + 10000, @developer.salary + assert @developer.salary_changed?, 'developer salary should have changed' + assert @developer.changed?, 'developer should be marked as changed' + @developer.reload + assert_equal previous_salary, @developer.salary end def test_touching_a_different_attribute previously_created_at = @developer.created_at @developer.touch(:created_at) + assert !@developer.created_at_changed? , 'created_at should not be changed' + assert !@developer.changed?, 'record should not be changed' assert_not_equal previously_created_at, @developer.created_at + assert_not_equal @previously_updated_at, @developer.updated_at end def test_saving_a_record_with_a_belongs_to_that_specifies_touching_the_parent_should_update_the_parent_updated_at