Skip to content

Commit

Permalink
test argument handling and simplify cache keys
Browse files Browse the repository at this point in the history
  • Loading branch information
seamusabshere committed Feb 22, 2011
1 parent 9999ca8 commit 94bfb6d
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 28 deletions.
12 changes: 2 additions & 10 deletions lib/cache_method.rb
Expand Up @@ -20,15 +20,7 @@ def self.method_delimiter(obj) #:nodoc:
def self.method_signature(obj, method_id) #:nodoc:
[ klass_name(obj), method_id ].join method_delimiter(obj)
end

# What gets called to determine the hashcode of an object.
#
# * If the object is a Class, then it just does Class.to_s (otherwise Class hash codes change too often)
# * Otherwise, call #hash
def self.hashcode(obj)
obj.is_a?(::Class) ? obj.to_s : obj.hash
end


# All Objects, including instances and Classes, get the <tt>#clear_method_cache</tt> method.
module InstanceMethods
# Clear the cache for a particular method.
Expand Down Expand Up @@ -65,7 +57,7 @@ def cache_method(method_id, ttl = nil)
original_method_id = "_uncached_#{method_id}"
alias_method original_method_id, method_id
define_method method_id do |*args|
::CacheMethod::CachedResult.fetch :obj => self, :method_id => method_id, :original_method_id => original_method_id, :args => args, :ttl => ttl
::CacheMethod::CachedResult.fetch :obj => self, :method_id => method_id, :original_method_id => original_method_id, :ttl => ttl, :args => args
end
end
end
Expand Down
11 changes: 8 additions & 3 deletions lib/cache_method/cached_result.rb
Expand Up @@ -19,6 +19,7 @@ def initialize(options = {})
attr_reader :original_method_id
attr_reader :args

# Store things wrapped in an Array so that nil is accepted
def fetch
if v = Config.instance.storage.get(cache_key) and v.is_a?(::Array)
v[0]
Expand All @@ -34,19 +35,23 @@ def ttl
end

def cache_key
[ 'CacheMethod', 'CachedResult', method_signature, current_epoch, obj_hash, args_digest ].join ','
if obj.is_a? ::Class
[ 'CacheMethod', 'CachedResult', method_signature, current_epoch, args_digest ].join ','
else
[ 'CacheMethod', 'CachedResult', method_signature, obj_hash, current_epoch, args_digest ].join ','
end
end

def method_signature
@method_signature ||= ::CacheMethod.method_signature(obj, method_id)
end

def obj_hash
@obj_hash ||= ::CacheMethod.hashcode(obj)
@obj_hash ||= obj.hash
end

def args_digest
@args_digest ||= ::Digest::MD5.hexdigest(args.flatten.join)
@args_digest ||= args.empty? ? 'empty' : ::Digest::MD5.hexdigest(args.join)
end

def current_epoch
Expand Down
11 changes: 7 additions & 4 deletions lib/cache_method/epoch.rb
@@ -1,4 +1,3 @@
require 'digest/md5'
module CacheMethod
class Epoch #:nodoc: all
class << self
Expand All @@ -13,7 +12,7 @@ def mark_passing(options = {})
end

def random_name
::Digest::MD5.hexdigest rand.to_s
rand(1_000_000).to_s
end
end

Expand All @@ -31,11 +30,15 @@ def method_signature
end

def obj_hash
@obj_hash ||= ::CacheMethod.hashcode(obj)
@obj_hash ||= obj.hash
end

def cache_key
[ 'CacheMethod', 'Epoch', method_signature, obj_hash ].join ','
if obj.is_a? ::Class
[ 'CacheMethod', 'Epoch', method_signature ].join ','
else
[ 'CacheMethod', 'Epoch', method_signature, obj_hash ].join ','
end
end

