Skip to content

Instantly share code, notes, and snippets.

@a-chernykh
Created July 14, 2011 11:49
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save a-chernykh/1082313 to your computer and use it in GitHub Desktop.
Save a-chernykh/1082313 to your computer and use it in GitHub Desktop.
Mongoid counter cache
class Forum
include Mongoid::Document
include Mongoid::Timestamps
field :posts_count, :type => Integer, :default => 0
has_many_related :posts
end
module Mongoid
module CounterCache
extend ActiveSupport::Concern
module ClassMethods
def counter_cache(options)
name = options[:name]
counter_field = options[:field]
after_create do |document|
relation = document.send(name)
relation.collection.update(relation._selector, {'$inc' => {counter_field.to_s => 1}}, {:multi => true})
end
after_destroy do |document|
relation = document.send(name)
relation.collection.update(relation._selector, {'$inc' => {counter_field.to_s => -1}}, {:multi => true})
end
end
end
end
end
class Post
include Mongoid::Document
include Mongoid::Timestamps
include Mongoid::CounterCache
counter_cache :name => 'forum', :field => 'posts_count'
belongs_to_related :forum
end
@jeffreyiacono
Copy link

why do you use :multi => true? For a given Post, it would belong to one Forum, so on create / destroy it would only be updating the counter cache for a singular document in a collection, no? Thanks for sharing, I ended up using a variation of this to handle embedded documents and a counter cache in the parent.

@a-chernykh
Copy link
Author

you're right. to be honest, :multi => true is just copy-paste :)

@jeffreyiacono
Copy link

no prob, I've done that thousands of times! I just wanted to make sure I wasn't missing something (still in the shallow end when it comes to Mongo / Mongoid). Thanks for the heads up.

@noiseunion
Copy link

I'm sure I'm missing something simple, but I keep getting an error on "relation._selector": undefined method "_selector". Any thoughts to help a guy out?

@danil-z
Copy link

danil-z commented Oct 26, 2011

Where mongoid_counter_cache.rb is should be placed? /lib ? how to automatically load it in rails 3.1?

@noiseunion
Copy link

I ended up putting it in my concerns directory "app/concerns/mongoid/counter_cache.rb". I haven't used 3.1 yet, but I'm assuming you'd add which ever directory into your load path, which is in "config/application.rb". I have a line that looks like this in mine: "config.autoload_paths += %W(#{config.root}/lib)". However, if you put it in as a concern, anything in the "app" directory will be loaded up automatically anyway.

@jeffreyiacono
Copy link

added mine to config/initializers as I wanted it autoloaded / included for all

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment