Skip to content

Commit

Permalink
Require explicit counter_cache option for has_many
Browse files Browse the repository at this point in the history
Previously has_many associations assumed a counter_cache was to be used
based on the presence of an appropriately named column. This is
inconsistent, since the inverse belongs_to association will not make
this assumption. See issues #19042 #8446.
This commit checks for the presence of the counter_cache key in the
options of either the has_many or belongs_to association as well as
ensuring that the *_count column is present.
  • Loading branch information
tristang committed Apr 7, 2015
1 parent 693b333 commit e0cb21f
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 6 deletions.
Expand Up @@ -80,8 +80,15 @@ def count_records
[association_scope.limit_value, count].compact.min
end


# Returns whether a counter cache should be used for this association.
#
# The counter_cache option must be given on either the owner or inverse
# association, and the column must be present on the owner.
def has_cached_counter?(reflection = reflection())
owner.attribute_present?(cached_counter_attribute_name(reflection))
if reflection.options[:counter_cache] || (inverse = inverse_which_updates_counter_cache(reflection)) && inverse.options[:counter_cache]
owner.attribute_present?(cached_counter_attribute_name(reflection))
end
end

def cached_counter_attribute_name(reflection = reflection())
Expand Down
2 changes: 1 addition & 1 deletion activerecord/test/models/categorization.rb
@@ -1,6 +1,6 @@
class Categorization < ActiveRecord::Base
belongs_to :post
belongs_to :category
belongs_to :category, counter_cache: true
belongs_to :named_category, :class_name => 'Category', :foreign_key => :named_category_name, :primary_key => :name
belongs_to :author

Expand Down
8 changes: 4 additions & 4 deletions activerecord/test/models/post.rb
Expand Up @@ -98,11 +98,11 @@ def add_joins_and_select
end
end

has_many :taggings_with_delete_all, :class_name => 'Tagging', :as => :taggable, :dependent => :delete_all
has_many :taggings_with_destroy, :class_name => 'Tagging', :as => :taggable, :dependent => :destroy
has_many :taggings_with_delete_all, :class_name => 'Tagging', :as => :taggable, :dependent => :delete_all, counter_cache: :taggings_with_delete_all_count
has_many :taggings_with_destroy, :class_name => 'Tagging', :as => :taggable, :dependent => :destroy, counter_cache: :taggings_with_destroy_count

has_many :tags_with_destroy, :through => :taggings, :source => :tag, :dependent => :destroy
has_many :tags_with_nullify, :through => :taggings, :source => :tag, :dependent => :nullify
has_many :tags_with_destroy, :through => :taggings, :source => :tag, :dependent => :destroy, counter_cache: :tags_with_destroy_count
has_many :tags_with_nullify, :through => :taggings, :source => :tag, :dependent => :nullify, counter_cache: :tags_with_nullify_count

has_many :misc_tags, -> { where :tags => { :name => 'Misc' } }, :through => :taggings, :source => :tag
has_many :funky_tags, :through => :taggings, :source => :tag
Expand Down

0 comments on commit e0cb21f

Please sign in to comment.