首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何修正这些增量/递减标记_计数器_缓存方法?

问如何修正这些增量/递减标记_计数器_缓存方法?
EN

Stack Overflow用户
提问于 2012-12-28 10:50:03
回答 2查看 143关注 0票数 0

我在posts_count模型中添加了一个Tag列:

代码语言:javascript
复制
  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:

代码语言:javascript
复制
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时,我得到了这个

代码语言:javascript
复制
 undefined method `tag' for []:ActiveRecord::Relation

我认为这个部分有问题:self.taggings.tag.id,但我不太确定如何修复它。

有什么建议吗?

模型:

代码语言:javascript
复制
**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:

代码语言:javascript
复制
  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:

代码语言:javascript
复制
 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
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-12-28 12:10:06

这个例子有点误导..。

您必须将回调和计数代码放置到标记模型中:

代码语言:javascript
复制
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模型已经知道它的标记(取决于应用程序逻辑)时,必须执行此代码:

代码语言:javascript
复制
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

但把这段代码放在后面的坏主意里。更新帖子时,你会做些什么?根据代码,它将再次增加计数器。当您添加新标记或移除时,您将做什么:您必须为每一种情况编写特殊的代码。真没意思。

票数 1
EN

Stack Overflow用户

发布于 2012-12-28 15:27:58

HOWTO只为具有:=“已发布”的帖子增加计数器

职位模式:

代码语言:javascript
复制
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

标签模型:

代码语言:javascript
复制
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
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14068354

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档