From c3e3577f9d5058382504773bf0d32afa15cb131e Mon Sep 17 00:00:00 2001
From: Tom Kadwill <tomkadwill@gmail.com>
Date: Sat, 23 Apr 2016 22:14:10 +0100
Subject: Fix counter_cache double increment bug

---
 .../lib/active_record/associations/belongs_to_association.rb  |  1 +
 .../lib/active_record/associations/builder/belongs_to.rb      |  2 ++
 .../test/cases/associations/belongs_to_associations_test.rb   | 11 +++++++++++
 3 files changed, 14 insertions(+)

diff --git a/activerecord/lib/active_record/associations/belongs_to_association.rb b/activerecord/lib/active_record/associations/belongs_to_association.rb
index 41698c5360..24997370b2 100644
--- a/activerecord/lib/active_record/associations/belongs_to_association.rb
+++ b/activerecord/lib/active_record/associations/belongs_to_association.rb
@@ -61,6 +61,7 @@ module ActiveRecord
 
         def update_counters_on_replace(record)
           if require_counter_update? && different_target?(record)
+            owner.instance_variable_set :@_after_replace_counter_called, true
             record.increment!(reflection.counter_cache_column)
             decrement_counters
           end
diff --git a/activerecord/lib/active_record/associations/builder/belongs_to.rb b/activerecord/lib/active_record/associations/builder/belongs_to.rb
index 346329c610..3121e70a04 100644
--- a/activerecord/lib/active_record/associations/builder/belongs_to.rb
+++ b/activerecord/lib/active_record/associations/builder/belongs_to.rb
@@ -33,6 +33,8 @@ module ActiveRecord::Associations::Builder # :nodoc:
 
           if (@_after_create_counter_called ||= false)
             @_after_create_counter_called = false
+          elsif (@_after_replace_counter_called ||= false)
+            @_after_replace_counter_called = false
           elsif attribute_changed?(foreign_key) && !new_record?
             if reflection.polymorphic?
               model     = attribute(reflection.foreign_type).try(:constantize)
diff --git a/activerecord/test/cases/associations/belongs_to_associations_test.rb b/activerecord/test/cases/associations/belongs_to_associations_test.rb
index a3046d526e..eef70f5691 100644
--- a/activerecord/test/cases/associations/belongs_to_associations_test.rb
+++ b/activerecord/test/cases/associations/belongs_to_associations_test.rb
@@ -700,6 +700,17 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
     assert_equal 17, reply.replies.size
   end
 
+  def test_replace_counter_cache
+    topic = Topic.create(title: "Zoom-zoom-zoom")
+    reply = Reply.create(title: "re: zoom", content: "speedy quick!")
+
+    reply.topic = topic
+    reply.save
+    topic.reload
+
+    assert_equal 1, topic.replies_count
+  end
+
   def test_association_assignment_sticks
     post = Post.first
 
-- 
cgit v1.2.3