module Twigg::Cacher

The Cacher module is an abstraction around caching that offers two public methods, {Twigg::Cacher.get} and {Twigg::Cacher.set}.

If the twigg-cache gem is installed and enabled, delegates the storing of cached items to Memcached. In the absence of the gem, every cache lookup is treated as a miss.

Public Class Methods

get(key, *args, &block) click to toggle source

Gets stored value for `key`; in the event of a cache miss, yields to `block`, and caches and returns the result. `*args`, if present, are hashed and appended to key to permit the results of different calls to the same method to be conveniently stored and retrieved independently.

Note: if a `nil` or `false` value is ever stored in the cache, this method will consider any lookup of the corresponding key to be a miss, because we employ a simple truthiness check to determine presence.

# File lib/twigg/cacher.rb, line 28
def get(key, *args, &block)
  raise ArgumentError, 'block required by not given' unless block_given?
  digest = hashed_key_and_args(key, *args)
  client.get(digest) || set(key, *args, &block)
end
set(key, *args) { || ... } click to toggle source

Stores the result of yielding to `block` in the cache, with `key` as key, and returns the result.

As with {get}, any `*args`, if present, are hashed and appended to the key to premit the results of different calls to the same method to be conveniently stored and retrieved independently.

# File lib/twigg/cacher.rb, line 40
def set(key, *args, &block)
  digest = hashed_key_and_args(key, *args)
  yield.tap { |result| client.set(digest, result) }
end

Private Class Methods

caching?() click to toggle source
# File lib/twigg/cacher.rb, line 51
def caching?
  return false unless Config.cache.enabled # don't want to load the gem
  return true if defined?(Twigg::Cache)    # gem was already loaded
  with_dependency('twigg-cache') { true }  # will die if can't load
end
client() click to toggle source
# File lib/twigg/cacher.rb, line 47
def client
  @client ||= (caching? ? Cache::Client.new : DummyClient.new)
end
hashed_key_and_args(key, *args) click to toggle source

Produces a composite cache key based on `key` and a digest of `args`.

If `args` contains non-shallow objects such as hashes or arrays, uses recursion to incorporate the contents of those objects in the digest.

Will raise an exception if `args` or any object encontered via recursion is not a “simple” object (Hash, Array, String, NilClass, Numeric, or Symbol).

# File lib/twigg/cacher.rb, line 65
def hashed_key_and_args(key, *args)
  base = args.inject('') do |memo, arg|
    memo << (':' + arg.class.to_s + ':') << case arg
    when Array
      hashed_key_and_args(key, *arg)
    when Hash
      hashed_key_and_args(key, *arg.to_a)
    when NilClass, Numeric, String, Symbol
      arg.to_s
    else
      raise ArgumentError, 'can only compute digest for primitive objects'
    end

    Digest::SHA1::hexdigest(memo)
  end

  key + ':' + base
end