class MethodCache::Proxy
Constants
- NULL
Attributes
args[R]
method_name[R]
opts[R]
target[R]
Public Class Methods
new(method_name, opts)
click to toggle source
# File lib/method_cache/proxy.rb, line 12 def initialize(method_name, opts) opts[:cache] ||= :counters if opts[:counter] @method_name = method_name @opts = opts end
Public Instance Methods
bind(target, args)
click to toggle source
# File lib/method_cache/proxy.rb, line 18 def bind(target, args) self.clone.bind!(target, args) end
bind!(target, args)
click to toggle source
# File lib/method_cache/proxy.rb, line 22 def bind!(target, args) @target = target @args = args @key = nil self end
cache()
click to toggle source
# File lib/method_cache/proxy.rb, line 115 def cache if @cache.nil? @cache = opts[:cache] || MethodCache.default_cache @cache = Memcache.pool[@cache] if @cache.kind_of?(Symbol) if not @cache.respond_to?(:[]) and @cache.respond_to?(:get) @cache.metaclass.module_eval do define_method :[] do |key| get(key) end end end end @cache end
cached?()
click to toggle source
# File lib/method_cache/proxy.rb, line 46 def cached? not cache[key].nil? end
cached_at()
click to toggle source
# File lib/method_cache/proxy.rb, line 149 def cached_at cache.cached_at(key) if cache.respond_to?(:cached_at) end
clone?()
click to toggle source
# File lib/method_cache/proxy.rb, line 134 def clone? !!opts[:clone] end
context()
click to toggle source
# File lib/method_cache/proxy.rb, line 38 def context opts[:context] end
counter_method(method_name)
click to toggle source
# File lib/method_cache/proxy.rb, line 96 def counter_method(method_name) proxy = self # Need access to the proxy in the closure. lambda do |*args| if args.last.kind_of?(Hash) and args.last.keys == [:by] amount = args.last[:by] args.pop end proxy.bind(self, args).send(method_name, amount || 1) end end
expires_at()
click to toggle source
# File lib/method_cache/proxy.rb, line 153 def expires_at cache.expires_at(key) if cache.respond_to?(:expires_at) end
invalidate() { |value| ... }
click to toggle source
# File lib/method_cache/proxy.rb, line 29 def invalidate if block_given? # Only invalidate if the block returns true. value = cache[key] return if value and not yield(value) end cache.delete(key) end
key()
click to toggle source
# File lib/method_cache/proxy.rb, line 138 def key if @key.nil? arg_string = ([method_name, target] + args).collect do |arg| object_key(arg) end.join('|') @key = [version, arg_string].compact.join('|') @key = Digest::SHA1.hexdigest(@key) if @key.length > 250 end "m#{MethodCache.version}|#{@key}" end
local?()
click to toggle source
# File lib/method_cache/proxy.rb, line 130 def local? cache.kind_of?(LocalCache) or cache.kind_of?(Hash) end
method_name_without_caching()
click to toggle source
# File lib/method_cache/proxy.rb, line 108 def method_name_without_caching @method_name_without_caching ||= begin base_name, punctuation = method_name.to_s.sub(/([?!=])$/, ''), $1 "#{base_name}_without_caching#{punctuation}".to_sym end end
method_with_caching()
click to toggle source
# File lib/method_cache/proxy.rb, line 88 def method_with_caching proxy = self # Need access to the proxy in the closure. lambda do |*args| proxy.bind(self, args).value end end
update() { |old_value| ... }
click to toggle source
# File lib/method_cache/proxy.rb, line 50 def update if block_given? old_value = read_from_cache(key) return if old_value.nil? old_value = nil if old_value == NULL new_value = yield(old_value) return if old_value == new_value else new_value = target.send(method_name_without_caching, *args) end write_to_cache(key, new_value) new_value end
value()
click to toggle source
# File lib/method_cache/proxy.rb, line 65 def value value = read_from_cache(key) value = nil unless valid?(:load, value) if value.nil? value = target.send(method_name_without_caching, *args) raise "non-integer value returned by counter method" if opts[:counter] and not value.kind_of?(Fixnum) write_to_cache(key, value) if valid?(:save, value) end if opts[:counter] value = [value, opts[:max]].min if opts[:max] value = [value, opts[:min]].max if opts[:min] end value = nil if value == NULL if clone? and value value.clone else value end end
version()
click to toggle source
# File lib/method_cache/proxy.rb, line 42 def version dynamic_opt(:version) end
Private Instance Methods
class_key(klass)
click to toggle source
# File lib/method_cache/proxy.rb, line 252 def class_key(klass) klass.respond_to?(:version) ? "#{klass.name}_#{klass.version(context)}" : klass.name end
decrement(amount)
click to toggle source
# File lib/method_cache/proxy.rb, line 220 def decrement(amount) raise "cannot decrement non-counter method" unless opts[:counter] cache.decr(key, amount) end
dynamic_opt(name, value = nil)
click to toggle source
# File lib/method_cache/proxy.rb, line 176 def dynamic_opt(name, value = nil) if opts[name].kind_of?(Proc) proc = opts[name] case proc.arity when 0 then target.instance_exec(&proc) when 1 then target.instance_exec(value, &proc) else meta = { :args => args, :cached_at => cached_at, :expires_at => expires_at, } target.instance_exec(value, meta, &proc) end else opts[name] end end
expiry(value)
click to toggle source
# File lib/method_cache/proxy.rb, line 159 def expiry(value) value = dynamic_opt(:expiry, value).to_i if defined?(Memcache) and cache.kind_of?(Memcache) {:expiry => value} else value end end
increment(amount)
click to toggle source
# File lib/method_cache/proxy.rb, line 215 def increment(amount) raise "cannot increment non-counter method" unless opts[:counter] cache.incr(key, amount) end
object_key(arg)
click to toggle source
# File lib/method_cache/proxy.rb, line 225 def object_key(arg) return "#{class_key(arg.class)}-#{arg.string_hash}" if arg.respond_to?(:string_hash) case arg when NilClass then 'nil' when TrueClass then 'true' when FalseClass then 'false' when Numeric then arg.to_s when Symbol then ":#{arg}" when String then "'#{arg}'" when Class, Module then class_key(arg) when Hash '{' + arg.collect {|key, value| "#{object_key(key)}=#{object_key(value)}"}.sort.join(',') + '}' when Array '[' + arg.collect {|item| object_key(item)}.join(',') + ']' when defined?(ActiveRecord::Base) && ActiveRecord::Base "#{class_key(arg.class)}-#{arg.id}" else if arg.respond_to?(:method_cache_key) arg.method_cache_key else hash = local? ? arg.hash : Marshal.dump(arg).hash "#{class_key(arg.class)}-#{hash}" end end end
read_from_cache(key)
click to toggle source
# File lib/method_cache/proxy.rb, line 210 def read_from_cache(key) return if MethodCache.disabled? opts[:counter] ? cache.count(key) : cache[key] end
valid?(type, value)
click to toggle source
# File lib/method_cache/proxy.rb, line 168 def valid?(type, value) name = "#{type}_validation".to_sym return true unless opts[name] return unless value dynamic_opt(name, value) end
write_to_cache(key, value)
click to toggle source
# File lib/method_cache/proxy.rb, line 195 def write_to_cache(key, value) unless opts[:counter] value = value.nil? ? NULL : value end if cache.kind_of?(Hash) raise 'expiry not permitted when cache is a Hash' if opts[:expiry] raise 'counter cache not permitted when cache is a Hash' if opts[:counter] cache[key] = value elsif opts[:counter] cache.write(key, value.to_s, expiry(value)) else cache.set(key, value, expiry(value)) end end