cache_method 0.1.6 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -4
- data/CHANGELOG +24 -0
- data/Gemfile +6 -1
- data/{README.rdoc → README.markdown} +25 -34
- data/Rakefile +4 -11
- data/cache_method.gemspec +0 -8
- data/lib/cache_method/cached_result.rb +13 -7
- data/lib/cache_method/generation.rb +5 -4
- data/lib/cache_method/version.rb +1 -1
- data/lib/cache_method.rb +10 -11
- data/test/helper.rb +15 -19
- data/test/test_cache_method.rb +226 -119
- metadata +8 -28
data/.gitignore
CHANGED
data/CHANGELOG
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
0.2.0 / 2012-02-29
|
2
|
+
|
3
|
+
* API changes:
|
4
|
+
|
5
|
+
* #clear_method_cache -> #cache_method_clear
|
6
|
+
* #method_cache_hash -> #as_cache_key (see README)
|
7
|
+
* doesn't rely on #hash at all any more (http://numbers.brighterplanet.com/2012/02/29/beware-of-string-hash-being-used-for-cache-keys/)
|
8
|
+
* doesn't try to mitigate differences between Ruby 1.8 and 1.9 splats (http://www.ruby-forum.com/topic/98106)
|
9
|
+
|
10
|
+
* Enhancements
|
11
|
+
|
12
|
+
* clearer method naming, I think
|
13
|
+
* safer determination of cache keys - previously, in effect, args.map(&:to_s) was being used
|
14
|
+
* no more autoload
|
15
|
+
* remove direct dependency on activesupport
|
16
|
+
* tests now run with dalli, green on MRI 1.8, MRI 1.9, and jruby 1.6.7
|
17
|
+
|
18
|
+
0.1.7 / yanked!
|
19
|
+
|
20
|
+
* Bug: used args.map(&:hash) instead of args.map(&:to_s)... which was actually worse because #hash is different across processes.
|
21
|
+
|
22
|
+
0.1.6 / November 17, 2011
|
23
|
+
|
24
|
+
* Last release before CHANGELOG in place
|
data/Gemfile
CHANGED
@@ -1,14 +1,14 @@
|
|
1
|
-
|
1
|
+
# cache_method
|
2
2
|
|
3
|
-
It's like
|
3
|
+
It's like `alias_method`, but it's `cache_method`!
|
4
4
|
|
5
5
|
Lets you cache the results of calling methods given their arguments. Like memoization, but stored in Memcached, Redis, etc. so that the cached results can be shared between processes and hosts.
|
6
6
|
|
7
|
-
|
7
|
+
## Real-world usage
|
8
8
|
|
9
|
-
In production use at
|
9
|
+
In production use at [impact.brighterplanet.com](http://impact.brighterplanet.com) and [data.brighterplanet.com](http://data.brighterplanet.com).
|
10
10
|
|
11
|
-
|
11
|
+
## Example
|
12
12
|
|
13
13
|
require 'cache_method'
|
14
14
|
class Blog
|
@@ -25,12 +25,11 @@ In production use at {impact.brighterplanet.com}[http://impact.brighterplanet.co
|
|
25
25
|
end
|
26
26
|
cache_method :get_latest_entries
|
27
27
|
|
28
|
-
# cache_method
|
29
|
-
#
|
30
|
-
#
|
31
|
-
|
32
|
-
|
33
|
-
{ :name => name, :url => url }.hash
|
28
|
+
# By default, cache_method derives the cache key for an instance by getting the SHA1 hash of the Marshal.dump
|
29
|
+
# If you need to customize how an instance is recognized, you can define #as_cache_key.
|
30
|
+
# Marshal.load will be called on the result.
|
31
|
+
def as_cache_key
|
32
|
+
{ :name => name, :url => url }
|
34
33
|
end
|
35
34
|
end
|
36
35
|
|
@@ -41,11 +40,11 @@ Then you can do
|
|
41
40
|
|
42
41
|
And clear them too
|
43
42
|
|
44
|
-
my_blog.
|
43
|
+
my_blog.cache_method_clear :get_latest_entries
|
45
44
|
|
46
45
|
(which doesn't delete the rest of your cache)
|
47
46
|
|
48
|
-
|
47
|
+
## Configuration (and supported cache clients)
|
49
48
|
|
50
49
|
You need to set where the cache will be stored:
|
51
50
|
|
@@ -59,9 +58,9 @@ or this might even work...
|
|
59
58
|
|
60
59
|
CacheMethod.config.storage = Rails.cache
|
61
60
|
|
62
|
-
See
|
61
|
+
See `Config` for the full list of supported caches.
|
63
62
|
|
64
|
-
== Defining a #
|
63
|
+
== Defining a #as_cache_key method
|
65
64
|
|
66
65
|
Since we're not pure functional programmers, sometimes cache hits depend on object state in addition to method arguments. To illustrate:
|
67
66
|
|
@@ -71,25 +70,17 @@ get_latest_entries doesn't take any arguments, so it must depend on my_blog.url
|
|
71
70
|
|
72
71
|
class Blog
|
73
72
|
# [...]
|
74
|
-
def
|
75
|
-
{ :name => name, :url => url }
|
73
|
+
def as_cache_key
|
74
|
+
{ :name => name, :url => url }
|
76
75
|
end
|
77
76
|
# [...]
|
78
77
|
end
|
79
78
|
|
80
|
-
|
79
|
+
If you don't define `#as_cache_key`, then `cache_method` will `Marshal.dump` an instance.
|
81
80
|
|
82
|
-
|
81
|
+
## Module methods
|
83
82
|
|
84
|
-
|
85
|
-
|
86
|
-
== Using #method_cache_hash instead of #hash
|
87
|
-
|
88
|
-
If you don't want to modify #hash, use #method_cache_hash instead.
|
89
|
-
|
90
|
-
== Module methods
|
91
|
-
|
92
|
-
You can put <tt>#cache_method</tt> right into your module declarations:
|
83
|
+
You can put `#cache_method` right into your module declarations:
|
93
84
|
|
94
85
|
module MyModule
|
95
86
|
def my_module_method(args)
|
@@ -106,7 +97,7 @@ You can put <tt>#cache_method</tt> right into your module declarations:
|
|
106
97
|
extend MyModule
|
107
98
|
end
|
108
99
|
|
109
|
-
Rest assured that
|
100
|
+
Rest assured that `Tiger.my_module_method` and `Lion.my_module_method` will be cached correctly and separately. This, on the other hand, won't work:
|
110
101
|
|
111
102
|
class Tiger
|
112
103
|
extend MyModule
|
@@ -114,13 +105,13 @@ Rest assured that <tt>Tiger.my_module_method</tt> and <tt>Lion.my_module_method<
|
|
114
105
|
# cache_method :my_module_method
|
115
106
|
end
|
116
107
|
|
117
|
-
|
108
|
+
## Rationale
|
118
109
|
|
119
|
-
* It should be easy to cache a method using memcached, dalli (if you're on heroku), redis, etc. (that's why I made the
|
110
|
+
* It should be easy to cache a method using memcached, dalli (if you're on heroku), redis, etc. (that's why I made the [cache gem](https://rubygems.org/gems/cache))
|
120
111
|
* It should be easy to uncache a method without clearing the whole cache
|
121
112
|
* It should be easy to cache instance methods
|
122
|
-
* It should be easy to cache methods that depend on object state
|
113
|
+
* It should be easy to cache methods that depend on object state (hence `#as_cache_key`)
|
123
114
|
|
124
|
-
|
115
|
+
## Copyright
|
125
116
|
|
126
|
-
Copyright
|
117
|
+
Copyright 2012 Seamus Abshere
|
data/Rakefile
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require "bundler/gem_tasks"
|
3
3
|
|
4
4
|
require 'rake'
|
5
5
|
require 'rake/testtask'
|
@@ -11,12 +11,5 @@ end
|
|
11
11
|
|
12
12
|
task :default => :test
|
13
13
|
|
14
|
-
require '
|
15
|
-
Rake::
|
16
|
-
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
17
|
-
|
18
|
-
rdoc.rdoc_dir = 'rdoc'
|
19
|
-
rdoc.title = "cache_method #{version}"
|
20
|
-
rdoc.rdoc_files.include('README*')
|
21
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
22
|
-
end
|
14
|
+
require 'yard'
|
15
|
+
YARD::Rake::YardocTask.new
|
data/cache_method.gemspec
CHANGED
@@ -5,7 +5,6 @@ require "cache_method/version"
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = "cache_method"
|
7
7
|
s.version = CacheMethod::VERSION
|
8
|
-
s.platform = Gem::Platform::RUBY
|
9
8
|
s.authors = ["Seamus Abshere"]
|
10
9
|
s.email = ["seamus@abshere.net"]
|
11
10
|
s.homepage = "https://github.com/seamusabshere/cache_method"
|
@@ -19,11 +18,4 @@ Gem::Specification.new do |s|
|
|
19
18
|
s.require_paths = ["lib"]
|
20
19
|
|
21
20
|
s.add_dependency 'cache', '>=0.2.1'
|
22
|
-
s.add_development_dependency 'memcached'
|
23
|
-
s.add_development_dependency 'rake'
|
24
|
-
# if RUBY_VERSION >= '1.9'
|
25
|
-
# s.add_development_dependency 'ruby-debug19'
|
26
|
-
# else
|
27
|
-
# s.add_development_dependency 'ruby-debug'
|
28
|
-
# end
|
29
21
|
end
|
@@ -1,6 +1,8 @@
|
|
1
|
-
require 'digest/
|
1
|
+
require 'digest/sha1'
|
2
2
|
module CacheMethod
|
3
3
|
class CachedResult #:nodoc: all
|
4
|
+
CACHE_KEY_JOINER = ','
|
5
|
+
|
4
6
|
def initialize(obj, method_id, original_method_id, ttl, args)
|
5
7
|
@obj = obj
|
6
8
|
@method_id = method_id
|
@@ -17,7 +19,7 @@ module CacheMethod
|
|
17
19
|
# Store things wrapped in an Array so that nil is accepted
|
18
20
|
def fetch
|
19
21
|
if v = Config.instance.storage.get(cache_key) and v.is_a?(::Array)
|
20
|
-
v
|
22
|
+
v.first
|
21
23
|
else
|
22
24
|
v = obj.send original_method_id, *args
|
23
25
|
Config.instance.storage.set cache_key, [v], ttl
|
@@ -31,9 +33,9 @@ module CacheMethod
|
|
31
33
|
|
32
34
|
def cache_key
|
33
35
|
if obj.is_a?(::Class) or obj.is_a?(::Module)
|
34
|
-
[ 'CacheMethod', 'CachedResult', method_signature, current_generation, args_digest ].compact.join
|
36
|
+
[ 'CacheMethod', 'CachedResult', method_signature, current_generation, args_digest ].compact.join CACHE_KEY_JOINER
|
35
37
|
else
|
36
|
-
[ 'CacheMethod', 'CachedResult', method_signature,
|
38
|
+
[ 'CacheMethod', 'CachedResult', method_signature, obj_digest, current_generation, args_digest ].compact.join CACHE_KEY_JOINER
|
37
39
|
end
|
38
40
|
end
|
39
41
|
|
@@ -41,12 +43,12 @@ module CacheMethod
|
|
41
43
|
@method_signature ||= ::CacheMethod.method_signature(obj, method_id)
|
42
44
|
end
|
43
45
|
|
44
|
-
def
|
45
|
-
@
|
46
|
+
def obj_digest
|
47
|
+
@obj_digest ||= ::Digest::SHA1.hexdigest(::Marshal.dump(obj.respond_to?(:as_cache_key) ? obj.as_cache_key : obj))
|
46
48
|
end
|
47
49
|
|
48
50
|
def args_digest
|
49
|
-
@args_digest ||= args.empty? ? 'empty' : ::Digest::
|
51
|
+
@args_digest ||= args.empty? ? 'empty' : ::Digest::SHA1.hexdigest(::Marshal.dump(args))
|
50
52
|
end
|
51
53
|
|
52
54
|
def current_generation
|
@@ -54,5 +56,9 @@ module CacheMethod
|
|
54
56
|
@current_generation ||= Generation.new(obj, method_id).current
|
55
57
|
end
|
56
58
|
end
|
59
|
+
|
60
|
+
def arity
|
61
|
+
@arity ||= obj.method(original_method_id).arity
|
62
|
+
end
|
57
63
|
end
|
58
64
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'digest/sha1'
|
1
2
|
module CacheMethod
|
2
3
|
class Generation #:nodoc: all
|
3
4
|
class << self
|
@@ -18,15 +19,15 @@ module CacheMethod
|
|
18
19
|
@method_signature ||= ::CacheMethod.method_signature(obj, method_id)
|
19
20
|
end
|
20
21
|
|
21
|
-
def
|
22
|
-
@
|
22
|
+
def obj_digest
|
23
|
+
@obj_digest ||= ::Digest::SHA1.hexdigest(::Marshal.dump(obj.respond_to?(:as_cache_key) ? obj.as_cache_key : obj))
|
23
24
|
end
|
24
25
|
|
25
26
|
def cache_key
|
26
|
-
if obj.is_a?
|
27
|
+
if obj.is_a?(::Class) or obj.is_a?(::Module)
|
27
28
|
[ 'CacheMethod', 'Generation', method_signature ].join ','
|
28
29
|
else
|
29
|
-
[ 'CacheMethod', 'Generation', method_signature,
|
30
|
+
[ 'CacheMethod', 'Generation', method_signature, obj_digest ].join ','
|
30
31
|
end
|
31
32
|
end
|
32
33
|
|
data/lib/cache_method/version.rb
CHANGED
data/lib/cache_method.rb
CHANGED
@@ -1,10 +1,9 @@
|
|
1
|
-
require 'cache_method/
|
1
|
+
require 'cache_method/config'
|
2
|
+
require 'cache_method/cached_result'
|
3
|
+
require 'cache_method/generation'
|
4
|
+
|
2
5
|
# See the README.rdoc for more info!
|
3
6
|
module CacheMethod
|
4
|
-
autoload :Config, 'cache_method/config'
|
5
|
-
autoload :CachedResult, 'cache_method/cached_result'
|
6
|
-
autoload :Generation, 'cache_method/generation'
|
7
|
-
|
8
7
|
def self.config #:nodoc:
|
9
8
|
Config.instance
|
10
9
|
end
|
@@ -21,19 +20,19 @@ module CacheMethod
|
|
21
20
|
[ klass_name(obj), method_id ].join method_delimiter(obj)
|
22
21
|
end
|
23
22
|
|
24
|
-
# All Objects, including instances and Classes, get the <tt>#
|
23
|
+
# All Objects, including instances and Classes, get the <tt>#cache_method_clear</tt> method.
|
25
24
|
module InstanceMethods
|
26
25
|
# Clear the cache for a particular method.
|
27
26
|
#
|
28
|
-
# Note: Remember to define <tt>#
|
27
|
+
# Note: Remember to define <tt>#as_cache_key</tt> on any object whose instance methods might get cached.
|
29
28
|
#
|
30
29
|
# Example:
|
31
|
-
# my_blog.
|
32
|
-
def
|
30
|
+
# my_blog.cache_method_clear :get_latest_entries
|
31
|
+
def cache_method_clear(method_id)
|
33
32
|
if ::CacheMethod.config.generational?
|
34
33
|
::CacheMethod::Generation.new(self, method_id).mark_passing
|
35
34
|
else
|
36
|
-
raise ::RuntimeError, "[cache_method]
|
35
|
+
raise ::RuntimeError, "[cache_method] cache_method_clear called, but you have disabled generational caching. Check your setting for CacheMethod.config.generational"
|
37
36
|
end
|
38
37
|
end
|
39
38
|
end
|
@@ -42,7 +41,7 @@ module CacheMethod
|
|
42
41
|
module ClassMethods
|
43
42
|
# Cache a method. TTL in seconds, defaults to whatever's in CacheMethod.config.default_ttl
|
44
43
|
#
|
45
|
-
# Note: Remember to define <tt>#
|
44
|
+
# Note: Remember to define <tt>#as_cache_key</tt> on any object whose instance methods might get cached.
|
46
45
|
#
|
47
46
|
# Note 2: Check out CacheMethod.config.default_ttl... the default is 24 hours.
|
48
47
|
#
|
data/test/helper.rb
CHANGED
@@ -25,30 +25,20 @@ class CopyCat1
|
|
25
25
|
# representation."
|
26
26
|
def echo(*args)
|
27
27
|
self.echo_count += 1
|
28
|
-
|
29
|
-
if args.empty?
|
30
|
-
return nil
|
31
|
-
elsif args.length == 1
|
32
|
-
return args[0]
|
33
|
-
else
|
34
|
-
return args
|
35
|
-
end
|
36
|
-
else
|
37
|
-
return *args
|
38
|
-
end
|
28
|
+
return *args
|
39
29
|
end
|
40
|
-
def
|
41
|
-
raise "Used
|
30
|
+
def marshal_dump
|
31
|
+
raise "Used marshal_dump"
|
42
32
|
end
|
43
|
-
def
|
44
|
-
name
|
33
|
+
def as_cache_key
|
34
|
+
name
|
45
35
|
end
|
46
36
|
cache_method :echo
|
47
37
|
end
|
48
38
|
|
49
39
|
class CopyCat1a < CopyCat1
|
50
|
-
def
|
51
|
-
raise "Used
|
40
|
+
def as_cache_key
|
41
|
+
raise "Used as_cache_key"
|
52
42
|
end
|
53
43
|
end
|
54
44
|
|
@@ -113,8 +103,8 @@ class Blog1
|
|
113
103
|
["voo vaa #{name}"]
|
114
104
|
end
|
115
105
|
cache_method :get_latest_entries2, 1 # second
|
116
|
-
def
|
117
|
-
{ :name => name, :url => url }
|
106
|
+
def as_cache_key
|
107
|
+
{ :name => name, :url => url }
|
118
108
|
end
|
119
109
|
end
|
120
110
|
def new_instance_of_my_blog
|
@@ -158,3 +148,9 @@ CopyCat1.extend Say
|
|
158
148
|
CopyCat2.extend Say
|
159
149
|
|
160
150
|
CopyCat1.send :include, Say
|
151
|
+
|
152
|
+
class DontStringifyMe < Struct.new(:message)
|
153
|
+
def to_s
|
154
|
+
"Don't stringify me, read my message!"
|
155
|
+
end
|
156
|
+
end
|
data/test/test_cache_method.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'dalli'
|
4
4
|
|
5
5
|
class TestCacheMethod < Test::Unit::TestCase
|
6
6
|
def setup
|
@@ -8,114 +8,178 @@ class TestCacheMethod < Test::Unit::TestCase
|
|
8
8
|
CopyCat2.echo_count = 0
|
9
9
|
CopyCat1.say_count = 0
|
10
10
|
CopyCat2.say_count = 0
|
11
|
-
my_cache =
|
11
|
+
my_cache = Dalli::Client.new '127.0.0.1:11211'
|
12
12
|
my_cache.flush
|
13
13
|
CacheMethod.config.storage = my_cache
|
14
14
|
CacheMethod.config.generational = true
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
def test_cache_instance_method_with_args
|
18
18
|
a = CopyCat1.new 'mimo'
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
19
|
+
|
20
|
+
if RUBY_VERSION >= '1.9'
|
21
|
+
assert_equal ['hi'], a.echo('hi')
|
22
|
+
assert_equal 1, a.echo_count
|
23
|
+
|
24
|
+
assert_equal ['hi'], a.echo('hi')
|
25
|
+
assert_equal 1, a.echo_count
|
26
|
+
else
|
27
|
+
assert_equal 'hi', a.echo('hi')
|
28
|
+
assert_equal 1, a.echo_count
|
29
|
+
|
30
|
+
assert_equal 'hi', a.echo('hi')
|
31
|
+
assert_equal 1, a.echo_count
|
32
|
+
end
|
25
33
|
end
|
26
|
-
|
34
|
+
|
27
35
|
def test_cache_instance_method_with_nil_args
|
28
36
|
a = CopyCat1.new 'mimo'
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
37
|
+
|
38
|
+
if RUBY_VERSION >= '1.9'
|
39
|
+
assert_equal [], a.echo
|
40
|
+
assert_equal 1, a.echo_count
|
41
|
+
|
42
|
+
assert_equal [], a.echo
|
43
|
+
assert_equal 1, a.echo_count
|
44
|
+
|
45
|
+
assert_equal [nil], a.echo(nil)
|
46
|
+
assert_equal 2, a.echo_count
|
47
|
+
|
48
|
+
assert_equal [nil], a.echo(nil)
|
49
|
+
assert_equal 2, a.echo_count
|
50
|
+
else
|
51
|
+
assert_equal nil, a.echo
|
52
|
+
assert_equal 1, a.echo_count
|
53
|
+
|
54
|
+
assert_equal nil, a.echo
|
55
|
+
assert_equal 1, a.echo_count
|
56
|
+
|
57
|
+
assert_equal nil, a.echo(nil)
|
58
|
+
assert_equal 2, a.echo_count
|
59
|
+
|
60
|
+
assert_equal nil, a.echo(nil)
|
61
|
+
assert_equal 2, a.echo_count
|
62
|
+
end
|
40
63
|
end
|
41
|
-
|
64
|
+
|
42
65
|
def test_cache_instance_method_with_array_args
|
43
66
|
a = CopyCat1.new 'mimo'
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
67
|
+
|
68
|
+
if RUBY_VERSION >= '1.9'
|
69
|
+
assert_equal [['hi']], a.echo(['hi'])
|
70
|
+
assert_equal 1, a.echo_count
|
71
|
+
|
72
|
+
assert_equal [['hi']], a.echo(['hi'])
|
73
|
+
assert_equal 1, a.echo_count
|
74
|
+
|
75
|
+
assert_equal [['bye']], a.echo(['bye'])
|
76
|
+
assert_equal 2, a.echo_count
|
77
|
+
|
78
|
+
assert_equal [['bye']], a.echo(['bye'])
|
79
|
+
assert_equal 2, a.echo_count
|
80
|
+
|
81
|
+
assert_equal [[]], a.echo([])
|
82
|
+
assert_equal 3, a.echo_count
|
83
|
+
|
84
|
+
assert_equal [[]], a.echo([])
|
85
|
+
assert_equal 3, a.echo_count
|
86
|
+
else
|
87
|
+
assert_equal ['hi'], a.echo(['hi'])
|
88
|
+
assert_equal 1, a.echo_count
|
89
|
+
|
90
|
+
assert_equal ['hi'], a.echo(['hi'])
|
91
|
+
assert_equal 1, a.echo_count
|
92
|
+
|
93
|
+
assert_equal ['bye'], a.echo(['bye'])
|
94
|
+
assert_equal 2, a.echo_count
|
95
|
+
|
96
|
+
assert_equal ['bye'], a.echo(['bye'])
|
97
|
+
assert_equal 2, a.echo_count
|
98
|
+
|
99
|
+
assert_equal [], a.echo([])
|
100
|
+
assert_equal 3, a.echo_count
|
101
|
+
|
102
|
+
assert_equal [], a.echo([])
|
103
|
+
assert_equal 3, a.echo_count
|
104
|
+
end
|
69
105
|
end
|
70
|
-
|
106
|
+
|
107
|
+
def test_cache_instance_method_with_array_args_splat
|
108
|
+
a = CopyCat1.new 'mimo'
|
109
|
+
|
110
|
+
if RUBY_VERSION >= '1.9'
|
111
|
+
assert_equal [['hi', 'there']], a.echo(['hi', 'there'])
|
112
|
+
assert_equal 1, a.echo_count
|
113
|
+
|
114
|
+
assert_equal ['hi', 'there'], a.echo('hi', 'there')
|
115
|
+
assert_equal 2, a.echo_count
|
116
|
+
else
|
117
|
+
assert_equal ['hi', 'there'], a.echo(['hi', 'there'])
|
118
|
+
assert_equal 1, a.echo_count
|
119
|
+
|
120
|
+
assert_equal ['hi', 'there'], a.echo('hi', 'there')
|
121
|
+
assert_equal 2, a.echo_count
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
71
125
|
def test_cache_class_method_with_args
|
72
126
|
assert_equal 'hi', CopyCat2.echo('hi')
|
73
127
|
assert_equal 1, CopyCat2.echo_count
|
74
|
-
|
128
|
+
|
75
129
|
assert_equal 'hi', CopyCat2.echo('hi')
|
76
130
|
assert_equal 1, CopyCat2.echo_count
|
77
131
|
end
|
78
|
-
|
132
|
+
|
79
133
|
def test_cache_class_method_with_nil_args
|
80
134
|
assert_equal nil, CopyCat2.echo
|
81
135
|
assert_equal 1, CopyCat2.echo_count
|
82
|
-
|
136
|
+
|
83
137
|
assert_equal nil, CopyCat2.echo
|
84
138
|
assert_equal 1, CopyCat2.echo_count
|
85
|
-
|
139
|
+
|
86
140
|
assert_equal nil, CopyCat2.echo(nil)
|
87
141
|
assert_equal 2, CopyCat2.echo_count
|
88
|
-
|
142
|
+
|
89
143
|
assert_equal nil, CopyCat2.echo(nil)
|
90
|
-
assert_equal 2, CopyCat2.echo_count
|
144
|
+
assert_equal 2, CopyCat2.echo_count
|
91
145
|
end
|
92
|
-
|
146
|
+
|
93
147
|
def test_cache_class_method_with_array_args
|
94
148
|
assert_equal ['hi'], CopyCat2.echo(['hi'])
|
95
149
|
assert_equal 1, CopyCat2.echo_count
|
96
|
-
|
150
|
+
|
97
151
|
assert_equal ['hi'], CopyCat2.echo(['hi'])
|
98
152
|
assert_equal 1, CopyCat2.echo_count
|
99
|
-
|
153
|
+
|
100
154
|
assert_equal ['bye'], CopyCat2.echo(['bye'])
|
101
155
|
assert_equal 2, CopyCat2.echo_count
|
102
|
-
|
156
|
+
|
103
157
|
assert_equal ['bye'], CopyCat2.echo(['bye'])
|
104
158
|
assert_equal 2, CopyCat2.echo_count
|
105
|
-
|
106
|
-
assert_equal ['hi', 'there'], CopyCat2.echo(['hi', 'there'])
|
107
|
-
assert_equal 3, CopyCat2.echo_count
|
108
|
-
|
109
|
-
assert_equal ['hi', 'there'], CopyCat2.echo('hi', 'there')
|
110
|
-
assert_equal 3, CopyCat2.echo_count
|
111
|
-
|
159
|
+
|
112
160
|
assert_equal [], CopyCat2.echo([])
|
113
|
-
assert_equal
|
114
|
-
|
161
|
+
assert_equal 3, CopyCat2.echo_count
|
162
|
+
|
115
163
|
assert_equal [], CopyCat2.echo([])
|
116
|
-
assert_equal
|
164
|
+
assert_equal 3, CopyCat2.echo_count
|
165
|
+
end
|
166
|
+
|
167
|
+
def test_cache_class_method_with_array_args_splat
|
168
|
+
if RUBY_VERSION >= '1.9'
|
169
|
+
assert_equal ['hi', 'there'], CopyCat2.echo(['hi', 'there'])
|
170
|
+
assert_equal 1, CopyCat2.echo_count
|
171
|
+
|
172
|
+
assert_equal ['hi', 'there'], CopyCat2.echo('hi', 'there')
|
173
|
+
assert_equal 2, CopyCat2.echo_count
|
174
|
+
else
|
175
|
+
assert_equal ['hi', 'there'], CopyCat2.echo(['hi', 'there'])
|
176
|
+
assert_equal 1, CopyCat2.echo_count
|
177
|
+
|
178
|
+
assert_equal ['hi', 'there'], CopyCat2.echo('hi', 'there')
|
179
|
+
assert_equal 2, CopyCat2.echo_count
|
180
|
+
end
|
117
181
|
end
|
118
|
-
|
182
|
+
|
119
183
|
def test_cache_instance_method
|
120
184
|
a = new_instance_of_my_blog
|
121
185
|
assert_equal ["hello from #{a.name}"], a.get_latest_entries
|
@@ -127,25 +191,25 @@ class TestCacheMethod < Test::Unit::TestCase
|
|
127
191
|
assert_equal ["hello from #{xxx.name}"], xxx.get_latest_entries
|
128
192
|
assert_equal 1, xxx.request_count
|
129
193
|
end
|
130
|
-
|
194
|
+
|
131
195
|
def test_clear_instance_method
|
132
196
|
a = new_instance_of_my_blog
|
133
197
|
assert_equal ["hello from #{a.name}"], a.get_latest_entries
|
134
198
|
assert_equal 1, a.request_count
|
135
|
-
a.
|
199
|
+
a.cache_method_clear :get_latest_entries
|
136
200
|
assert_equal ["hello from #{a.name}"], a.get_latest_entries
|
137
201
|
assert_equal 2, a.request_count
|
138
202
|
end
|
139
|
-
|
203
|
+
|
140
204
|
def test_clear_correct_instance_method
|
141
205
|
a = new_instance_of_my_blog
|
142
206
|
assert_equal ["hello from #{a.name}"], a.get_latest_entries
|
143
207
|
assert_equal 1, a.request_count
|
144
|
-
a.
|
208
|
+
a.cache_method_clear :foobar
|
145
209
|
assert_equal ["hello from #{a.name}"], a.get_latest_entries
|
146
210
|
assert_equal 1, a.request_count
|
147
211
|
end
|
148
|
-
|
212
|
+
|
149
213
|
def test_clear_instance_method_from_correct_instance
|
150
214
|
a = new_instance_of_my_blog
|
151
215
|
assert_equal ["hello from #{a.name}"], a.get_latest_entries
|
@@ -153,13 +217,13 @@ class TestCacheMethod < Test::Unit::TestCase
|
|
153
217
|
xxx = new_instance_of_another_blog
|
154
218
|
assert_equal ["hello from #{xxx.name}"], xxx.get_latest_entries
|
155
219
|
assert_equal 1, xxx.request_count
|
156
|
-
xxx.
|
220
|
+
xxx.cache_method_clear :get_latest_entries
|
157
221
|
assert_equal ["hello from #{a.name}"], a.get_latest_entries
|
158
222
|
assert_equal 1, a.request_count
|
159
223
|
assert_equal ["hello from #{xxx.name}"], xxx.get_latest_entries
|
160
224
|
assert_equal 2, xxx.request_count
|
161
225
|
end
|
162
|
-
|
226
|
+
|
163
227
|
def test_cache_instance_method_ttl
|
164
228
|
a = new_instance_of_my_blog
|
165
229
|
assert_equal ["voo vaa #{a.name}"], a.get_latest_entries2
|
@@ -168,7 +232,7 @@ class TestCacheMethod < Test::Unit::TestCase
|
|
168
232
|
assert_equal ["voo vaa #{a.name}"], a.get_latest_entries2
|
169
233
|
assert_equal 2, a.request_count
|
170
234
|
end
|
171
|
-
|
235
|
+
|
172
236
|
def test_cache_class_method
|
173
237
|
assert_equal 0, Blog2.request_count
|
174
238
|
assert_equal 'danke schoen', Blog2.get_latest_entries
|
@@ -176,52 +240,68 @@ class TestCacheMethod < Test::Unit::TestCase
|
|
176
240
|
assert_equal 'danke schoen', Blog2.get_latest_entries
|
177
241
|
assert_equal 1, Blog2.request_count
|
178
242
|
end
|
179
|
-
|
243
|
+
|
180
244
|
def test_clear_class_method
|
181
245
|
assert_equal 0, Blog2.request_count
|
182
246
|
assert_equal 'danke schoen', Blog2.get_latest_entries
|
183
247
|
assert_equal 1, Blog2.request_count
|
184
|
-
Blog2.
|
248
|
+
Blog2.cache_method_clear :get_latest_entries
|
185
249
|
assert_equal 'danke schoen', Blog2.get_latest_entries
|
186
250
|
assert_equal 2, Blog2.request_count
|
187
251
|
end
|
188
|
-
|
252
|
+
|
189
253
|
def test_clear_correct_class_method
|
190
254
|
assert_equal 0, Blog2.request_count
|
191
255
|
assert_equal 'danke schoen', Blog2.get_latest_entries
|
192
256
|
assert_equal 1, Blog2.request_count
|
193
|
-
|
194
|
-
Blog2.
|
257
|
+
|
258
|
+
Blog2.cache_method_clear :foobar
|
195
259
|
assert_equal 'danke schoen', Blog2.get_latest_entries
|
196
260
|
assert_equal 1, Blog2.request_count
|
197
|
-
|
198
|
-
Blog2.
|
261
|
+
|
262
|
+
Blog2.cache_method_clear :get_latest_entries
|
199
263
|
assert_equal 'danke schoen', Blog2.get_latest_entries
|
200
264
|
assert_equal 2, Blog2.request_count
|
201
265
|
end
|
202
|
-
|
266
|
+
|
203
267
|
def test_never_set_storage
|
204
268
|
CacheMethod.config.instance_variable_set :@storage, nil
|
205
269
|
a = CopyCat1.new 'mimo'
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
270
|
+
|
271
|
+
if RUBY_VERSION >= '1.9'
|
272
|
+
assert_equal ['hi'], a.echo('hi')
|
273
|
+
assert_equal 1, a.echo_count
|
274
|
+
|
275
|
+
assert_equal ['hi'], a.echo('hi')
|
276
|
+
assert_equal 1, a.echo_count
|
277
|
+
else
|
278
|
+
assert_equal 'hi', a.echo('hi')
|
279
|
+
assert_equal 1, a.echo_count
|
280
|
+
|
281
|
+
assert_equal 'hi', a.echo('hi')
|
282
|
+
assert_equal 1, a.echo_count
|
283
|
+
end
|
212
284
|
end
|
213
|
-
|
285
|
+
|
214
286
|
def test_set_storage_to_nil
|
215
287
|
CacheMethod.config.storage = nil
|
216
288
|
a = CopyCat1.new 'mimo'
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
289
|
+
|
290
|
+
if RUBY_VERSION >= '1.9'
|
291
|
+
assert_equal ['hi'], a.echo('hi')
|
292
|
+
assert_equal 1, a.echo_count
|
293
|
+
|
294
|
+
assert_equal ['hi'], a.echo('hi')
|
295
|
+
assert_equal 1, a.echo_count
|
296
|
+
else
|
297
|
+
assert_equal 'hi', a.echo('hi')
|
298
|
+
assert_equal 1, a.echo_count
|
299
|
+
|
300
|
+
assert_equal 'hi', a.echo('hi')
|
301
|
+
assert_equal 1, a.echo_count
|
302
|
+
end
|
223
303
|
end
|
224
|
-
|
304
|
+
|
225
305
|
def test_cache_module_method
|
226
306
|
assert_equal 0, BlogM.request_count
|
227
307
|
assert_equal 'danke schoen', BlogM.get_latest_entries
|
@@ -229,14 +309,14 @@ class TestCacheMethod < Test::Unit::TestCase
|
|
229
309
|
assert_equal 'danke schoen', BlogM.get_latest_entries
|
230
310
|
assert_equal 1, BlogM.request_count
|
231
311
|
end
|
232
|
-
|
233
|
-
def
|
234
|
-
assert_raises(RuntimeError, /Used
|
312
|
+
|
313
|
+
def test_as_cache_key
|
314
|
+
assert_raises(RuntimeError, /Used as_cache_key/) do
|
235
315
|
a = CopyCat1a.new 'mimo'
|
236
316
|
a.echo 'hi'
|
237
317
|
end
|
238
318
|
end
|
239
|
-
|
319
|
+
|
240
320
|
def test_method_added_by_extension
|
241
321
|
assert_equal 'hi', CopyCat2.say('hi')
|
242
322
|
assert_equal 1, CopyCat2.say_count
|
@@ -244,17 +324,17 @@ class TestCacheMethod < Test::Unit::TestCase
|
|
244
324
|
assert_equal 'hi', CopyCat2.say('hi')
|
245
325
|
assert_equal 1, CopyCat2.say_count
|
246
326
|
end
|
247
|
-
|
327
|
+
|
248
328
|
def test_method_added_by_inclusion
|
249
329
|
a = CopyCat1.new 'sayer'
|
250
330
|
|
251
331
|
assert_equal 'hi', a.say('hi')
|
252
332
|
assert_equal 1, a.say_count
|
253
|
-
|
333
|
+
|
254
334
|
assert_equal 'hi', a.say('hi')
|
255
335
|
assert_equal 1, a.say_count
|
256
336
|
end
|
257
|
-
|
337
|
+
|
258
338
|
def test_not_confused_by_module
|
259
339
|
assert_equal 'hi', CopyCat2.say('hi')
|
260
340
|
assert_equal 1, CopyCat2.say_count
|
@@ -268,31 +348,58 @@ class TestCacheMethod < Test::Unit::TestCase
|
|
268
348
|
assert_equal 'hi', CopyCat1.say('hi')
|
269
349
|
assert_equal 1, CopyCat1.say_count
|
270
350
|
end
|
271
|
-
|
351
|
+
|
272
352
|
def test_disable_generational_caching
|
273
353
|
CacheMethod.config.generational = false
|
274
|
-
|
354
|
+
|
275
355
|
a = CopyCat1.new 'mimo'
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
356
|
+
|
357
|
+
if RUBY_VERSION >= '1.9'
|
358
|
+
assert_equal ['hi'], a.echo('hi')
|
359
|
+
assert_equal 1, a.echo_count
|
360
|
+
|
361
|
+
assert_equal ['hi'], a.echo('hi')
|
362
|
+
assert_equal 1, a.echo_count
|
363
|
+
else
|
364
|
+
assert_equal 'hi', a.echo('hi')
|
365
|
+
assert_equal 1, a.echo_count
|
366
|
+
|
367
|
+
assert_equal 'hi', a.echo('hi')
|
368
|
+
assert_equal 1, a.echo_count
|
369
|
+
end
|
282
370
|
end
|
283
|
-
|
284
|
-
def
|
371
|
+
|
372
|
+
def test_cant_cache_method_clear_without_generational_caching
|
285
373
|
CacheMethod.config.generational = false
|
286
374
|
|
287
375
|
a = new_instance_of_my_blog
|
288
376
|
assert_equal ["hello from #{a.name}"], a.get_latest_entries
|
289
377
|
assert_equal 1, a.request_count
|
290
|
-
|
378
|
+
|
291
379
|
assert_raises(::RuntimeError) do
|
292
|
-
a.
|
380
|
+
a.cache_method_clear :get_latest_entries
|
293
381
|
end
|
294
|
-
|
382
|
+
|
295
383
|
assert_equal ["hello from #{a.name}"], a.get_latest_entries
|
296
384
|
assert_equal 1, a.request_count
|
297
385
|
end
|
386
|
+
|
387
|
+
def test_doesnt_rely_on_to_s_for_args_digest
|
388
|
+
hello = DontStringifyMe.new("hello")
|
389
|
+
world = DontStringifyMe.new("world")
|
390
|
+
|
391
|
+
a = CopyCat1.new 'mimo'
|
392
|
+
|
393
|
+
a.echo(hello)
|
394
|
+
assert_equal 1, a.echo_count
|
395
|
+
|
396
|
+
a.echo(hello)
|
397
|
+
assert_equal 1, a.echo_count
|
398
|
+
|
399
|
+
a.echo(world)
|
400
|
+
assert_equal 2, a.echo_count
|
401
|
+
|
402
|
+
a.echo(world)
|
403
|
+
assert_equal 2, a.echo_count
|
404
|
+
end
|
298
405
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cache_method
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2012-03-01 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: cache
|
16
|
-
requirement: &
|
16
|
+
requirement: &2156275580 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,29 +21,7 @@ dependencies:
|
|
21
21
|
version: 0.2.1
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
25
|
-
- !ruby/object:Gem::Dependency
|
26
|
-
name: memcached
|
27
|
-
requirement: &2155073740 !ruby/object:Gem::Requirement
|
28
|
-
none: false
|
29
|
-
requirements:
|
30
|
-
- - ! '>='
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: '0'
|
33
|
-
type: :development
|
34
|
-
prerelease: false
|
35
|
-
version_requirements: *2155073740
|
36
|
-
- !ruby/object:Gem::Dependency
|
37
|
-
name: rake
|
38
|
-
requirement: &2155072900 !ruby/object:Gem::Requirement
|
39
|
-
none: false
|
40
|
-
requirements:
|
41
|
-
- - ! '>='
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
version: '0'
|
44
|
-
type: :development
|
45
|
-
prerelease: false
|
46
|
-
version_requirements: *2155072900
|
24
|
+
version_requirements: *2156275580
|
47
25
|
description: Like alias_method, but it's cache_method!
|
48
26
|
email:
|
49
27
|
- seamus@abshere.net
|
@@ -52,8 +30,9 @@ extensions: []
|
|
52
30
|
extra_rdoc_files: []
|
53
31
|
files:
|
54
32
|
- .gitignore
|
33
|
+
- CHANGELOG
|
55
34
|
- Gemfile
|
56
|
-
- README.
|
35
|
+
- README.markdown
|
57
36
|
- Rakefile
|
58
37
|
- cache_method.gemspec
|
59
38
|
- lib/cache_method.rb
|
@@ -83,7 +62,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
83
62
|
version: '0'
|
84
63
|
requirements: []
|
85
64
|
rubyforge_project: cache_method
|
86
|
-
rubygems_version: 1.8.
|
65
|
+
rubygems_version: 1.8.15
|
87
66
|
signing_key:
|
88
67
|
specification_version: 3
|
89
68
|
summary: Lets you cache methods (to memcached, redis, etc.) sort of like you can memoize
|
@@ -91,3 +70,4 @@ summary: Lets you cache methods (to memcached, redis, etc.) sort of like you can
|
|
91
70
|
test_files:
|
92
71
|
- test/helper.rb
|
93
72
|
- test/test_cache_method.rb
|
73
|
+
has_rdoc:
|