aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
authorRyuta Kamizono <kamipo@gmail.com>2018-05-26 15:04:41 +0900
committerRyuta Kamizono <kamipo@gmail.com>2018-05-26 15:04:41 +0900
commit7ac5b9e8486b90e7a6003a1b5e34b0fd530e6683 (patch)
tree1873d0225c6ba0c0cfb307b4ee504008a30fbb87 /activerecord
parente34c2050e996ffe7ae5feecb005117cd7df4ba74 (diff)
downloadrails-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.
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/lib/active_record/associations/builder/belongs_to.rb13
-rw-r--r--activerecord/test/cases/associations/belongs_to_associations_test.rb8
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