def current
Expand Down
2 changes: 1 addition & 1 deletion lib/cache_method/version.rb
@@ -1,3 +1,3 @@
module CacheMethod
VERSION = "0.0.3"
VERSION = "0.1.0"
end
28 changes: 26 additions & 2 deletions test/helper.rb
Expand Up @@ -19,9 +19,23 @@ def initialize(name)
def echo_count
@echo_count ||= 0
end
# http://www.ruby-forum.com/topic/98106
# matz: "In 1.9, values (i.e. result of splat) are always represented by array,
# so that we won't confuse array as an value with array as values
# representation."
def echo(*args)
self.echo_count += 1
return *args
if RUBY_VERSION >= '1.9'
if args.empty?
return nil
elsif args.length == 1
return args[0]
else
return args
end
else
return *args
end
end
def hash
name.hash
Expand All @@ -37,7 +51,17 @@ def echo_count
end
def echo(*args)
self.echo_count += 1
return *args
if RUBY_VERSION >= '1.9'
if args.empty?
return nil
elsif args.length == 1
return args[0]
else
return args
end
else
return *args
end
end
cache_method :echo
end
Expand Down
76 changes: 68 additions & 8 deletions test/test_cache_method.rb
Expand Up @@ -6,14 +6,39 @@ class TestCacheMethod < Test::Unit::TestCase
def setup
Blog2.request_count = 0
CopyCat2.echo_count = 0
my_cache = Memcached.new '127.0.0.1:11211'
CacheMethod.config.storage = my_cache
my_cache = Memcached.new '127.0.0.1:11211', :binary => false
my_cache.flush
CacheMethod.config.storage = my_cache
end

def test_cache_instance_method_with_args
a = CopyCat1.new 'mimo'

assert_equal 'hi', a.echo('hi')
assert_equal 1, a.echo_count

assert_equal 'hi', a.echo('hi')
assert_equal 1, a.echo_count
end

def test_cache_instance_method_with_nil_args
a = CopyCat1.new 'mimo'
assert_equal nil, a.echo
assert_equal 1, a.echo_count

assert_equal nil, a.echo
assert_equal 1, a.echo_count

assert_equal nil, a.echo(nil)
assert_equal 2, a.echo_count

assert_equal nil, a.echo(nil)
assert_equal 2, a.echo_count
end

def test_cache_instance_method_with_array_args
a = CopyCat1.new 'mimo'

assert_equal ['hi'], a.echo(['hi'])
assert_equal 1, a.echo_count

Expand All @@ -26,14 +51,43 @@ def test_cache_instance_method_with_args
assert_equal ['bye'], a.echo(['bye'])
assert_equal 2, a.echo_count

assert_equal nil, a.echo
assert_equal ['hi', 'there'], a.echo(['hi', 'there'])
assert_equal 3, a.echo_count

assert_equal nil, a.echo
# same as previous
assert_equal ['hi', 'there'], a.echo('hi', 'there')
assert_equal 3, a.echo_count

assert_equal [], a.echo([])
assert_equal 4, a.echo_count

assert_equal [], a.echo([])
assert_equal 4, a.echo_count
end

def test_cache_class_method_with_args
assert_equal 'hi', CopyCat2.echo('hi')
assert_equal 1, CopyCat2.echo_count

assert_equal 'hi', CopyCat2.echo('hi')
assert_equal 1, CopyCat2.echo_count
end

def test_cache_class_method_with_nil_args
assert_equal nil, CopyCat2.echo
assert_equal 1, CopyCat2.echo_count

assert_equal nil, CopyCat2.echo
assert_equal 1, CopyCat2.echo_count

assert_equal nil, CopyCat2.echo(nil)
assert_equal 2, CopyCat2.echo_count

assert_equal nil, CopyCat2.echo(nil)
assert_equal 2, CopyCat2.echo_count
end

def test_cache_class_method_with_array_args
assert_equal ['hi'], CopyCat2.echo(['hi'])
assert_equal 1, CopyCat2.echo_count

Expand All @@ -46,13 +100,19 @@ def test_cache_class_method_with_args
assert_equal ['bye'], CopyCat2.echo(['bye'])
assert_equal 2, CopyCat2.echo_count

assert_equal nil, CopyCat2.echo
assert_equal ['hi', 'there'], CopyCat2.echo(['hi', 'there'])
assert_equal 3, CopyCat2.echo_count

assert_equal nil, CopyCat2.echo
assert_equal ['hi', 'there'], CopyCat2.echo('hi', 'there')
assert_equal 3, CopyCat2.echo_count

assert_equal [], CopyCat2.echo([])
assert_equal 4, CopyCat2.echo_count

assert_equal [], CopyCat2.echo([])
assert_equal 4, CopyCat2.echo_count
end

def test_cache_instance_method
a = new_instance_of_my_blog
assert_equal ["hello from #{a.name}"], a.get_latest_entries
Expand Down

0 comments on commit 94bfb6d

Please sign in to comment.