aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionpack/lib/action_dispatch/http/response.rb3
-rw-r--r--activerecord/CHANGELOG.md9
-rw-r--r--activerecord/lib/active_record/associations/builder/belongs_to.rb7
-rw-r--r--activerecord/test/cases/associations/has_many_associations_test.rb9
-rw-r--r--activerecord/test/cases/dirty_test.rb8
-rw-r--r--activesupport/lib/active_support/subscriber.rb22
6 files changed, 49 insertions, 9 deletions
diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb
index 06e936cdb0..60a2cccdc5 100644
--- a/actionpack/lib/action_dispatch/http/response.rb
+++ b/actionpack/lib/action_dispatch/http/response.rb
@@ -55,6 +55,7 @@ module ActionDispatch # :nodoc:
CONTENT_TYPE = "Content-Type".freeze
SET_COOKIE = "Set-Cookie".freeze
LOCATION = "Location".freeze
+ NO_CONTENT_CODES = [204, 304]
cattr_accessor(:default_charset) { "utf-8" }
cattr_accessor(:default_headers)
@@ -289,7 +290,7 @@ module ActionDispatch # :nodoc:
header[SET_COOKIE] = header[SET_COOKIE].join("\n") if header[SET_COOKIE].respond_to?(:join)
- if [204, 304].include?(@status)
+ if NO_CONTENT_CODES.include?(@status)
header.delete CONTENT_TYPE
[status, header, []]
else
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index ad766d3267..d47a23b8f5 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,5 +1,14 @@
## Rails 4.0.0 (unreleased) ##
+* Fix for a regression bug in which counter cache columns were not being updated
+ when record was pushed into a has_many association. For example:
+
+ Post.first.comments << Comment.create
+
+ Fixes #3891.
+
+ *Matthew Robertson*
+
* If a model was instantiated from the database using `select`, `respond_to?`
returns false for non-selected attributes. For example:
diff --git a/activerecord/lib/active_record/associations/builder/belongs_to.rb b/activerecord/lib/active_record/associations/builder/belongs_to.rb
index 3ba6a71366..092230b2f7 100644
--- a/activerecord/lib/active_record/associations/builder/belongs_to.rb
+++ b/activerecord/lib/active_record/associations/builder/belongs_to.rb
@@ -25,9 +25,10 @@ module ActiveRecord::Associations::Builder
mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
def belongs_to_counter_cache_after_create_for_#{name}
- record = #{name}
- record.class.increment_counter(:#{cache_column}, record.id) unless record.nil?
- @_after_create_counter_called = true
+ if record = #{name}
+ record.class.increment_counter(:#{cache_column}, record.id)
+ @_after_create_counter_called = true
+ end
end
def belongs_to_counter_cache_before_destroy_for_#{name}
diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb
index 781b87741d..d85570236f 100644
--- a/activerecord/test/cases/associations/has_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_associations_test.rb
@@ -755,6 +755,15 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert_equal topic.replies.to_a.size, topic.replies_count
end
+ def test_pushing_association_updates_counter_cache
+ topic = Topic.order("id ASC").first
+ reply = Reply.create!
+
+ assert_difference "topic.reload.replies_count", 1 do
+ topic.replies << reply
+ end
+ end
+
def test_deleting_updates_counter_cache_without_dependent_option
post = posts(:welcome)
diff --git a/activerecord/test/cases/dirty_test.rb b/activerecord/test/cases/dirty_test.rb
index 7b2034dadf..36b87033ae 100644
--- a/activerecord/test/cases/dirty_test.rb
+++ b/activerecord/test/cases/dirty_test.rb
@@ -213,9 +213,11 @@ class DirtyTest < ActiveRecord::TestCase
topic = target.create
assert_nil topic.written_on
- topic.written_on = ""
- assert_nil topic.written_on
- assert !topic.written_on_changed?
+ ["", nil].each do |value|
+ topic.written_on = value
+ assert_nil topic.written_on
+ assert !topic.written_on_changed?
+ end
end
end
diff --git a/activesupport/lib/active_support/subscriber.rb b/activesupport/lib/active_support/subscriber.rb
index ab76cf5c85..34c6f900c1 100644
--- a/activesupport/lib/active_support/subscriber.rb
+++ b/activesupport/lib/active_support/subscriber.rb
@@ -1,3 +1,5 @@
+require 'active_support/per_thread_registry'
+
module ActiveSupport
# ActiveSupport::Subscriber is an object set to consume
# ActiveSupport::Notifications. The subscriber dispatches notifications to
@@ -68,8 +70,24 @@ module ActiveSupport
private
- def event_stack
- Thread.current[@queue_key] ||= []
+ def event_stack
+ SubscriberQueueRegistry.get_queue(@queue_key)
+ end
+ end
+
+ # This is a registry for all the event stacks kept for subscribers.
+ #
+ # See the documentation of <tt>ActiveSupport::PerThreadRegistry</tt>
+ # for further details.
+ class SubscriberQueueRegistry # :nodoc:
+ extend PerThreadRegistry
+
+ def initialize
+ @registry = {}
+ end
+
+ def get_queue(queue_key)
+ @registry[queue_key] ||= []
end
end
end