cache_method 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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