diff options
author | Ryuta Kamizono <kamipo@gmail.com> | 2018-05-26 15:04:41 +0900 |
---|---|---|
committer | Ryuta Kamizono <kamipo@gmail.com> | 2018-05-26 15:04:41 +0900 |
commit | 7ac5b9e8486b90e7a6003a1b5e34b0fd530e6683 (patch) | |
tree | 1873d0225c6ba0c0cfb307b4ee504008a30fbb87 | |
parent | e34c2050e996ffe7ae5feecb005117cd7df4ba74 (diff) | |
download | rails-7ac5b9e8486b90e7a6003a1b5e34b0fd530e6683.tar.gz rails-7ac5b9e8486b90e7a6003a1b5e34b0fd530e6683.tar.bz2 rails-7ac5b9e8486b90e7a6003a1b5e34b0fd530e6683.zip |
Fix `belongs_to_counter_cache_after_update` to respect custom primary key counter
If belongs_to primary key is customized, the callback will update
counters against the wrong target looked up by the customized key as
primary key.
We need to convert the customized key into an object that can be
referred to as primary key.
-rw-r--r-- | activerecord/lib/active_record/associations/builder/belongs_to.rb | 13 | ||||
-rw-r--r-- | activerecord/test/cases/associations/belongs_to_associations_test.rb | 8 |
2 files changed, 20 insertions, 1 deletions
diff --git a/activerecord/lib/active_record/associations/builder/belongs_to.rb b/activerecord/lib/active_record/associations/builder/belongs_to.rb index c161454c1a..852a858d9b 100644 --- a/activerecord/lib/active_record/associations/builder/belongs_to.rb +++ b/activerecord/lib/active_record/associations/builder/belongs_to.rb @@ -49,14 +49,27 @@ module ActiveRecord::Associations::Builder # :nodoc: foreign_key = attribute_in_database foreign_key if foreign_key && model.respond_to?(:increment_counter) + foreign_key = counter_cache_target(reflection, model, foreign_key) model.increment_counter(cache_column, foreign_key) end if foreign_key_was && model_was.respond_to?(:decrement_counter) + foreign_key_was = counter_cache_target(reflection, model_was, foreign_key_was) model_was.decrement_counter(cache_column, foreign_key_was) end end end + + private + def counter_cache_target(reflection, model, foreign_key) + primary_key = reflection.association_primary_key(model) + + if primary_key == model.primary_key + foreign_key + else + model.unscoped.where!(primary_key => foreign_key) + end + end end end diff --git a/activerecord/test/cases/associations/belongs_to_associations_test.rb b/activerecord/test/cases/associations/belongs_to_associations_test.rb index c0dfa91a21..856bc70f6b 100644 --- a/activerecord/test/cases/associations/belongs_to_associations_test.rb +++ b/activerecord/test/cases/associations/belongs_to_associations_test.rb @@ -466,7 +466,13 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase def test_belongs_to_with_primary_key_counter debate = Topic.create("title" => "debate") debate2 = Topic.create("title" => "debate2") - reply = Reply.create("title" => "blah!", "content" => "world around!", "parent_title" => "debate") + reply = Reply.create("title" => "blah!", "content" => "world around!", "parent_title" => "debate2") + + assert_equal 0, debate.reload.replies_count + assert_equal 1, debate2.reload.replies_count + + reply.parent_title = "debate" + reply.save! assert_equal 1, debate.reload.replies_count assert_equal 0, debate2.reload.replies_count |