Skip to content

Commit

Permalink
Docs: Improve method docs.
Browse files Browse the repository at this point in the history
  • Loading branch information
nate00 committed May 12, 2016
1 parent 294528b commit a0858ce
Showing 1 changed file with 76 additions and 36 deletions.
112 changes: 76 additions & 36 deletions lib/cached_counts.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,46 +5,62 @@ module CachedCounts
extend ActiveSupport::Concern

module ClassMethods
# Cache the count for a scope in memcached.
# Cache the count for a scope in Memcached.
#
# e.g.
# User.caches_count_where :confirmed
# > User.confirmed_count # User.confirmed.count, but cached
# For example, if you have a model:
# class Post < ActiveRecord::Base
# scope :sponsored, -> { where(sponsored: true) }
# caches_count_where :sponsored
# end
#
# Automatically adds after_commit hooks which increment/decrement the value
# in memcached when needed. Queries the db on cache miss.
# Then you can call
# Post.sponsored_count
# to fetch the number of sponsored posts from Memcached.
#
# Defines a few class methods:
# [+#{attribute_name}_count+]
# The number of models in the scope.
# [+#{attribute_name}_key+]
# The key in Memcached that stores the count.
# [+#{attribute_name}_count=(value)+]
# Sets the value of the count.
# [+expire_#{attribute_name}_count+]
# Deletes the key from Memcached.
#
# @param [String] attribute_name
# The name that appears in generated method names.
#
# @param [Hash] options
#
# @option options [String] :scope
# Name of the scope to count. Defaults to the +attribute_name+
# (the required argument to +caches_count_where+).
# Name of the scope to count. Defaults to the +attribute_name+.
#
# @option options [String, Array<String>] :alias
# Alias(es) for the count attribute.
# e.g.
# caches_count_where :confirmed, alias: 'sitemap'
# > User.sitemap_count
# Alias(es) for the count attribute. For example:
# class Post < ActiveRecord::Base
# # ...
# caches_count_where :sponsored, alias: 'paid'
# end
#
# Post.paid_count
#
# @option options [Integer] :expires_in
# Expiry for the cached value.
#
# @option options [Proc] :if
# proc passed through to the after_commit hooks;
# decides whether an object counts towards the association total.
# Proc that decides whether an object is included in the count.
#
# @option options [Integer, #to_s] :version
# Cache version - bump if you change the definition of a count.
#
# @option options [Proc] :race_condition_fallback
# Fallback to the result of this proc if the cache is empty, while
# loading the actual value from the db. Works similarly to
# +race_condition_ttl+ but for empty caches rather than expired values.
# Meant to prevent a thundering-herd scenario, if for example a
# memcached instance goes away. Can be nil; defaults to using a value
# grabbed from the cache or DB at startup.
# On cache miss, first write the result of this proc to the cache (to
# prevent a thundering herd), and then perform the count and update the
# cache.
#
# Defaults to a value grabbed from the cache or the database at startup.
#
# @return [void]
#
def caches_count_where(attribute_name, options = {})
# Delay actual run to work around circular dependencies
Expand All @@ -54,43 +70,67 @@ def caches_count_where(attribute_name, options = {})
end
end

# Cache the count for an association in memcached.
# Cache the count for an association in Memcached.
#
# e.g.
# User.caches_count_of :friends
# > User.first.friends_count # Users.first.friends.count, but cached
# For example, if you have a model:
# class Post < ActiveRecord::Base
# has_many :comments
# caches_count_of :comments
# end
#
# Automatically adds after_commit hooks to the associated class which
# increment/decrement the value in memcached when needed. Queries the db
# on cache miss.
# Then you can call
# Post.first.comments_count
# to fetch the number of sponsored posts from Memcached.
#
# Defines a few instance methods:
# [+#{attribute_name}_count+]
# The number of models in the association.
# [+#{attribute_name}_key+]
# The key in Memcached that stores the count.
# [+#{attribute_name}_count=(value)+]
# Sets the value of the count.
# [+expire_#{attribute_name}_count+]
# Deletes the key from Memcached.
#
# And a few class methods:
# [+#{attribute_name}_count_for(id)+]
# The number of models associated with the given +id+.
# [+#{attribute_name}_count_key(id)+]
# The key in Memcached that stores the count for the given +id+.
#
# @param [String] attribute_name
# The name that appears in the generated method names.
#
# @param [Hash] options
#
# @option options [Symbol] :association
# Name of the association to count. Defaults to the +attribute_name+
# (the required argument to +caches_count_of+).
# Name of the association to count. Defaults to the +attribute_name+.
#
# @option options [String, Array<String>] :alias
# Alias(es) for the count attribute. Useful with join tables.
# e.g.
# caches_count_of :user_departments, alias: 'users'
# > Department.first.users_count
# Alias(es) for the count attribute. For example:
# class Post < ActiveRecord::Base
# # ...
# caches_count_of :comments, alias: 'replies'
# end
#
# Post.first.replies_count
#
# @option options [Integer] :expires_in
# Expiry for the cached value.
#
# @option options [Proc] :if
# proc passed through to the after_commit hooks on the counted class;
# decides whether an object counts towards the association total.
# Proc that decides whether an object is included in the count. (You must
# also specify +:scope+.)
#
# @option options [Proc] :scope
# proc used like an ActiveRecord scope on the counted class on cache misses.
# Proc used like an ActiveRecord scope to decide which objects are
# included in the count. (You must also specify +:if+.)
#
# @option options [Integer, #to_s] :version
# Cache version - bump if you change the definition of a count.
#
# @return [void]
#
def caches_count_of(attribute_name, options = {})
# Delay actual run to work around circular dependencies
klass = self
Expand Down

0 comments on commit a0858ce

Please sign in to comment.