cache_method 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -3,3 +3,5 @@
3
3
  Gemfile.lock
4
4
  pkg/*
5
5
  rdoc/*
6
+ secret.sh
7
+ .DS_Store
data/README.rdoc CHANGED
@@ -42,17 +42,17 @@ And clear them too
42
42
 
43
43
  == Configuration (and supported cache clients)
44
44
 
45
- You need to set a client that will be used to access the cache:
45
+ You need to set where the cache will be stored:
46
46
 
47
- CacheMethod.config.client = Memcached.new '127.0.0.1:11211'
47
+ CacheMethod.config.storage = Memcached.new '127.0.0.1:11211'
48
48
 
49
49
  or
50
50
 
51
- CacheMethod.config.client = Redis.new
51
+ CacheMethod.config.storage = Redis.new
52
52
 
53
53
  or this might even work...
54
54
 
55
- CacheMethod.config.client = Rails.cache
55
+ CacheMethod.config.storage = Rails.cache
56
56
 
57
57
  See <tt>Config</tt> for the full list of supported caches.
58
58
 
data/cache_method.gemspec CHANGED
@@ -8,9 +8,9 @@ Gem::Specification.new do |s|
8
8
  s.platform = Gem::Platform::RUBY
9
9
  s.authors = ["Seamus Abshere"]
10
10
  s.email = ["seamus@abshere.net"]
11
- s.homepage = ""
12
- s.summary = %q{Provides cache_method}
13
- s.description = %q{Lets you cache methods (to memcached, redis, etc.) sort of like you can memoize them}
11
+ s.homepage = "https://github.com/seamusabshere/cache_method"
12
+ s.summary = %q{Lets you cache methods (to memcached, redis, etc.) sort of like you can memoize them}
13
+ s.description = %q{Like alias_method, but it's cache_method!}
14
14
 
15
15
  s.rubyforge_project = "cache_method"
16
16
 
@@ -18,13 +18,8 @@ Gem::Specification.new do |s|
18
18
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
19
  s.require_paths = ["lib"]
20
20
 
21
- s.add_development_dependency 'redis'
22
- s.add_development_dependency 'activesupport', '>=2.3.4'
23
- s.add_development_dependency 'i18n' # activesupport
24
- s.add_development_dependency 'test-unit'
21
+ s.add_dependency 'cache'
25
22
  s.add_development_dependency 'memcached'
26
- s.add_development_dependency 'dalli'
27
- s.add_development_dependency 'memcache-client'
28
23
  # if RUBY_VERSION >= '1.9'
29
24
  # s.add_development_dependency 'ruby-debug19'
30
25
  # else
@@ -0,0 +1,56 @@
1
+ require 'digest/md5'
2
+ module CacheMethod
3
+ class CachedResult #:nodoc: all
4
+ class << self
5
+ def fetch(options = {})
6
+ cached_result = new options
7
+ cached_result.fetch
8
+ end
9
+ end
10
+
11
+ def initialize(options = {})
12
+ options.each do |k, v|
13
+ instance_variable_set "@#{k}", v
14
+ end
15
+ end
16
+
17
+ attr_reader :obj
18
+ attr_reader :method_id
19
+ attr_reader :original_method_id
20
+ attr_reader :args
21
+
22
+ def fetch
23
+ if v = Config.instance.storage.get(cache_key) and v.is_a?(::Array)
24
+ v[0]
25
+ else
26
+ v = obj.send original_method_id, *args
27
+ Config.instance.storage.set cache_key, [v], ttl
28
+ v
29
+ end
30
+ end
31
+
32
+ def ttl
33
+ @ttl ||= Config.instance.default_ttl
34
+ end
35
+
36
+ def cache_key
37
+ [ method_signature, current_epoch, obj_hash, args_digest ].join ','
38
+ end
39
+
40
+ def method_signature
41
+ @method_signature ||= ::CacheMethod.method_signature(obj, method_id)
42
+ end
43
+
44
+ def obj_hash
45
+ @obj_hash ||= obj.hash
46
+ end
47
+
48
+ def args_digest
49
+ @args_digest ||= ::Digest::MD5.hexdigest(args.flatten.join)
50
+ end
51
+
52
+ def current_epoch
53
+ @current_epoch ||= Epoch.current(:obj => obj, :method_id => method_id)
54
+ end
55
+ end
56
+ end
@@ -1,16 +1,17 @@
1
+ require 'cache'
1
2
  require 'singleton'
2
3
  module CacheMethod
3
4
  # Here's where you set config options.
4
5
  #
5
6
  # Example:
6
- # CacheMethod.config.client = Memcached.new '127.0.0.1:11211'
7
+ # CacheMethod.config.storage = Memcached.new '127.0.0.1:11211'
7
8
  # CacheMethod.config.default_ttl = 120 # seconds
8
9
  #
9
10
  # You'd probably put this in your Rails config/initializers, for example.
10
11
  class Config
11
12
  include ::Singleton
12
13
 
13
- # Client for accessing the cache.
14
+ # Storage for the cache.
14
15
  #
15
16
  # Supported memcached clients:
16
17
  # * memcached[https://github.com/fauna/memcached] (either a Memcached or a Memcached::Rails)
@@ -18,16 +19,18 @@ module CacheMethod
18
19
  # * memcache-client[https://github.com/mperham/memcache-client] (MemCache, the one commonly used by Rails)
19
20
  #
20
21
  # Supported Redis clients:
21
- # * redis[https://github.com/ezmobius/redis-rb] (NOTE: AUTOMATIC CACHE EXPIRATION NOT SUPPORTED)
22
+ # * redis[https://github.com/ezmobius/redis-rb]
23
+ #
24
+ # Uses the cache[https://github.com/seamusabshere/cache] gem to wrap these, so support depends on that gem
22
25
  #
23
26
  # Example:
24
- # CacheMethod.config.client = Memcached.new '127.0.0.1:11211'
25
- def client=(client)
26
- @client = client
27
+ # CacheMethod.config.storage = Memcached.new '127.0.0.1:11211'
28
+ def storage=(raw_client)
29
+ @storage = ::Cache.new raw_client
27
30
  end
28
31
 
29
- def client #:nodoc:
30
- @client || raise("You need to set CacheMethod.config.client with a cache client of your choice")
32
+ def storage #:nodoc:
33
+ @storage || raise("You need to set CacheMethod.config.storage with a cache storage of your choice")
31
34
  end
32
35
 
33
36
  # TTL for method caches. Defaults to 60 seconds.
@@ -0,0 +1,44 @@
1
+ module CacheMethod
2
+ class Epoch #:nodoc: all
3
+ class << self
4
+ def current(options = {})
5
+ epoch = new options
6
+ epoch.current
7
+ end
8
+
9
+ def mark_passing(options = {})
10
+ epoch = new options
11
+ epoch.mark_passing
12
+ end
13
+ end
14
+
15
+ def initialize(options = {})
16
+ options.each do |k, v|
17
+ instance_variable_set "@#{k}", v
18
+ end
19
+ end
20
+
21
+ attr_reader :obj
22
+ attr_reader :method_id
23
+
24
+ def method_signature
25
+ @method_signature ||= ::CacheMethod.method_signature(obj, method_id)
26
+ end
27
+
28
+ def obj_hash
29
+ @obj_hash ||= obj.hash
30
+ end
31
+
32
+ def cache_key
33
+ [ 'CacheMethod', method_signature, obj_hash ].join ','
34
+ end
35
+
36
+ def current
37
+ Config.instance.storage.get(cache_key).to_i
38
+ end
39
+
40
+ def mark_passing
41
+ Config.instance.storage.set cache_key, (current+1), 0
42
+ end
43
+ end
44
+ end
@@ -1,3 +1,3 @@
1
1
  module CacheMethod
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
data/lib/cache_method.rb CHANGED
@@ -1,14 +1,24 @@
1
+ require 'cache_method/version'
1
2
  # See the README.rdoc for more info!
2
3
  module CacheMethod
3
4
  autoload :Config, 'cache_method/config'
4
- autoload :Cache, 'cache_method/cache'
5
+ autoload :CachedResult, 'cache_method/cached_result'
6
+ autoload :Epoch, 'cache_method/epoch'
5
7
 
6
8
  def self.config #:nodoc:
7
9
  Config.instance
8
10
  end
9
11
 
10
- def self.cache #:nodoc:
11
- Cache.instance
12
+ def self.klass_name(obj) #:nodoc:
13
+ obj.is_a?(::Class) ? obj.to_s : obj.class.to_s
14
+ end
15
+
16
+ def self.method_delimiter(obj) #:nodoc:
17
+ obj.is_a?(::Class) ? '.' : '#'
18
+ end
19
+
20
+ def self.method_signature(obj, method_id) #:nodoc:
21
+ [ klass_name(obj), method_id ].join method_delimiter(obj)
12
22
  end
13
23
 
14
24
  # All Objects, including instances and Classes, get the <tt>#clear_method_cache</tt> method.
@@ -20,7 +30,7 @@ module CacheMethod
20
30
  # Example:
21
31
  # my_blog.clear_method_cache :get_latest_entries
22
32
  def clear_method_cache(method_id)
23
- ::CacheMethod.cache.delete self, method_id
33
+ ::CacheMethod::Epoch.mark_passing :obj => self, :method_id => method_id
24
34
  end
25
35
  end
26
36
 
@@ -47,9 +57,7 @@ module CacheMethod
47
57
  original_method_id = "_uncached_#{method_id}"
48
58
  alias_method original_method_id, method_id
49
59
  define_method method_id do |*args|
50
- ::CacheMethod.cache.fetch self, method_id, ttl, *args do
51
- send original_method_id, *args
52
- end
60
+ ::CacheMethod::CachedResult.fetch :obj => self, :method_id => method_id, :original_method_id => original_method_id, :args => args, :ttl => ttl
53
61
  end
54
62
  end
55
63
  end
data/test/helper.rb CHANGED
@@ -8,44 +8,50 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
8
8
  require 'cache_method'
9
9
 
10
10
  class Test::Unit::TestCase
11
- def setup
12
- CacheMethod.cache.flush
13
- end
14
11
  end
15
12
 
16
- require 'memcached'
17
- require 'memcache'
18
- require 'redis'
19
- require 'dalli'
20
- require 'active_support/all'
21
- require 'active_support/cache/dalli_store'
22
- def random_cache
23
- c = if ENV['C']
24
- ENV['C'].to_i
25
- else
26
- rand 6
13
+ class Blog1
14
+ attr_reader :name
15
+ attr_reader :url
16
+ def initialize(name, url)
17
+ @name = name
18
+ @url = url
19
+ end
20
+ attr_writer :request_count
21
+ def request_count
22
+ @request_count ||= 0
23
+ end
24
+ def get_latest_entries
25
+ self.request_count += 1
26
+ ["hello from #{name}"]
27
+ end
28
+ cache_method :get_latest_entries
29
+ def get_latest_entries2
30
+ self.request_count += 1
31
+ ["voo vaa #{name}"]
27
32
  end
28
- case c
29
- when 0
30
- $stderr.puts 'using memcached'
31
- Memcached.new 'localhost:11211'
32
- when 1
33
- $stderr.puts 'using memcache-client'
34
- MemCache.new ['localhost:11211']
35
- when 2
36
- $stderr.puts 'using dalli'
37
- Dalli::Client.new ['localhost:11211']
38
- when 3
39
- $stderr.puts 'using dalli_store'
40
- ActiveSupport::Cache::DalliStore.new ['localhost:11211']
41
- when 4
42
- $stderr.puts 'using memcached-rails'
43
- Memcached::Rails.new 'localhost:11211'
44
- when 5
45
- $stderr.puts 'using Redis'
46
- Redis.new
33
+ cache_method :get_latest_entries2, 1 # second
34
+ def hash
35
+ { :name => name, :url => url }.hash
47
36
  end
48
37
  end
38
+ def new_instance_of_my_blog
39
+ Blog1.new 'my_blog', 'http://my_blog.example.com'
40
+ end
41
+ def new_instance_of_another_blog
42
+ Blog1.new 'another_blog', 'http://another_blog.example.com'
43
+ end
49
44
 
50
- $my_cache = random_cache
51
- CacheMethod.config.client = $my_cache
45
+ class Blog2
46
+ class << self
47
+ attr_writer :request_count
48
+ def request_count
49
+ @request_count ||= 0
50
+ end
51
+ def get_latest_entries
52
+ self.request_count += 1
53
+ 'danke schoen'
54
+ end
55
+ cache_method :get_latest_entries
56
+ end
57
+ end
@@ -1,40 +1,16 @@
1
1
  require 'helper'
2
2
 
3
- class Blog1
4
- attr_reader :name
5
- attr_reader :url
6
- def initialize(name, url)
7
- @name = name
8
- @url = url
9
- end
10
- attr_writer :request_count
11
- def request_count
12
- @request_count ||= 0
13
- end
14
- def get_latest_entries
15
- self.request_count += 1
16
- ["hello from #{name}"]
17
- end
18
- cache_method :get_latest_entries
19
- def get_latest_entries2
20
- self.request_count += 1
21
- ["voo vaa #{name}"]
22
- end
23
- cache_method :get_latest_entries2, 1 # second
24
- def hash
25
- { :name => name, :url => url }.hash
26
- end
27
- end
3
+ require 'memcached'
28
4
 
29
- class TestCacheInstanceMethods < Test::Unit::TestCase
30
- def new_instance_of_my_blog
31
- Blog1.new 'my_blog', 'http://my_blog.example.com'
32
- end
33
- def new_instance_of_another_blog
34
- Blog1.new 'another_blog', 'http://another_blog.example.com'
5
+ class TestCacheMethod < Test::Unit::TestCase
6
+ def setup
7
+ Blog2.request_count = 0
8
+ my_cache = Memcached.new '127.0.0.1:11211'
9
+ CacheMethod.config.storage = my_cache
10
+ my_cache.flush
35
11
  end
36
12
 
37
- def test_cache_method
13
+ def test_cache_instance_method
38
14
  a = new_instance_of_my_blog
39
15
  assert_equal ["hello from #{a.name}"], a.get_latest_entries
40
16
  assert_equal 1, a.request_count
@@ -46,7 +22,7 @@ class TestCacheInstanceMethods < Test::Unit::TestCase
46
22
  assert_equal 1, xxx.request_count
47
23
  end
48
24
 
49
- def test_clear_method
25
+ def test_clear_instance_method
50
26
  a = new_instance_of_my_blog
51
27
  assert_equal ["hello from #{a.name}"], a.get_latest_entries
52
28
  assert_equal 1, a.request_count
@@ -55,7 +31,7 @@ class TestCacheInstanceMethods < Test::Unit::TestCase
55
31
  assert_equal 2, a.request_count
56
32
  end
57
33
 
58
- def test_clear_a_different_method
34
+ def test_clear_correct_instance_method
59
35
  a = new_instance_of_my_blog
60
36
  assert_equal ["hello from #{a.name}"], a.get_latest_entries
61
37
  assert_equal 1, a.request_count
@@ -64,7 +40,7 @@ class TestCacheInstanceMethods < Test::Unit::TestCase
64
40
  assert_equal 1, a.request_count
65
41
  end
66
42
 
67
- def test_clear_from_somebody_else
43
+ def test_clear_instance_method_from_correct_instance
68
44
  a = new_instance_of_my_blog
69
45
  assert_equal ["hello from #{a.name}"], a.get_latest_entries
70
46
  assert_equal 1, a.request_count
@@ -78,13 +54,43 @@ class TestCacheInstanceMethods < Test::Unit::TestCase
78
54
  assert_equal 2, xxx.request_count
79
55
  end
80
56
 
81
- def test_ttl
57
+ def test_cache_instance_method_ttl
82
58
  a = new_instance_of_my_blog
83
59
  assert_equal ["voo vaa #{a.name}"], a.get_latest_entries2
84
60
  assert_equal 1, a.request_count
85
- a = new_instance_of_my_blog
86
61
  sleep 2
87
62
  assert_equal ["voo vaa #{a.name}"], a.get_latest_entries2
88
- assert_equal 1, a.request_count
63
+ assert_equal 2, a.request_count
64
+ end
65
+
66
+ def test_cache_class_method
67
+ assert_equal 0, Blog2.request_count
68
+ assert_equal 'danke schoen', Blog2.get_latest_entries
69
+ assert_equal 1, Blog2.request_count
70
+ assert_equal 'danke schoen', Blog2.get_latest_entries
71
+ assert_equal 1, Blog2.request_count
72
+ end
73
+
74
+ def test_clear_class_method
75
+ assert_equal 0, Blog2.request_count
76
+ assert_equal 'danke schoen', Blog2.get_latest_entries
77
+ assert_equal 1, Blog2.request_count
78
+ Blog2.clear_method_cache :get_latest_entries
79
+ assert_equal 'danke schoen', Blog2.get_latest_entries
80
+ assert_equal 2, Blog2.request_count
81
+ end
82
+
83
+ def test_clear_correct_class_method
84
+ assert_equal 0, Blog2.request_count
85
+ assert_equal 'danke schoen', Blog2.get_latest_entries
86
+ assert_equal 1, Blog2.request_count
87
+
88
+ Blog2.clear_method_cache :foobar
89
+ assert_equal 'danke schoen', Blog2.get_latest_entries
90
+ assert_equal 1, Blog2.request_count
91
+
92
+ Blog2.clear_method_cache :get_latest_entries
93
+ assert_equal 'danke schoen', Blog2.get_latest_entries
94
+ assert_equal 2, Blog2.request_count
89
95
  end
90
96
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cache_method
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 27
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 1
10
- version: 0.0.1
9
+ - 2
10
+ version: 0.0.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Seamus Abshere
@@ -15,11 +15,11 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-02-15 00:00:00 -06:00
18
+ date: 2011-02-17 00:00:00 -06:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
- name: redis
22
+ name: cache
23
23
  prerelease: false
24
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
25
  none: false
@@ -30,84 +30,12 @@ dependencies:
30
30
  segments:
31
31
  - 0
32
32
  version: "0"
33
- type: :development
33
+ type: :runtime
34
34
  version_requirements: *id001
35
- - !ruby/object:Gem::Dependency
36
- name: activesupport
37
- prerelease: false
38
- requirement: &id002 !ruby/object:Gem::Requirement
39
- none: false
40
- requirements:
41
- - - ">="
42
- - !ruby/object:Gem::Version
43
- hash: 11
44
- segments:
45
- - 2
46
- - 3
47
- - 4
48
- version: 2.3.4
49
- type: :development
50
- version_requirements: *id002
51
- - !ruby/object:Gem::Dependency
52
- name: i18n
53
- prerelease: false
54
- requirement: &id003 !ruby/object:Gem::Requirement
55
- none: false
56
- requirements:
57
- - - ">="
58
- - !ruby/object:Gem::Version
59
- hash: 3
60
- segments:
61
- - 0
62
- version: "0"
63
- type: :development
64
- version_requirements: *id003
65
- - !ruby/object:Gem::Dependency
66
- name: test-unit
67
- prerelease: false
68
- requirement: &id004 !ruby/object:Gem::Requirement
69
- none: false
70
- requirements:
71
- - - ">="
72
- - !ruby/object:Gem::Version
73
- hash: 3
74
- segments:
75
- - 0
76
- version: "0"
77
- type: :development
78
- version_requirements: *id004
79
35
  - !ruby/object:Gem::Dependency
80
36
  name: memcached
81
37
  prerelease: false
82
- requirement: &id005 !ruby/object:Gem::Requirement
83
- none: false
84
- requirements:
85
- - - ">="
86
- - !ruby/object:Gem::Version
87
- hash: 3
88
- segments:
89
- - 0
90
- version: "0"
91
- type: :development
92
- version_requirements: *id005
93
- - !ruby/object:Gem::Dependency
94
- name: dalli
95
- prerelease: false
96
- requirement: &id006 !ruby/object:Gem::Requirement
97
- none: false
98
- requirements:
99
- - - ">="
100
- - !ruby/object:Gem::Version
101
- hash: 3
102
- segments:
103
- - 0
104
- version: "0"
105
- type: :development
106
- version_requirements: *id006
107
- - !ruby/object:Gem::Dependency
108
- name: memcache-client
109
- prerelease: false
110
- requirement: &id007 !ruby/object:Gem::Requirement
38
+ requirement: &id002 !ruby/object:Gem::Requirement
111
39
  none: false
112
40
  requirements:
113
41
  - - ">="
@@ -117,8 +45,8 @@ dependencies:
117
45
  - 0
118
46
  version: "0"
119
47
  type: :development
120
- version_requirements: *id007
121
- description: Lets you cache methods (to memcached, redis, etc.) sort of like you can memoize them
48
+ version_requirements: *id002
49
+ description: Like alias_method, but it's cache_method!
122
50
  email:
123
51
  - seamus@abshere.net
124
52
  executables: []
@@ -129,22 +57,19 @@ extra_rdoc_files: []
129
57
 
130
58
  files:
131
59
  - .gitignore
132
- - DEVELOPER_NOTES.rdoc
133
60
  - Gemfile
134
61
  - README.rdoc
135
62
  - Rakefile
136
63
  - cache_method.gemspec
137
64
  - lib/cache_method.rb
138
- - lib/cache_method/cache.rb
139
- - lib/cache_method/cache/epoch.rb
140
- - lib/cache_method/cache/key.rb
65
+ - lib/cache_method/cached_result.rb
141
66
  - lib/cache_method/config.rb
67
+ - lib/cache_method/epoch.rb
142
68
  - lib/cache_method/version.rb
143
69
  - test/helper.rb
144
- - test/test_cache_class_methods.rb
145
- - test/test_cache_instance_methods.rb
70
+ - test/test_cache_method.rb
146
71
  has_rdoc: true
147
- homepage: ""
72
+ homepage: https://github.com/seamusabshere/cache_method
148
73
  licenses: []
149
74
 
150
75
  post_install_message:
@@ -176,8 +101,7 @@ rubyforge_project: cache_method
176
101
  rubygems_version: 1.3.7
177
102
  signing_key:
178
103
  specification_version: 3
179
- summary: Provides cache_method
104
+ summary: Lets you cache methods (to memcached, redis, etc.) sort of like you can memoize them
180
105
  test_files:
181
106
  - test/helper.rb
182
- - test/test_cache_class_methods.rb
183
- - test/test_cache_instance_methods.rb
107
+ - test/test_cache_method.rb
data/DEVELOPER_NOTES.rdoc DELETED
@@ -1,45 +0,0 @@
1
- = Developer notes
2
-
3
- == Lots of cache method signatures...
4
-
5
- def get(k)
6
- if defined?(::Memcached) and raw_client.is_a?(::Memcached)
7
- # def get(keys, marshal=true)
8
- begin; raw_client.get(k.to_s); rescue ::Memcached::NotFound; nil; end
9
- elsif defined?(::Memcached::Rails) and raw_client.is_a?(::Memcached::Rails)
10
- # def get(key, raw=false)
11
- raw_client.get k.to_s
12
- elsif defined?(::Dalli::Client) and raw_client.is_a?(::Dalli::Client)
13
- # def get(key, options=nil)
14
- raw_client.get k.to_s
15
- elsif defined?(::MemCache) and raw_client.is_a?(::MemCache)
16
- # def get(key, raw = false)
17
- raw_client.get k.to_s
18
- elsif defined?(::ActiveSupport::Cache::Store) and raw_client.is_a?(::ActiveSupport::Cache::Store)
19
- # def read(name, options = nil)
20
- raw_client.read k.to_s
21
- else
22
- raise "Unknown client: #{raw_client.inspect}"
23
- end
24
- end
25
-
26
- def set(k, v)
27
- if defined?(::Memcached) and raw_client.is_a?(::Memcached)
28
- # def set(key, value, ttl=@default_ttl, marshal=true, flags=FLAGS)
29
- raw_client.set k.to_s, v, ttl
30
- elsif defined?(::Memcached::Rails) and raw_client.is_a?(::Memcached::Rails)
31
- # def set(key, value, ttl=@default_ttl, raw=false)
32
- raw_client.set k.to_s, v, ttl
33
- elsif defined?(::Dalli::Client) and raw_client.is_a?(::Dalli::Client)
34
- # def set(key, value, ttl=nil, options=nil)
35
- raw_client.set k.to_s, v, ttl
36
- elsif defined?(::MemCache) and raw_client.is_a?(::MemCache)
37
- # def set(key, value, expiry = 0, raw = false)
38
- raw_client.set k.to_s, v, ttl
39
- elsif defined?(::ActiveSupport::Cache::Store) and raw_client.is_a?(::ActiveSupport::Cache::Store)
40
- # def write(name, value, options = nil)
41
- raw_client.write k.to_s, v, :expires_in => ttl
42
- else
43
- raise "Unknown client: #{raw_client.inspect}"
44
- end
45
- end
@@ -1,45 +0,0 @@
1
- module CacheMethod
2
- class Cache
3
- class Epoch
4
- class << self
5
- def mark_passing(options = {})
6
- e = new options
7
- e.mark_passing
8
- end
9
- def current(options = {})
10
- e = new options
11
- e.current
12
- end
13
- end
14
-
15
- def initialize(options = {})
16
- options.each do |k, v|
17
- instance_variable_set "@#{k}", v
18
- end
19
- end
20
-
21
- attr_reader :obj
22
- attr_reader :method_id
23
-
24
- def method_signature
25
- @method_signature ||= Key.method_signature(obj, method_id)
26
- end
27
-
28
- def obj_hash
29
- @obj_hash ||= obj.hash
30
- end
31
-
32
- def cache_key
33
- [ 'CacheMethod', method_signature, obj_hash ].join ','
34
- end
35
-
36
- def current
37
- Cache.instance.get(cache_key).to_i
38
- end
39
-
40
- def mark_passing
41
- Cache.instance.set cache_key, (current+1), 0
42
- end
43
- end
44
- end
45
- end
@@ -1,56 +0,0 @@
1
- require 'digest/md5'
2
- module CacheMethod
3
- class Cache
4
- class Key
5
- class << self
6
- def digest(*ary)
7
- ::Digest::MD5.hexdigest ary.flatten.map { |i| i.to_s }.join
8
- end
9
- def parse(str)
10
- method_signature, epoch, obj_hash, args_digest = str.split ','
11
- new :method_signature => method_signature, :epoch => epoch, :obj_hash => obj_hash, :args_digest => args_digest
12
- end
13
- def klass_name(obj)
14
- obj.is_a?(::Class) ? obj.to_s : obj.class.to_s
15
- end
16
- def method_delimiter(obj)
17
- obj.is_a?(::Class) ? '.' : '#'
18
- end
19
- def method_signature(obj, method_id)
20
- [ klass_name(obj), method_id ].join method_delimiter(obj)
21
- end
22
- end
23
-
24
- def initialize(options = {})
25
- options.each do |k, v|
26
- instance_variable_set "@#{k}", v
27
- end
28
- end
29
-
30
- attr_reader :obj
31
- attr_reader :method_id
32
- attr_reader :args
33
-
34
- def obj_hash
35
- @obj_hash ||= obj.hash
36
- end
37
-
38
- def args_digest
39
- @args_digest ||= Key.digest(args)
40
- end
41
-
42
- def method_signature
43
- @method_signature ||= Key.method_signature(obj, method_id)
44
- end
45
-
46
- def epoch
47
- @epoch ||= Epoch.current(:obj => obj, :method_id => method_id)
48
- end
49
-
50
- def to_str
51
- [ method_signature, epoch, obj_hash, args_digest ].join ','
52
- end
53
- alias :to_s :to_str
54
- end
55
- end
56
- end
@@ -1,65 +0,0 @@
1
- require 'singleton'
2
- module CacheMethod
3
- # All cache requests go through a clearinghouse, allowing uncaching.
4
- class Cache #:nodoc: all
5
- autoload :Key, 'cache_method/cache/key'
6
- autoload :Epoch, 'cache_method/cache/epoch'
7
-
8
- include ::Singleton
9
-
10
- def flush
11
- bare_client.send %w{ flush flush_all clear flushdb }.detect { |c| bare_client.respond_to? c }
12
- end
13
-
14
- def fetch(obj, method_id, ttl, *args)
15
- k = Key.new :obj => obj, :method_id => method_id, :args => args
16
- if cached_v = get(k.to_s)
17
- return cached_v
18
- end
19
- v = yield
20
- set k.to_s, v, ttl
21
- v
22
- end
23
-
24
- def delete(obj, method_id)
25
- Epoch.mark_passing :obj => obj, :method_id => method_id
26
- end
27
-
28
- def get(k)
29
- if defined?(::Memcached) and bare_client.is_a?(::Memcached)
30
- begin; bare_client.get(k); rescue ::Memcached::NotFound; nil; end
31
- elsif defined?(::Redis) and bare_client.is_a?(::Redis)
32
- if cached_v = bare_client.get(k)
33
- ::Marshal.load cached_v
34
- end
35
- elsif bare_client.respond_to?(:get)
36
- bare_client.get k
37
- elsif bare_client.respond_to?(:read)
38
- bare_client.read k
39
- else
40
- raise "Don't know how to work with #{bare_client.inspect}"
41
- end
42
- end
43
-
44
- def set(k, v, ttl)
45
- ttl ||= ::CacheMethod.config.default_ttl
46
- if defined?(::Redis) and bare_client.is_a?(::Redis)
47
- bare_client.set k, ::Marshal.dump(v)
48
- elsif bare_client.respond_to?(:set)
49
- bare_client.set k, v, ttl
50
- elsif bare_client.respond_to?(:write)
51
- if ttl == 0
52
- bare_client.write k, v # never expire
53
- else
54
- bare_client.write k, v, :expires_in => ttl
55
- end
56
- else
57
- raise "Don't know how to work with #{bare_client.inspect}"
58
- end
59
- end
60
-
61
- def bare_client
62
- ::CacheMethod.config.client
63
- end
64
- end
65
- end
@@ -1,53 +0,0 @@
1
- require 'helper'
2
-
3
- class Blog2
4
- class << self
5
- attr_writer :request_count
6
- def request_count
7
- @request_count ||= 0
8
- end
9
- def get_latest_entries
10
- self.request_count += 1
11
- 'danke schoen'
12
- end
13
- cache_method :get_latest_entries
14
- end
15
- end
16
-
17
- class TestCacheClassMethods < Test::Unit::TestCase
18
- def setup
19
- super
20
- Blog2.request_count = 0
21
- end
22
-
23
- def test_cache_method
24
- assert_equal 0, Blog2.request_count
25
- assert_equal 'danke schoen', Blog2.get_latest_entries
26
- assert_equal 1, Blog2.request_count
27
- assert_equal 'danke schoen', Blog2.get_latest_entries
28
- assert_equal 1, Blog2.request_count
29
- end
30
-
31
- def test_clear_method
32
- assert_equal 0, Blog2.request_count
33
- assert_equal 'danke schoen', Blog2.get_latest_entries
34
- assert_equal 1, Blog2.request_count
35
- Blog2.clear_method_cache :get_latest_entries
36
- assert_equal 'danke schoen', Blog2.get_latest_entries
37
- assert_equal 2, Blog2.request_count
38
- end
39
-
40
- def test_clear_method_doesnt_overstep
41
- assert_equal 0, Blog2.request_count
42
- assert_equal 'danke schoen', Blog2.get_latest_entries
43
- assert_equal 1, Blog2.request_count
44
-
45
- Blog2.clear_method_cache :foobar
46
- assert_equal 'danke schoen', Blog2.get_latest_entries
47
- assert_equal 1, Blog2.request_count
48
-
49
- Blog2.clear_method_cache :get_latest_entries
50
- assert_equal 'danke schoen', Blog2.get_latest_entries
51
- assert_equal 2, Blog2.request_count
52
- end
53
- end