cache_method 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ rdoc/*
@@ -0,0 +1,45 @@
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
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in cache_method.gemspec
4
+ gemspec
data/README.rdoc ADDED
@@ -0,0 +1,95 @@
1
+ = cache_method
2
+
3
+ It's like <tt>alias_method</tt>, but it's <tt>cache_method</tt>!
4
+
5
+ == Example
6
+
7
+ require 'cache_method'
8
+ class Blog
9
+ attr_reader :name
10
+ attr_reader :url
11
+
12
+ def initialize(name, url)
13
+ @name = name
14
+ @url = url
15
+ end
16
+
17
+ # The method we're going to cache
18
+ def get_latest_entries
19
+ sleep 5
20
+ end
21
+
22
+ # What you get with this gem
23
+ cache_method :get_latest_entries
24
+
25
+ # Per Ruby convention, a "hash code" representing the internal state of an instance.
26
+ # It's recommended that you construct a String or a Hash and then call #hash on it.
27
+ def hash
28
+ { :name => name, :url => url }.hash
29
+ end
30
+ end
31
+
32
+ Then you can do
33
+
34
+ my_blog.get_latest_entries => first time won't be cached
35
+ my_blog.get_latest_entries => second time will come from cache
36
+
37
+ And clear them too
38
+
39
+ my_blog.clear_method_cache :get_latest_entries
40
+
41
+ (which doesn't delete the rest of your cache)
42
+
43
+ == Configuration (and supported cache clients)
44
+
45
+ You need to set a client that will be used to access the cache:
46
+
47
+ CacheMethod.config.client = Memcached.new '127.0.0.1:11211'
48
+
49
+ or
50
+
51
+ CacheMethod.config.client = Redis.new
52
+
53
+ or this might even work...
54
+
55
+ CacheMethod.config.client = Rails.cache
56
+
57
+ See <tt>Config</tt> for the full list of supported caches.
58
+
59
+ == Defining a #hash method (not the same as #to_hash)
60
+
61
+ Since we're not pure functional programmers, sometimes cache hits depend on object state in addition to method arguments. To illustrate:
62
+
63
+ my_blog.get_latest_entries
64
+
65
+ get_latest_entries doesn't take any arguments, so it must depend on my_blog.url or something. This works because we define:
66
+
67
+ class Blog
68
+ # [...]
69
+ def hash
70
+ { :name => name, :url => url }.hash
71
+ end
72
+ # [...]
73
+ end
74
+
75
+ You should follow Ruby convention and have <tt>#hash</tt> return a <tt>Fixnum</tt>.
76
+
77
+ Ideally, you should try to make a <tt>String</tt> or a <tt>Hash</tt> and call the standard <tt>#hash</tt> on that.
78
+
79
+ Note: this is NOT the same thing as <tt>#to_hash</tt>! That returns a <b><tt>Hash</tt></b>. What we want is an integer "hash code."
80
+
81
+ == Rationale
82
+
83
+ * It should be easy to cache a method using memcached.
84
+ * The main clients should be supported
85
+ * memcache-client (for people who use the Rails default)
86
+ * dalli (for people on heroku)
87
+ * memcached (for people using Evan Weaver's ultra-fast gem)
88
+ * redis (for people who like that sort of thing, but you won't get expiration)
89
+ * It should be easy to uncache a method without clearing the whole cache
90
+ * It should be easy to cache instance methods
91
+ * It should be easy to cache methods that depend on object state
92
+
93
+ == Copyright
94
+
95
+ Copyright 2011 Seamus Abshere
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rake'
5
+ require 'rake/testtask'
6
+ Rake::TestTask.new(:test) do |test|
7
+ test.libs << 'lib' << 'test'
8
+ test.pattern = 'test/**/test_*.rb'
9
+ test.verbose = true
10
+ end
11
+
12
+ task :default => :test
13
+
14
+ require 'rake/rdoctask'
15
+ Rake::RDocTask.new do |rdoc|
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
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "cache_method/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "cache_method"
7
+ s.version = CacheMethod::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Seamus Abshere"]
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}
14
+
15
+ s.rubyforge_project = "cache_method"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.require_paths = ["lib"]
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'
25
+ s.add_development_dependency 'memcached'
26
+ s.add_development_dependency 'dalli'
27
+ s.add_development_dependency 'memcache-client'
28
+ # if RUBY_VERSION >= '1.9'
29
+ # s.add_development_dependency 'ruby-debug19'
30
+ # else
31
+ # s.add_development_dependency 'ruby-debug'
32
+ # end
33
+ end
@@ -0,0 +1,45 @@
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
@@ -0,0 +1,56 @@
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
@@ -0,0 +1,65 @@
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
@@ -0,0 +1,45 @@
1
+ require 'singleton'
2
+ module CacheMethod
3
+ # Here's where you set config options.
4
+ #
5
+ # Example:
6
+ # CacheMethod.config.client = Memcached.new '127.0.0.1:11211'
7
+ # CacheMethod.config.default_ttl = 120 # seconds
8
+ #
9
+ # You'd probably put this in your Rails config/initializers, for example.
10
+ class Config
11
+ include ::Singleton
12
+
13
+ # Client for accessing the cache.
14
+ #
15
+ # Supported memcached clients:
16
+ # * memcached[https://github.com/fauna/memcached] (either a Memcached or a Memcached::Rails)
17
+ # * dalli[https://github.com/mperham/dalli] (either a Dalli::Client or an ActiveSupport::Cache::DalliStore)
18
+ # * memcache-client[https://github.com/mperham/memcache-client] (MemCache, the one commonly used by Rails)
19
+ #
20
+ # Supported Redis clients:
21
+ # * redis[https://github.com/ezmobius/redis-rb] (NOTE: AUTOMATIC CACHE EXPIRATION NOT SUPPORTED)
22
+ #
23
+ # Example:
24
+ # CacheMethod.config.client = Memcached.new '127.0.0.1:11211'
25
+ def client=(client)
26
+ @client = client
27
+ end
28
+
29
+ def client #:nodoc:
30
+ @client || raise("You need to set CacheMethod.config.client with a cache client of your choice")
31
+ end
32
+
33
+ # TTL for method caches. Defaults to 60 seconds.
34
+ #
35
+ # Example:
36
+ # CacheMethod.config.default_ttl = 120 # seconds
37
+ def default_ttl=(seconds)
38
+ @default_ttl = seconds
39
+ end
40
+
41
+ def default_ttl #:nodoc:
42
+ @default_ttl || 60
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,3 @@
1
+ module CacheMethod
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,61 @@
1
+ # See the README.rdoc for more info!
2
+ module CacheMethod
3
+ autoload :Config, 'cache_method/config'
4
+ autoload :Cache, 'cache_method/cache'
5
+
6
+ def self.config #:nodoc:
7
+ Config.instance
8
+ end
9
+
10
+ def self.cache #:nodoc:
11
+ Cache.instance
12
+ end
13
+
14
+ # All Objects, including instances and Classes, get the <tt>#clear_method_cache</tt> method.
15
+ module InstanceMethods
16
+ # Clear the cache for a particular method.
17
+ #
18
+ # Note: Remember to define <tt>#hash</tt> on any object whose instance methods might get cached.
19
+ #
20
+ # Example:
21
+ # my_blog.clear_method_cache :get_latest_entries
22
+ def clear_method_cache(method_id)
23
+ ::CacheMethod.cache.delete self, method_id
24
+ end
25
+ end
26
+
27
+ # All Classes (but not instances), get the <tt>.cache_method</tt> method.
28
+ module ClassMethods
29
+ # Cache a method. TTL in seconds, defaults to whatever's in CacheMethod.config.default_ttl
30
+ #
31
+ # Note: Remember to define <tt>#hash</tt> on any object whose instance methods might get cached.
32
+ #
33
+ # Note 2: Check out CacheMethod.config.default_ttl... the default is only 60 seconds.
34
+ #
35
+ # Example:
36
+ # class Blog
37
+ # # [...]
38
+ # def get_latest_entries
39
+ # sleep 5
40
+ # end
41
+ # # [...]
42
+ # cache_method :get_latest_entries
43
+ # # if you wanted a different ttl...
44
+ # # cache_method :get_latest_entries, 800 #seconds
45
+ # end
46
+ def cache_method(method_id, ttl = nil)
47
+ original_method_id = "_uncached_#{method_id}"
48
+ alias_method original_method_id, method_id
49
+ define_method method_id do |*args|
50
+ ::CacheMethod.cache.fetch self, method_id, ttl, *args do
51
+ send original_method_id, *args
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ unless ::Object.method_defined? :cache_method
59
+ ::Object.send :include, ::CacheMethod::InstanceMethods
60
+ ::Object.extend ::CacheMethod::ClassMethods
61
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,51 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ Bundler.setup
4
+ require 'test/unit'
5
+ # require 'ruby-debug'
6
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
7
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
8
+ require 'cache_method'
9
+
10
+ class Test::Unit::TestCase
11
+ def setup
12
+ CacheMethod.cache.flush
13
+ end
14
+ end
15
+
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
27
+ 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
47
+ end
48
+ end
49
+
50
+ $my_cache = random_cache
51
+ CacheMethod.config.client = $my_cache
@@ -0,0 +1,53 @@
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
@@ -0,0 +1,90 @@
1
+ require 'helper'
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
28
+
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'
35
+ end
36
+
37
+ def test_cache_method
38
+ a = new_instance_of_my_blog
39
+ assert_equal ["hello from #{a.name}"], a.get_latest_entries
40
+ assert_equal 1, a.request_count
41
+ a = new_instance_of_my_blog
42
+ assert_equal ["hello from #{a.name}"], a.get_latest_entries
43
+ assert_equal 0, a.request_count
44
+ xxx = new_instance_of_another_blog
45
+ assert_equal ["hello from #{xxx.name}"], xxx.get_latest_entries
46
+ assert_equal 1, xxx.request_count
47
+ end
48
+
49
+ def test_clear_method
50
+ a = new_instance_of_my_blog
51
+ assert_equal ["hello from #{a.name}"], a.get_latest_entries
52
+ assert_equal 1, a.request_count
53
+ a.clear_method_cache :get_latest_entries
54
+ assert_equal ["hello from #{a.name}"], a.get_latest_entries
55
+ assert_equal 2, a.request_count
56
+ end
57
+
58
+ def test_clear_a_different_method
59
+ a = new_instance_of_my_blog
60
+ assert_equal ["hello from #{a.name}"], a.get_latest_entries
61
+ assert_equal 1, a.request_count
62
+ a.clear_method_cache :foobar
63
+ assert_equal ["hello from #{a.name}"], a.get_latest_entries
64
+ assert_equal 1, a.request_count
65
+ end
66
+
67
+ def test_clear_from_somebody_else
68
+ a = new_instance_of_my_blog
69
+ assert_equal ["hello from #{a.name}"], a.get_latest_entries
70
+ assert_equal 1, a.request_count
71
+ xxx = new_instance_of_another_blog
72
+ assert_equal ["hello from #{xxx.name}"], xxx.get_latest_entries
73
+ assert_equal 1, xxx.request_count
74
+ xxx.clear_method_cache :get_latest_entries
75
+ assert_equal ["hello from #{a.name}"], a.get_latest_entries
76
+ assert_equal 1, a.request_count
77
+ assert_equal ["hello from #{xxx.name}"], xxx.get_latest_entries
78
+ assert_equal 2, xxx.request_count
79
+ end
80
+
81
+ def test_ttl
82
+ a = new_instance_of_my_blog
83
+ assert_equal ["voo vaa #{a.name}"], a.get_latest_entries2
84
+ assert_equal 1, a.request_count
85
+ a = new_instance_of_my_blog
86
+ sleep 2
87
+ assert_equal ["voo vaa #{a.name}"], a.get_latest_entries2
88
+ assert_equal 1, a.request_count
89
+ end
90
+ end
metadata ADDED
@@ -0,0 +1,183 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cache_method
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Seamus Abshere
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-02-15 00:00:00 -06:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: redis
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :development
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
+ - !ruby/object:Gem::Dependency
80
+ name: memcached
81
+ 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
111
+ none: false
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ hash: 3
116
+ segments:
117
+ - 0
118
+ version: "0"
119
+ type: :development
120
+ version_requirements: *id007
121
+ description: Lets you cache methods (to memcached, redis, etc.) sort of like you can memoize them
122
+ email:
123
+ - seamus@abshere.net
124
+ executables: []
125
+
126
+ extensions: []
127
+
128
+ extra_rdoc_files: []
129
+
130
+ files:
131
+ - .gitignore
132
+ - DEVELOPER_NOTES.rdoc
133
+ - Gemfile
134
+ - README.rdoc
135
+ - Rakefile
136
+ - cache_method.gemspec
137
+ - lib/cache_method.rb
138
+ - lib/cache_method/cache.rb
139
+ - lib/cache_method/cache/epoch.rb
140
+ - lib/cache_method/cache/key.rb
141
+ - lib/cache_method/config.rb
142
+ - lib/cache_method/version.rb
143
+ - test/helper.rb
144
+ - test/test_cache_class_methods.rb
145
+ - test/test_cache_instance_methods.rb
146
+ has_rdoc: true
147
+ homepage: ""
148
+ licenses: []
149
+
150
+ post_install_message:
151
+ rdoc_options: []
152
+
153
+ require_paths:
154
+ - lib
155
+ required_ruby_version: !ruby/object:Gem::Requirement
156
+ none: false
157
+ requirements:
158
+ - - ">="
159
+ - !ruby/object:Gem::Version
160
+ hash: 3
161
+ segments:
162
+ - 0
163
+ version: "0"
164
+ required_rubygems_version: !ruby/object:Gem::Requirement
165
+ none: false
166
+ requirements:
167
+ - - ">="
168
+ - !ruby/object:Gem::Version
169
+ hash: 3
170
+ segments:
171
+ - 0
172
+ version: "0"
173
+ requirements: []
174
+
175
+ rubyforge_project: cache_method
176
+ rubygems_version: 1.3.7
177
+ signing_key:
178
+ specification_version: 3
179
+ summary: Provides cache_method
180
+ test_files:
181
+ - test/helper.rb
182
+ - test/test_cache_class_methods.rb
183
+ - test/test_cache_instance_methods.rb