Rails Mongoid::CounterCache,ruby-china 源码

hz_qiuyuanxin · 2013年08月26日 · 最后由 lihuazhang 回复于 2015年11月12日 · 4371 次阅读

今天在开发项目遇到一个问题,即一个模型要按其 embeded document 的 length 排序。

虽然最简单的就是加一个冗余字段 counter 之类的,但是还是先看看文档和 google 一把,最终还是没找到答案。

后来想想,ruby-china 源码应该有关于这方面的,哈哈,于是就想看看是怎么做的。

结果发现也是没有,但是却发现了 CounterCache 这个类,用于 cache 一些 counter。

代码也是十分简单。

module Mongoid
  module CounterCache
    extend ActiveSupport::Concern

    module ClassMethods
      def counter_cache(metadata)
        counter_name = "#{metadata[:inverse_of]}_count"

        set_callback(:create, :after) do |document|
          relation = document.send(metadata[:name])
          if relation
            relation.inc(counter_name.to_sym => 1) if relation.class.fields.keys.include?(counter_name)
          end
        end

        set_callback(:destroy, :after) do |document|
          relation = document.send(metadata[:name])
          if relation && relation.class.fields.keys.include?(counter_name)
            relation.inc(counter_name.to_sym => -1)
          end
        end

      end

    end #ClassMethods

  end #CounterCache
end #Mongoid

使用也十分简单,如在 reply 模型里(部分)

class Reply
  include Mongoid::Document
  include Mongoid::Timestamps
  include Mongoid::BaseModel
  include Mongoid::CounterCache
  include Mongoid::SoftDelete
  include Mongoid::MarkdownBody
  include Mongoid::Mentionable
  include Mongoid::Likeable

  belongs_to :user, :inverse_of => :replies
  belongs_to :topic, :inverse_of => :replies, touch: true

  counter_cache :name => :user, :inverse_of => :replies
  counter_cache :name => :topic, :inverse_of => :replies
end

这样的话,每 create 或者 destroy 一个 reply,则会自动更新 user 和 topic 模型里的 replies_count 这个字段。

哈哈,打算把这种思路引入到项目里来。

我是新手,看不懂,想请教 个问题,我用 grape 做 api 可是返回的中文乱码,请问是什么原因,帮忙谢谢

返回的代码就一句:joke 表的全部 Joke.all

在我潜意识里,用应用数据库保存的都不应该叫 cache,但现代看来是自己狭隘了

#2 楼 @shatle 有了字段就不必 count() 了

#2 楼 @shatle 不是的,你看清楚,在这里用这个的原因是因为用了 MongoDB,mysql 估计支持这个排序的,MongoDB 文档里并不支持对 embeded document 进行 count 之后的一个排序。

所以需要所一个字段来做冗余,以做排序用。

#1 楼 @brant 我也是菜鸟,你说的 grape 是 ?

@brant 在另外一个帖子也看到你的这段话了,怎么搞得我感觉是机器自动发的=。=|||

@brant 第一行加

#encoding: utf-8

#6 楼 @Blues 不好意思,我不知道会不会有人看到,所以。。就这两处。。。

#7 楼 @jjzxcc Thank you 晚上回家试下。。

#7 楼 @jjzxcc 加到 api.rb 的第一行报错。加到里面也报错。。rails s 运行不了

@brant 报什么错。

#2 楼 @shatle 用快的、少的来暂时替代满的、多的,都叫缓存吧

每 create 或者 destroy 一个 reply,则会自动更新 user 和 topic 模型里的 replies_count 这个字段。

这样子,有问题,rubychina 现在的问题,我在 A node 发了一个帖子,然后把这个帖子更新到 B node。就不会更新 node 里面的 topic_count

需要 登录 后方可回复, 如果你还没有账号请 注册新账号