我有两个模型,我通过关联使用多态has_many链接在一起,我想添加一个counter_cache但似乎Rails / ActiveRecord不支持开箱即用的这个功能。
class Classifiable < ActiveRecord::Base
has_many :classifications, :as => :classifiable, :foreign_key => :classifiable_id
end
class Taxonomy < ActiveRecord::Base
has_many :classifications, :as => :taxonomy, :foreign_key => :taxonomy_id
end
class Question < Classifiable
has_many :categories, :through => :classifications, :as => :classifiable, :source => :taxonomy, :source_type => "Category"
end
class Category < Taxonomy
has_many :questions, :through => :classifications, :source => :classifiable, :source_type => "Question"
end
class Classification < ActiveRecord::Base
attr_accessible :classifiable, :classifiable_id, :classifiable_type,
:taxonomy, :taxonomy_id, :taxonomy_type
belongs_to :classifiable, :polymorphic => true
belongs_to :taxonomy, :polymorphic => true
end
答案 0 :(得分:10)
只需修改以下分类模型:
class Classification < ActiveRecord::Base
attr_accessible :classifiable, :classifiable_id, :classifiable_type,
:taxonomy, :taxonomy_id, :taxonomy_type
belongs_to :classifiable, :polymorphic => true
belongs_to :taxonomy, :polymorphic => true
before_create :increment_counter
before_destroy :decrement_counter
private
# increments the right classifiable counter for the right taxonomy
def increment_counter
self.taxonomy_type.constantize.increment_counter("#{self.classifiable_type.downcase.pluralize}_count", self.taxonomy_id)
end
# decrements the right classifiable counter for the right taxonomy
def decrement_counter
self.taxonomy_type.constantize.decrement_counter("#{self.classifiable_type.downcase.pluralize}_count", self.taxonomy_id)
end
end
另外,请确保分类表中包含以下列:
t.integer :questions_count, :null => false, :default => 0
t.integer :other_classifiables_count, :null => false, :default => 0
t.integer :other_classifiables_count, :null => false, :default => 0
t.integer :other_classifiables_count, :null => false, :default => 0
将“other_classifiables_count”更改为您需要的内容(“answers_count”,“users_count”等)
答案 1 :(得分:3)
看起来Rails在调用delete时没有通过before / after_destroy回调(当你删除一个有多个关联时会发生什么)。
相反,您可以使用关联的回调#before_add
和#before_remove
:
class Question < Classifiable
has_many :categories, through: :classifications,
as: :classifiable,
source: :taxonomy,
source_type: Category,
before_add: :increment_counter
def increment_counter(category)
# increment counter, etc.
end
end
答案 2 :(得分:2)
要稍微修改Jonathan的答案,你可以让它在增量/减量之前查找列类型以查看它是否存在。我也把它干掉了一点:
def increment_counter(direction=:increment)
ar_class = self.taxonomy_type.constantize
ar_column = "#{self.taxonomy_type.underscore.pluralize}_count"
if ar_class.columns.include? ar_column
ar_class.send "#{direction}_counter", ar_column, self.taxonomy_id
end
end
def decrement_counter
increment_counter :decrement
end
哦,它适用于MultiWordClassNames
。 underscore
执行了downcase
,因此我的版本省略了它。