jashmenn-method_cache 0.7.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Justin Balthrop
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,40 @@
1
+ = MethodCache
2
+
3
+ MethodCache lets you easily cache the results of any instance method or class method in
4
+ Ruby.
5
+
6
+ == Usage:
7
+
8
+ class Foo
9
+ extend MethodCache
10
+
11
+ cache_method :bar
12
+ def bar
13
+ # do expensive calculation
14
+ end
15
+
16
+ cache_class_method :baz, :clone => true, :expiry => 1.day
17
+ def self.baz
18
+ # do some expensive calculation that will be invalid tomorrow
19
+ end
20
+ end
21
+
22
+ foo = Foo.new
23
+ foo.bar # does calculation
24
+ foo.bar # cached
25
+
26
+ Foo.baz # does calculation
27
+ Foo.baz # cached
28
+
29
+ Foo.invalidate_cached_method(:baz)
30
+
31
+ Foo.baz # does calculation
32
+ Foo.baz # cached
33
+
34
+ == Install:
35
+
36
+ gem install method_cache
37
+
38
+ == License:
39
+
40
+ Copyright (c) 2010 Justin Balthrop, Geni.com; Published under The MIT License, see LICENSE
@@ -0,0 +1,45 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ begin
6
+ require 'jeweler'
7
+ Jeweler::Tasks.new do |s|
8
+ s.name = "jashmenn-method_cache"
9
+ s.summary = %Q{Simple memcache-based memoization library for Ruby}
10
+ s.email = "code@justinbalthrop.com"
11
+ s.homepage = "http://github.com/ninjudd/method_cache"
12
+ s.description = "Simple memcache-based memoization library for Ruby"
13
+ s.authors = ["Justin Balthrop"]
14
+ # s.add_dependency('memcache', '>= 1.0.0')
15
+ end
16
+ Jeweler::GemcutterTasks.new
17
+ rescue LoadError
18
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
19
+ end
20
+
21
+ Rake::TestTask.new do |t|
22
+ t.libs << ['lib', 'test']
23
+ t.pattern = 'test/**/*_test.rb'
24
+ t.verbose = false
25
+ end
26
+
27
+ Rake::RDocTask.new do |rdoc|
28
+ rdoc.rdoc_dir = 'rdoc'
29
+ rdoc.title = 'method_cache'
30
+ rdoc.options << '--line-numbers' << '--inline-source'
31
+ rdoc.rdoc_files.include('README*')
32
+ rdoc.rdoc_files.include('lib/**/*.rb')
33
+ end
34
+
35
+ begin
36
+ require 'rcov/rcovtask'
37
+ Rcov::RcovTask.new do |t|
38
+ t.libs << 'test'
39
+ t.test_files = FileList['test/**/*_test.rb']
40
+ t.verbose = true
41
+ end
42
+ rescue LoadError
43
+ end
44
+
45
+ task :default => :test
@@ -0,0 +1,5 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 7
4
+ :patch: 1
5
+ :build: 0
@@ -0,0 +1,186 @@
1
+ $:.unshift(File.dirname(__FILE__))
2
+ require 'method_cache/proxy'
3
+
4
+ module MethodCache
5
+ def cache_method(method_name, opts = {})
6
+ method_name = method_name.to_sym
7
+ proxy = opts.kind_of?(Proxy) ? opts : Proxy.new(method_name, opts)
8
+
9
+ if self.class == Class
10
+ return if instance_methods.include?(proxy.method_name_without_caching)
11
+
12
+ if cached_instance_methods.empty?
13
+ include(InvalidationMethods)
14
+ extend(MethodAdded)
15
+ end
16
+
17
+ cached_instance_methods[method_name] = nil
18
+ if method_defined?(method_name) or private_method_defined?(method_name)
19
+ if proxy.opts[:counter]
20
+ define_method "increment_#{method_name}", proxy.counter_method(:increment)
21
+ define_method "decrement_#{method_name}", proxy.counter_method(:decrement)
22
+ end
23
+
24
+ # Replace instance method.
25
+ alias_method proxy.method_name_without_caching, method_name
26
+ define_method method_name, proxy.method_with_caching
27
+ end
28
+ cached_instance_methods[method_name] = proxy
29
+
30
+ elsif self.class == Module
31
+ # We will alias all methods when the module is mixed-in.
32
+ extend(ModuleAdded) if cached_module_methods.empty?
33
+ cached_module_methods[method_name.to_sym] = proxy
34
+ end
35
+ end
36
+
37
+ def cache_class_method(method_name, opts = {})
38
+ method_name = method_name.to_sym
39
+ proxy = opts.kind_of?(Proxy) ? opts : Proxy.new(method_name, opts)
40
+
41
+ return if methods.include?(proxy.method_name_without_caching)
42
+
43
+ if cached_class_methods.empty?
44
+ extend(InvalidationMethods)
45
+ extend(SingletonMethodAdded)
46
+ end
47
+
48
+ method_name = method_name.to_sym
49
+ cached_class_methods[method_name] = nil
50
+ if class_method_defined?(method_name)
51
+ (class << self; self; end).module_eval do
52
+ if proxy.opts[:counter]
53
+ define_method "increment_#{method_name}", proxy.counter_method(:increment)
54
+ define_method "decrement_#{method_name}", proxy.counter_method(:decrement)
55
+ end
56
+
57
+ # Replace class method.
58
+ alias_method proxy.method_name_without_caching, method_name
59
+ define_method method_name, proxy.method_with_caching
60
+ end
61
+ end
62
+ cached_class_methods[method_name] = proxy
63
+ end
64
+
65
+ def class_method_defined?(method_name)
66
+ method(method_name)
67
+ true
68
+ rescue NameError
69
+ false
70
+ end
71
+
72
+ def self.default_cache
73
+ @default_cache ||= {}
74
+ end
75
+
76
+ def cached_instance_methods(method_name = nil)
77
+ if method_name
78
+ method_name = method_name.to_sym
79
+ ancestors.each do |klass|
80
+ next unless klass.kind_of?(MethodCache)
81
+ proxy = klass.cached_instance_methods[method_name]
82
+ return proxy if proxy
83
+ end
84
+ nil
85
+ else
86
+ @cached_instance_methods ||= {}
87
+ end
88
+ end
89
+
90
+ def cached_class_methods(method_name = nil)
91
+ if method_name
92
+ method_name = method_name.to_sym
93
+ ancestors.each do |klass|
94
+ next unless klass.kind_of?(MethodCache)
95
+ proxy = klass.cached_class_methods[method_name]
96
+ return proxy if proxy
97
+ end
98
+ nil
99
+ else
100
+ @cached_class_methods ||= {}
101
+ end
102
+ end
103
+
104
+ def cached_module_methods(method_name = nil)
105
+ if method_name
106
+ cached_module_methods[method_name.to_sym]
107
+ else
108
+ @cached_module_methods ||= {}
109
+ end
110
+ end
111
+
112
+ def self.disable(&block)
113
+ @disabled, old = true, @disabled
114
+ yield
115
+ ensure
116
+ @disabled = old
117
+ end
118
+
119
+ def self.disabled?
120
+ @disabled
121
+ end
122
+
123
+ module InvalidationMethods
124
+ def invalidate_cached_method(method_name, *args, &block)
125
+ cached_method(method_name, args).invalidate(&block)
126
+ end
127
+
128
+ def method_value_cached?(method_name, *args)
129
+ cached_method(method_name, args).cached?
130
+ end
131
+
132
+ def update_cached_method(method_name, *args, &block)
133
+ cached_method(method_name, args).update(&block)
134
+ end
135
+
136
+ def without_method_cache(&block)
137
+ MethodCache.disable(&block)
138
+ end
139
+
140
+ private
141
+
142
+ def cached_method(method_name, args)
143
+ if self.kind_of?(Class) or self.kind_of?(Module)
144
+ proxy = cached_class_methods(method_name)
145
+ else
146
+ proxy = self.class.send(:cached_instance_methods, method_name)
147
+ end
148
+ raise "method '#{method_name}' not cached" unless proxy
149
+ proxy.bind(self, args)
150
+ end
151
+ end
152
+
153
+ module MethodAdded
154
+ def method_added(method_name)
155
+ if proxy = cached_instance_methods(method_name)
156
+ cache_method(method_name, proxy)
157
+ end
158
+ super
159
+ end
160
+ end
161
+
162
+ module SingletonMethodAdded
163
+ def singleton_method_added(method_name)
164
+ if proxy = cached_class_methods(method_name)
165
+ cache_class_method(method_name, proxy)
166
+ end
167
+ super
168
+ end
169
+ end
170
+
171
+ module ModuleAdded
172
+ def extended(mod)
173
+ mod.extend(MethodCache)
174
+ cached_module_methods.each do |method_name, proxy|
175
+ mod.cache_class_method(method_name, proxy)
176
+ end
177
+ end
178
+
179
+ def included(mod)
180
+ mod.extend(MethodCache)
181
+ cached_module_methods.each do |method_name, proxy|
182
+ mod.cache_method(method_name, proxy)
183
+ end
184
+ end
185
+ end
186
+ end
@@ -0,0 +1,220 @@
1
+ require 'digest/sha1'
2
+
3
+ class Object
4
+ def metaclass; class << self; self; end; end
5
+ end
6
+
7
+ module MethodCache
8
+ class Proxy
9
+ attr_reader :method_name, :opts, :args, :target
10
+ NULL = 'NULL'
11
+
12
+ def initialize(method_name, opts)
13
+ opts[:cache] ||= :counters if opts[:counter]
14
+ @method_name = method_name
15
+ @opts = opts
16
+ end
17
+
18
+ def bind(target, args)
19
+ self.clone.bind!(target, args)
20
+ end
21
+
22
+ def bind!(target, args)
23
+ @target = target
24
+ @args = args
25
+ @key = nil
26
+ self
27
+ end
28
+
29
+ def invalidate
30
+ if block_given?
31
+ # Only invalidate if the block returns true.
32
+ value = cache[key]
33
+ return if value and not yield(value)
34
+ end
35
+ cache.delete(key)
36
+ end
37
+
38
+ def context
39
+ opts[:context]
40
+ end
41
+
42
+ def version
43
+ dynamic_opt(:version)
44
+ end
45
+
46
+ def cached?
47
+ not cache[key].nil?
48
+ end
49
+
50
+ def update
51
+ value = block_given? ? yield(cache[key]) : target.send(method_name_without_caching, *args)
52
+ write_to_cache(key, value)
53
+ value
54
+ end
55
+
56
+ def value
57
+ value = opts[:counter] ? cache.count(key) : cache[key] unless MethodCache.disabled?
58
+ value = nil unless valid?(:load, value)
59
+
60
+ if value.nil?
61
+ value = target.send(method_name_without_caching, *args)
62
+ raise "non-integer value returned by counter method" if opts[:counter] and not value.kind_of?(Fixnum)
63
+ write_to_cache(key, value) if valid?(:save, value)
64
+ end
65
+
66
+ value = nil if value == NULL
67
+ if clone? and value
68
+ value.clone
69
+ else
70
+ value
71
+ end
72
+ end
73
+
74
+ def method_with_caching
75
+ proxy = self # Need access to the proxy in the closure.
76
+
77
+ lambda do |*args|
78
+ proxy.bind(self, args).value
79
+ end
80
+ end
81
+
82
+ def counter_method(method_name)
83
+ proxy = self # Need access to the proxy in the closure.
84
+
85
+ lambda do |*args|
86
+ if args.last.kind_of?(Hash) and args.last.keys == [:by]
87
+ amount = args.last[:by]
88
+ args.pop
89
+ end
90
+ proxy.bind(self, args).send(method_name, amount || 1)
91
+ end
92
+ end
93
+
94
+ def method_name_without_caching
95
+ @method_name_without_caching ||= begin
96
+ base_name, punctuation = method_name.to_s.sub(/([?!=])$/, ''), $1
97
+ "#{base_name}_without_caching#{punctuation}"
98
+ end
99
+ end
100
+
101
+ def cache
102
+ if @cache.nil?
103
+ @cache = opts[:cache] || MethodCache.default_cache
104
+ @cache = Memcache.pool[@cache] if @cache.kind_of?(Symbol)
105
+ if not @cache.respond_to?(:[]) and @cache.respond_to?(:get)
106
+ @cache.metaclass.module_eval do
107
+ define_method :[] do |key|
108
+ get(key)
109
+ end
110
+ end
111
+ end
112
+ end
113
+ @cache
114
+ end
115
+
116
+ def local?
117
+ cache.kind_of?(Hash)
118
+ end
119
+
120
+ def clone?
121
+ !!opts[:clone]
122
+ end
123
+
124
+ def key
125
+ if @key.nil?
126
+ arg_string = ([method_name, target] + args).collect do |arg|
127
+ object_key(arg)
128
+ end.join('|')
129
+ @key = ['m', version, arg_string].compact.join('|')
130
+ @key = "m|#{Digest::SHA1.hexdigest(@key)}" if @key.length > 250
131
+ end
132
+ @key
133
+ end
134
+
135
+ private
136
+
137
+ def expiry(value)
138
+ value = dynamic_opt(:expiry, value).to_i
139
+ if defined?(Memcache) and cache.kind_of?(Memcache)
140
+ {:expiry => value}
141
+ else
142
+ value
143
+ end
144
+ end
145
+
146
+ def valid?(type, value)
147
+ name = "#{type}_validation".to_sym
148
+ return true unless opts[name]
149
+ return unless value
150
+
151
+ dynamic_opt(name, value)
152
+ end
153
+
154
+ def dynamic_opt(name, value = nil)
155
+ if opts[name].kind_of?(Proc)
156
+ proc = opts[name].bind(target)
157
+ case proc.arity
158
+ when 0 then proc.call()
159
+ when 1 then proc.call(value)
160
+ else
161
+ proc.call(value, *args)
162
+ end
163
+ else
164
+ opts[name]
165
+ end
166
+ end
167
+
168
+ def write_to_cache(key, value)
169
+ unless opts[:counter]
170
+ value = value.nil? ? NULL : value
171
+ end
172
+ if cache.kind_of?(Hash)
173
+ raise 'expiry not permitted when cache is a Hash' if opts[:expiry]
174
+ raise 'counter cache not permitted when cache is a Hash' if opts[:counter]
175
+ cache[key] = value
176
+ elsif opts[:counter]
177
+ cache.write(key, value.to_s, expiry(value))
178
+ else
179
+ cache.set(key, value, expiry(value))
180
+ end
181
+ end
182
+
183
+ def increment(amount)
184
+ raise "cannot increment non-counter method" unless opts[:counter]
185
+ cache.incr(key, amount)
186
+ end
187
+
188
+ def decrement(amount)
189
+ raise "cannot decrement non-counter method" unless opts[:counter]
190
+ cache.decr(key, amount)
191
+ end
192
+
193
+ def object_key(arg)
194
+ return "#{class_key(arg.class)}-#{arg.string_hash}" if arg.respond_to?(:string_hash)
195
+
196
+ case arg
197
+ when NilClass then 'nil'
198
+ when TrueClass then 'true'
199
+ when FalseClass then 'false'
200
+ when Numeric then arg.to_s
201
+ when Symbol then ":#{arg}"
202
+ when String then "'#{arg}'"
203
+ when Class, Module then class_key(arg)
204
+ when Hash
205
+ '{' + arg.collect {|key, value| "#{object_key(key)}=#{object_key(value)}"}.sort.join(',') + '}'
206
+ when Array
207
+ '[' + arg.collect {|item| object_key(item)}.join(',') + ']'
208
+ when defined?(ActiveRecord::Base) && ActiveRecord::Base
209
+ "#{class_key(arg.class)}-#{arg.id}"
210
+ else
211
+ hash = local? ? arg.hash : Marshal.dump(arg).hash
212
+ "#{class_key(arg.class)}-#{hash}"
213
+ end
214
+ end
215
+
216
+ def class_key(klass)
217
+ klass.respond_to?(:version) ? "#{klass.name}_#{klass.version(context)}" : klass.name
218
+ end
219
+ end
220
+ end
@@ -0,0 +1,25 @@
1
+ require 'test_helper'
2
+ require 'dalli'
3
+
4
+ PORT = 19112
5
+ $client = Dalli::Client.new("localhost:#{PORT}")
6
+
7
+ class FooBar
8
+ extend MethodCache
9
+
10
+ cache_method :foo, :cache => $client
11
+ def foo
12
+ 'bar'
13
+ end
14
+ end
15
+
16
+ class MethodCacheRemoteTest < Test::Unit::TestCase
17
+
18
+ should 'work with dalli client' do
19
+ start_memcache(PORT)
20
+ $client.flush
21
+
22
+ f = FooBar.new
23
+ assert_equal 'bar', f.foo
24
+ end
25
+ end
@@ -0,0 +1,201 @@
1
+ require 'test_helper'
2
+ require 'memcache'
3
+
4
+ class Foo
5
+ extend MethodCache
6
+
7
+ def foo(i)
8
+ @i ||= 0
9
+ @i += i
10
+ end
11
+ cache_method :foo
12
+
13
+ cache_method :bar
14
+ def bar
15
+ @i ||= 0
16
+ @i += 1
17
+ end
18
+
19
+ @@i = 0
20
+ def baz(i)
21
+ @@i += i
22
+ end
23
+ cache_method :baz, :cache => :remote
24
+
25
+ cache_class_method :bap
26
+ def self.bap(i)
27
+ @i ||= 0
28
+ @i += i
29
+ end
30
+
31
+ cache_class_method :zap, :counter => true
32
+ def self.zap
33
+ 0
34
+ end
35
+
36
+ attr_accessor :z
37
+ def zang
38
+ self.z ||= 1
39
+ self.z += 1
40
+ nil
41
+ end
42
+ cache_method :zang
43
+ end
44
+
45
+ module Bar
46
+ extend MethodCache
47
+
48
+ cache_method :foo
49
+ def foo(i)
50
+ @i ||= 0
51
+ @i += i
52
+ end
53
+
54
+ cache_method :foo_count, :counter => true, :cache => :default
55
+ def foo_count(key)
56
+ 100
57
+ end
58
+ end
59
+
60
+ class Baz
61
+ include Bar
62
+ extend Bar
63
+ end
64
+
65
+ class TestMethodCache < Test::Unit::TestCase
66
+ should 'cache methods locally' do
67
+ a = Foo.new
68
+ f1 = a.foo(1)
69
+ f2 = a.foo(2)
70
+
71
+ assert_equal 1, f1
72
+ assert_equal 3, f2
73
+
74
+ assert f1 == a.foo(1)
75
+ assert f1 != f2
76
+ assert f2 == a.foo(2)
77
+
78
+ b = a.bar
79
+ assert b == a.bar
80
+ assert b == a.bar
81
+ end
82
+
83
+ should 'disable method_cache' do
84
+ a = Foo.new
85
+ f1 = a.foo(1)
86
+
87
+ f2 = a.without_method_cache do
88
+ a.foo(1)
89
+ end
90
+
91
+ f3 = MethodCache.disable do
92
+ a.foo(1)
93
+ end
94
+
95
+ assert f1 != f2
96
+ assert f1 != f3
97
+ assert f2 != f3
98
+ end
99
+
100
+ should 'cache methods remotely' do
101
+ a = Foo.new
102
+ b1 = a.baz(1)
103
+ b2 = a.baz(2)
104
+
105
+ assert_equal 1, b1
106
+ assert_equal 3, b2
107
+
108
+ assert b1 == a.baz(1)
109
+ assert b1 != b2
110
+ assert b2 == a.baz(2)
111
+ end
112
+
113
+ should 'cache class methods' do
114
+ assert_equal 10, Foo.bap(10)
115
+ assert_equal 23, Foo.bap(13)
116
+ assert_equal 10, Foo.bap(10)
117
+ assert_equal 23, Foo.bap(13)
118
+ end
119
+
120
+ should 'cache methods for mixins' do
121
+ a = Baz.new
122
+
123
+ assert_equal 1, a.foo(1)
124
+ assert_equal 1, a.foo(1)
125
+ assert_equal 3, a.foo(2)
126
+ assert_equal 3, a.foo(2)
127
+ end
128
+
129
+ should 'cache class methods for mixins' do
130
+ assert_equal 1, Baz.foo(1)
131
+ assert_equal 1, Baz.foo(1)
132
+ assert_equal 3, Baz.foo(2)
133
+ assert_equal 3, Baz.foo(2)
134
+ end
135
+
136
+ should 'invalidate cached method' do
137
+ a = Foo.new
138
+
139
+ assert_equal 1, a.foo(1)
140
+ assert_equal 3, a.foo(2)
141
+
142
+ a.invalidate_cached_method(:foo, 1)
143
+
144
+ assert_equal 4, a.foo(1)
145
+ assert_equal 3, a.foo(2)
146
+ end
147
+
148
+ should 'cache counters' do
149
+ b = Baz.new
150
+
151
+ assert_equal 100, b.foo_count(:bar)
152
+ b.increment_foo_count(:bar, :by => 42)
153
+ assert_equal 142, b.foo_count(:bar)
154
+ b.decrement_foo_count(:bar, :by => 99)
155
+ assert_equal 43, b.foo_count(:bar)
156
+ b.increment_foo_count(:bar)
157
+ assert_equal 44, b.foo_count(:bar)
158
+
159
+ assert_equal 100, b.foo_count(:baz)
160
+ b.increment_foo_count(:baz)
161
+ assert_equal 101, b.foo_count(:baz)
162
+ assert_equal 44, b.foo_count(:bar) # make sure :bar wasn't affected
163
+
164
+ assert_equal 0, Foo.zap
165
+ Foo.increment_zap(:by => 3)
166
+ assert_equal 3, Foo.zap
167
+ Foo.decrement_zap
168
+ assert_equal 2, Foo.zap
169
+ end
170
+
171
+ should 'use consistent local keys' do
172
+ a = Foo.new
173
+ o = Object.new
174
+ a_hash = a.hash
175
+ o_hash = o.hash
176
+
177
+ 5.times do
178
+ key = a.send(:cached_method, :bar, [{'a' => 3, 'b' => [5,6], 'c' => o}, [1,nil,{:o => o}]]).key
179
+ assert_equal "m|:bar|Foo-#{a_hash}|{'a'=3,'b'=[5,6],'c'=Object-#{o_hash}}|[1,nil,{:o=Object-#{o_hash}}]", key
180
+ end
181
+ end
182
+
183
+ should 'use consistent remote keys' do
184
+ a = Foo.new
185
+ o = Object.new
186
+ a_hash = Marshal.dump(a).hash
187
+ o_hash = Marshal.dump(o).hash
188
+
189
+ 5.times do
190
+ key = a.send(:cached_method, :baz, [{:a => 3, :b => [5,6], :c => o}, [false,true,{:o => o}]]).key
191
+ assert_equal "m|:baz|Foo-#{a_hash}|{:a=3,:b=[5,6],:c=Object-#{o_hash}}|[false,true,{:o=Object-#{o_hash}}]", key
192
+ end
193
+ end
194
+
195
+ should 'cache nil locally' do
196
+ a = Foo.new
197
+ a.zang
198
+ a.zang
199
+ assert_equal 2, a.z
200
+ end
201
+ end
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+ require 'mocha'
5
+ require 'pp'
6
+
7
+ $LOAD_PATH.unshift File.dirname(__FILE__) + "/../lib"
8
+ $LOAD_PATH.unshift File.dirname(__FILE__) + "/../../memcache/lib"
9
+ $LOAD_PATH.unshift File.dirname(__FILE__) + "/../../cache_version/lib"
10
+ require 'method_cache'
11
+
12
+ class Test::Unit::TestCase
13
+ def start_memcache(port)
14
+ system("memcached -p #{port} -U 0 -d -P /tmp/memcached_#{port}.pid")
15
+ sleep 1
16
+ File.read("/tmp/memcached_#{port}.pid")
17
+ end
18
+ end
metadata ADDED
@@ -0,0 +1,55 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jashmenn-method_cache
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.7.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Justin Balthrop
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-02-17 00:00:00.000000000Z
13
+ dependencies: []
14
+ description: Simple memcache-based memoization library for Ruby
15
+ email: code@justinbalthrop.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files:
19
+ - LICENSE
20
+ - README.rdoc
21
+ files:
22
+ - LICENSE
23
+ - README.rdoc
24
+ - Rakefile
25
+ - VERSION.yml
26
+ - lib/method_cache.rb
27
+ - lib/method_cache/proxy.rb
28
+ - test/method_cache_remote_test.rb
29
+ - test/method_cache_test.rb
30
+ - test/test_helper.rb
31
+ homepage: http://github.com/ninjudd/method_cache
32
+ licenses: []
33
+ post_install_message:
34
+ rdoc_options: []
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ! '>='
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ! '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ requirements: []
50
+ rubyforge_project:
51
+ rubygems_version: 1.8.6
52
+ signing_key:
53
+ specification_version: 3
54
+ summary: Simple memcache-based memoization library for Ruby
55
+ test_files: []