mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Mutation tracker should be cleared before continuing around callbacks
`changes_applied` should be called before continuing around callback chain. Otherwise the mutation tracker returns old value for methods like `changed`? or `id_in_database` in around callbacks. Also methods depend on `id_in_database`, like `update_column`, are not working in `around_create` callbacks. ``` class Foo < ActiveRecord::Base around_create :around_create_callback def around_create_callback ... yield p id_in_database # => nil update_column(:generated_column, generate_value) # silently fails end ... end ```
This commit is contained in:
parent
1353610ff2
commit
34f075fe56
2 changed files with 26 additions and 5 deletions
|
@ -16,9 +16,6 @@ module ActiveRecord
|
|||
|
||||
class_attribute :partial_writes, instance_writer: false, default: true
|
||||
|
||||
after_create { changes_applied }
|
||||
after_update { changes_applied }
|
||||
|
||||
# Attribute methods for "changed in last call to save?"
|
||||
attribute_method_affix(prefix: "saved_change_to_", suffix: "?")
|
||||
attribute_method_prefix("saved_change_to_")
|
||||
|
@ -168,11 +165,15 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
def _update_record(*)
|
||||
partial_writes? ? super(keys_for_partial_write) : super
|
||||
affected_rows = partial_writes? ? super(keys_for_partial_write) : super
|
||||
changes_applied
|
||||
affected_rows
|
||||
end
|
||||
|
||||
def _create_record(*)
|
||||
partial_writes? ? super(keys_for_partial_write) : super
|
||||
id = partial_writes? ? super(keys_for_partial_write) : super
|
||||
changes_applied
|
||||
id
|
||||
end
|
||||
|
||||
def keys_for_partial_write
|
||||
|
|
|
@ -879,6 +879,26 @@ class DirtyTest < ActiveRecord::TestCase
|
|||
raise "changed? should be false" if changed?
|
||||
raise "has_changes_to_save? should be false" if has_changes_to_save?
|
||||
raise "saved_changes? should be true" unless saved_changes?
|
||||
raise "id_in_database should not be nil" if id_in_database.nil?
|
||||
end
|
||||
end
|
||||
|
||||
person = klass.create!(first_name: "Sean")
|
||||
assert_not_predicate person, :changed?
|
||||
end
|
||||
|
||||
test "changed? in around callbacks after yield returns false" do
|
||||
klass = Class.new(ActiveRecord::Base) do
|
||||
self.table_name = "people"
|
||||
|
||||
around_create :check_around
|
||||
|
||||
def check_around
|
||||
yield
|
||||
raise "changed? should be false" if changed?
|
||||
raise "has_changes_to_save? should be false" if has_changes_to_save?
|
||||
raise "saved_changes? should be true" unless saved_changes?
|
||||
raise "id_in_database should not be nil" if id_in_database.nil?
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue