diff options
author | Sergiy Kukunin <sergey.kukunin@gmail.com> | 2019-03-20 12:04:39 +0200 |
---|---|---|
committer | Sergiy Kukunin <sergey.kukunin@gmail.com> | 2019-03-22 19:54:27 +0200 |
commit | 3da0024db472b5697d4b6f17a9e4edefdf4d6a96 (patch) | |
tree | 6ec1a7fea0fcfbbab966903d25cbe948d48d8a8b /activerecord/lib/active_record | |
parent | 7c6343078a566264ce6df6e531c9790ff2d2f432 (diff) | |
download | rails-3da0024db472b5697d4b6f17a9e4edefdf4d6a96.tar.gz rails-3da0024db472b5697d4b6f17a9e4edefdf4d6a96.tar.bz2 rails-3da0024db472b5697d4b6f17a9e4edefdf4d6a96.zip |
Fix unintended autosave on has_one through association
Fixes #35680
The problem occurred, when a `has one through` association contains
a foreign key (it belongs to the intermediate association).
For example, Comment belongs to Post, Post belongs to Author, and Author
`has_one :first_comment, through: :first_post`.
In this case, the value of the foreign key is comparing with the original
record, and since they are likely different, the association is marked
as changed. So it updates every time when the origin record updates.
Diffstat (limited to 'activerecord/lib/active_record')
-rw-r--r-- | activerecord/lib/active_record/autosave_association.rb | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb index d77d76cb1e..fe94662543 100644 --- a/activerecord/lib/active_record/autosave_association.rb +++ b/activerecord/lib/active_record/autosave_association.rb @@ -457,10 +457,16 @@ module ActiveRecord # If the record is new or it has changed, returns true. def record_changed?(reflection, record, key) record.new_record? || - (record.has_attribute?(reflection.foreign_key) && record[reflection.foreign_key] != key) || + association_foreign_key_changed?(reflection, record, key) || record.will_save_change_to_attribute?(reflection.foreign_key) end + def association_foreign_key_changed?(reflection, record, key) + return false if reflection.through_reflection? + + record.has_attribute?(reflection.foreign_key) && record[reflection.foreign_key] != key + end + # Saves the associated record if it's new or <tt>:autosave</tt> is enabled. # # In addition, it will destroy the association if it was marked for destruction. |