0

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

标记.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
4

2 回答 2

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

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 中 - 坏主意。更新帖子时你会做什么?根据代码,它将再次增加计数器。当您添加新标签或删除标签时,您会做什么:您必须为每种情况编写特殊代码。糟透了。

于 2012-12-28T12:10:06.853 回答
1

HOWTO只为具有 :status = "Published" 的帖子增加计数器

岗位型号:

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
于 2012-12-28T15:27:58.387 回答