我在posts_count
模型中添加了Tag
列:
create_table "tags", :force => true do |t|
t.string "name"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "posts_count", :default => 0, :null => false
end
现在我正在尝试根据这个问题为他们构建一个计数器缓存(为多对多关联创建一个计数器缓存):Counter cache for a model with a many-to-many association
post.rb:
private
after_create :increment_tag_counter_cache
after_destroy :decrement_tag_counter_cache
def increment_tag_counter_cache
Tag.increment_counter(:posts_count, self.taggings.tag.id)
end
def decrement_tag_counter_cache
Tag.decrement_counter(:posts_count, self.taggings.tag.id)
end
但是当我创建Post
:
undefined method `tag' for []:ActiveRecord::Relation
我认为这部分有问题:self.taggings.tag.id
但我不太确定如何修复它。
有什么建议吗?
型号:
**post.rb:**
has_many :taggings, dependent: :destroy
has_many :tags, through: :taggings
**tag.rb:**
has_many :taggings, :dependent => :destroy
has_many :posts, :through => :taggings
**tagging:**
attr_accessible :tag_id, :post_id
belongs_to :post
belongs_to :tag
修改
post.rb:
before_save :publish_post
protected
def publish_post
if self.status == "Published" && self.published_at.nil?
self.published_at = Time.now
end
end
tagging.rb:
private
def increment_tag_counter_cache
if self.post.status == "Published" && self.post.published_at.nil?
Tag.increment_counter(:posts_count, self.tag.id)
end
end
答案 0 :(得分:1)
这个例子有点误导......
您必须将回调和计数代码放入标记模型:
private
after_create :increment_tag_counter_cache
after_destroy :decrement_tag_counter_cache
def increment_tag_counter_cache
Tag.increment_counter(:posts_count, self.tag.id) #
end
def decrement_tag_counter_cache
Tag.decrement_counter(:posts_count, self.tag.id)
end
您可以将其保留在Post中,但在这种情况下,您必须为所有已分配的标记增加计数器。当post模型已经知道它的标签时(取决于app逻辑),必须执行此代码:
def increment_tag_counter_cache
tags.each do |tag| # if .tags contain Tag objects... or has_many :tags, :through => :tagggings
Tag.increment_counter(:posts_count, tag.id)
end
end
但是把这段代码留在Post - 坏主意。更新帖子后你会做什么?根据代码,它将再次增加计数器。添加新标签或删除时,您将做什么:您必须为每个案例编写特殊代码。很糟糕。
答案 1 :(得分:1)
HOWTO 仅针对以下帖子递增计数器:status =“已发布”
发布模型:
after_save :increment_tag_counters # covers :save, :create, :update methods
before_destroy :correct_tag_counters
def published?
self.status == "Published"
end
def increment_tag_counters? # if changes provided and previous status wasn't "published"
status_changed? && changed_attributes["status"] != "Published"
end
def decrement_tag_counters? # if changes provides and previous status was "published"
status_changed? && changed_attributes["status"] == "Published"
end
def increment_tag_counters
if published? && increment_tag_counters?
taggings.each {|tagging| tagging.increment_tag_counter_cache}
elsif decrement_tag_counters?
taggings.each {|tagging| tagging.decrement_tag_counter_cache}
end
end
def correct_tag_counters
if published?
taggings.each {|tagging| tagging.decrement_tag_counter_cache}
end
end
标记模型:
after_create :increment_tag_counter_cache
after_destroy :decrement_tag_counter_cache
def increment_tag_counter_cache
Tag.increment_counter(:posts_count, self.tag.id) if post.published?
end
def decrement_tag_counter_cache
Tag.decrement_counter(:posts_count, self.tag.id) if !post.published? || post.decrement_tag_counters?
end