Skip to content

Commit 976c487

Browse files
authored
Merge pull request rails#47767 from joshuay03/fix-updated-at-not-updating-in-before-update
Fix rails#45389 | `updated_at` not updating in `before_update` callback
2 parents bb4cc27 + f2d622a commit 976c487

File tree

3 files changed

+96
-9
lines changed

3 files changed

+96
-9
lines changed

activerecord/lib/active_record/callbacks.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,7 @@ def _create_record
446446
end
447447

448448
def _update_record
449-
_run_update_callbacks { super }
449+
_run_update_callbacks { record_update_timestamps { super } }
450450
end
451451
end
452452
end

activerecord/lib/active_record/timestamp.rb

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,17 @@ def _create_record
115115
end
116116

117117
def _update_record
118+
record_update_timestamps
119+
120+
super
121+
end
122+
123+
def create_or_update(touch: true, **)
124+
@_touch_record = touch
125+
super
126+
end
127+
128+
def record_update_timestamps
118129
if @_touch_record && should_record_timestamps?
119130
current_time = current_time_from_proper_timezone
120131

@@ -124,12 +135,7 @@ def _update_record
124135
end
125136
end
126137

127-
super
128-
end
129-
130-
def create_or_update(touch: true, **)
131-
@_touch_record = touch
132-
super
138+
yield if block_given?
133139
end
134140

135141
def should_record_timestamps?

activerecord/test/cases/timestamp_test.rb

Lines changed: 83 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,60 @@ def change_name
253253
assert_not_equal @previously_updated_at, @developer.updated_at
254254
end
255255

256+
def test_saving_an_unchanged_record_with_a_mutating_before_update_callback_updates_its_timestamp
257+
klass = Class.new(ActiveRecord::Base) do
258+
self.table_name = "developers"
259+
260+
include Developer::TimestampAliases
261+
262+
before_update :change_name
263+
264+
private
265+
def change_name
266+
return if new_record?
267+
268+
self.name = "Jack Bauer"
269+
end
270+
end
271+
272+
@developer = klass.create!
273+
@previously_updated_at = @developer.updated_at
274+
@previous_name = @developer.name
275+
276+
travel(1.second) do
277+
@developer.save!
278+
end
279+
280+
@developer.reload
281+
282+
assert_not_equal @previous_name, @developer.name
283+
assert_not_equal @previously_updated_at, @developer.updated_at
284+
end
285+
286+
def test_saving_an_unchanged_record_with_a_non_mutating_before_update_callback_does_not_update_its_timestamp
287+
klass = Class.new(ActiveRecord::Base) do
288+
self.table_name = "developers"
289+
290+
include Developer::TimestampAliases
291+
292+
before_update :change_name
293+
294+
private
295+
def change_name; end
296+
end
297+
298+
@developer = klass.create!
299+
@previously_updated_at = @developer.updated_at
300+
301+
travel(1.second) do
302+
@developer.save!
303+
end
304+
305+
@developer.reload
306+
307+
assert_equal @previously_updated_at, @developer.updated_at
308+
end
309+
256310
def test_saving_a_record_with_a_belongs_to_that_specifies_touching_the_parent_should_update_the_parent_updated_at
257311
pet = Pet.first
258312
owner = pet.owner
@@ -469,7 +523,34 @@ def self.name; "Toy"; end
469523
assert_not_equal time, pet.updated_at
470524
end
471525

472-
def test_timestamp_column_values_are_present_in_the_callbacks
526+
def test_timestamp_column_values_are_present_in_create_callbacks
527+
klass = Class.new(ActiveRecord::Base) do
528+
self.table_name = "people"
529+
530+
before_create do
531+
self.born_at = created_at
532+
end
533+
end
534+
535+
person = klass.create first_name: "David"
536+
assert_not_nil person.born_at
537+
end
538+
539+
def test_timestamp_column_values_are_present_in_update_callbacks
540+
klass = Class.new(ActiveRecord::Base) do
541+
self.table_name = "people"
542+
543+
before_update do
544+
self.born_at = created_at
545+
end
546+
end
547+
548+
person = klass.create first_name: "David"
549+
person.update first_name: "John"
550+
assert_not_nil person.born_at
551+
end
552+
553+
def test_timestamp_column_values_are_present_in_save_callbacks
473554
klass = Class.new(ActiveRecord::Base) do
474555
self.table_name = "people"
475556

@@ -479,7 +560,7 @@ def test_timestamp_column_values_are_present_in_the_callbacks
479560
end
480561

481562
person = klass.create first_name: "David"
482-
assert_not_equal person.born_at, nil
563+
assert_not_nil person.born_at
483564
end
484565

485566
def test_timestamp_attributes_for_create_in_model

0 commit comments

Comments
 (0)