benny_cache 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 +19 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +281 -0
- data/Rakefile +15 -0
- data/benny_cache.gemspec +23 -0
- data/lib/benny_cache.rb +7 -0
- data/lib/benny_cache/base.rb +36 -0
- data/lib/benny_cache/cache.rb +44 -0
- data/lib/benny_cache/config.rb +21 -0
- data/lib/benny_cache/model.rb +264 -0
- data/lib/benny_cache/related.rb +58 -0
- data/lib/benny_cache/version.rb +3 -0
- data/spec/models/cache_spec.rb +59 -0
- data/spec/models/config_spec.rb +15 -0
- data/spec/models/model_method_cache_spec.rb +85 -0
- data/spec/models/model_spec.rb +116 -0
- data/spec/models/related_spec.rb +63 -0
- data/spec/spec_helper.rb +38 -0
- data/spec/test_classes.rb +73 -0
- metadata +137 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
module BennyCache
|
2
|
+
class Config
|
3
|
+
@@_store = nil
|
4
|
+
|
5
|
+
def self.store
|
6
|
+
return @@_store if @@_store
|
7
|
+
|
8
|
+
if const_defined?('Rails') && Rails.cache
|
9
|
+
@@_store = Rails.cache
|
10
|
+
else
|
11
|
+
@@_store = BennyCache::Cache.new
|
12
|
+
end
|
13
|
+
|
14
|
+
@@_store
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.store=(store)
|
18
|
+
@@_store = store
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,264 @@
|
|
1
|
+
require 'digest/sha1'
|
2
|
+
|
3
|
+
module BennyCache
|
4
|
+
module Model
|
5
|
+
|
6
|
+
def self.included(base)
|
7
|
+
base.instance_eval {
|
8
|
+
include BennyCache::Base
|
9
|
+
}
|
10
|
+
|
11
|
+
base.extend BennyCache::Model::ClassMethods
|
12
|
+
|
13
|
+
unless base.class_variable_defined? :@@BENNY_MODEL_INDEXES
|
14
|
+
base.class_variable_set(:@@BENNY_MODEL_INDEXES, [])
|
15
|
+
end
|
16
|
+
|
17
|
+
unless base.class_variable_defined? :@@BENNY_DATA_INDEXES
|
18
|
+
base.class_variable_set(:@@BENNY_DATA_INDEXES, [])
|
19
|
+
end
|
20
|
+
|
21
|
+
unless base.class_variable_defined? :@@BENNY_METHOD_INDEXES
|
22
|
+
base.class_variable_set(:@@BENNY_METHOD_INDEXES, [])
|
23
|
+
end
|
24
|
+
|
25
|
+
if base.respond_to? :after_save
|
26
|
+
base.after_save :benny_model_cache_delete
|
27
|
+
end
|
28
|
+
|
29
|
+
if base.respond_to? :after_destroy
|
30
|
+
base.after_destroy :benny_model_cache_delete
|
31
|
+
end
|
32
|
+
|
33
|
+
def benny_model_cache_delete
|
34
|
+
ns = self.class.get_benny_model_ns
|
35
|
+
key = "#{ns}/#{self.id}"
|
36
|
+
|
37
|
+
BennyCache::Config.store.delete(key)
|
38
|
+
self.class.class_variable_get(:@@BENNY_MODEL_INDEXES).each do |idx|
|
39
|
+
|
40
|
+
if idx.is_a?(Symbol)
|
41
|
+
key = "#{ns}/#{idx}/" + idx.to_s.gsub(/(\w+)/) { self.send($1) }
|
42
|
+
elsif idx.is_a?(String)
|
43
|
+
key = "#{ns}/" + idx.to_s.gsub(/:(\w+)/) { "#{self.send($1) }" }
|
44
|
+
end
|
45
|
+
|
46
|
+
BennyCache::Config.store.delete(key)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def benny_data_cache(data_index, &block)
|
51
|
+
full_index = self.class.benny_data_cache_full_index(self.id, data_index)
|
52
|
+
BennyCache::Config.store.fetch(full_index, &block)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
module ClassMethods
|
57
|
+
|
58
|
+
##
|
59
|
+
# Clear the a data cache from a given model
|
60
|
+
def benny_data_cache_delete(model_id, data_index)
|
61
|
+
full_index = self.benny_data_cache_full_index(model_id, data_index)
|
62
|
+
BennyCache::Config.store.delete(full_index)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Clear the a method cache from a given model
|
66
|
+
def benny_method_cache_delete(model_id, data_index)
|
67
|
+
full_index = self.benny_method_cache_full_index(model_id, data_index)
|
68
|
+
|
69
|
+
keys = BennyCache::Config.store.fetch(full_index)
|
70
|
+
|
71
|
+
unless (keys.nil? || keys.empty?)
|
72
|
+
keys.each do |key|
|
73
|
+
BennyCache::Config.store.delete(key)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
BennyCache::Config.store.delete(full_index)
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
def benny_data_cache_full_index(model_id, data_index) # :nodoc:
|
81
|
+
raise "undefined cache data key '#{data_index}'" unless self.class_variable_get(:@@BENNY_DATA_INDEXES).include?(data_index.to_s)
|
82
|
+
ns = self.get_benny_model_ns
|
83
|
+
full_index = "#{ns}/#{model_id}/data/#{data_index.to_s}"
|
84
|
+
end
|
85
|
+
|
86
|
+
def benny_method_cache_full_index(model_id, method_index) # :nodoc:
|
87
|
+
raise "undefined cache method key '#{method_index}'" unless self.class_variable_get(:@@BENNY_METHOD_INDEXES).include?(method_index.to_s)
|
88
|
+
ns = self.get_benny_model_ns
|
89
|
+
full_index = "#{ns}/#{model_id}/method/#{method_index.to_s}"
|
90
|
+
end
|
91
|
+
|
92
|
+
# For each benny cached method, we store an array cached results. Each result
|
93
|
+
# is unique to the parameters used during the method call.
|
94
|
+
# Meaning: foo.bar(:baz) and foo.bar(:bin) are stored as two separate
|
95
|
+
# results, with their own key in the benny cache. Additionally,
|
96
|
+
# these various keys associated with foo.bar are stored as an
|
97
|
+
# separate array in their own cache entry.
|
98
|
+
# When it's time to clear the all the foo.bar cached results, we will
|
99
|
+
# have an array of keys to reference.
|
100
|
+
def benny_method_store_method_args_index(base_method_index, args_method_index)
|
101
|
+
method_sig_ary = BennyCache::Config.store.fetch(base_method_index) { [] }
|
102
|
+
unless method_sig_ary.include?(args_method_index)
|
103
|
+
method_sig_ary.push(args_method_index)
|
104
|
+
BennyCache::Config.store.write(base_method_index, method_sig_ary)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def benny_method_store_method_args_indexes_delete(model_id, method_name)
|
109
|
+
base_method_index = self.benny_method_cache_full_index(model_id, method_name)
|
110
|
+
|
111
|
+
method_sig_ary = BennyCache::Config.store.fetch(base_method_index) { [] }
|
112
|
+
method_sig_ary.each do |args_method_index|
|
113
|
+
BennyCache::Config.store.clear(args_method_index)
|
114
|
+
end
|
115
|
+
BennyCache::Config.store.clear(base_method_index)
|
116
|
+
end
|
117
|
+
|
118
|
+
##
|
119
|
+
# Declares one or more caching indexes for instances of this class.
|
120
|
+
# You do not have to declare an :id index, but if you will be referencing or loading
|
121
|
+
# models by other indexes, declare them here.
|
122
|
+
#
|
123
|
+
# Explicit declarations are needed so BennyCache knows which cache keys to clear
|
124
|
+
# on a relevant change.
|
125
|
+
#
|
126
|
+
# Valid options are symbols of other methods, or for multiple-field indexes, an array
|
127
|
+
# of :symbols
|
128
|
+
# class Agent
|
129
|
+
# benny_model_index :user_id
|
130
|
+
# # internally works like Agent.where(:user_id => user_id ).first when referenced
|
131
|
+
# end
|
132
|
+
#
|
133
|
+
# or
|
134
|
+
#
|
135
|
+
# class Location
|
136
|
+
# benny_model_index [:x, :y]
|
137
|
+
# # internally works like Locaion.where(:x => x, :y => y ).first when referenced
|
138
|
+
# end
|
139
|
+
#
|
140
|
+
# You can include many indexes in the declaration:
|
141
|
+
#
|
142
|
+
# class Foo
|
143
|
+
# benny_model_index :bar, :baz, [:zip, :zap]
|
144
|
+
# end
|
145
|
+
|
146
|
+
def benny_model_index(*options)
|
147
|
+
index_keys = options.map do |idx|
|
148
|
+
if idx.is_a?(Array)
|
149
|
+
idx.map{ |jdx| "#{jdx.to_s}/:#{jdx.to_s}"}.join("/")
|
150
|
+
else
|
151
|
+
"#{idx.to_s}/:#{idx.to_s}"
|
152
|
+
end
|
153
|
+
end
|
154
|
+
self.class_variable_get(:@@BENNY_MODEL_INDEXES).push(*index_keys)
|
155
|
+
end
|
156
|
+
|
157
|
+
def benny_data_index(*options)
|
158
|
+
self.class_variable_get(:@@BENNY_DATA_INDEXES).push(*(options.map(&:to_s)))
|
159
|
+
end
|
160
|
+
|
161
|
+
def benny_method_args_sig(*options)
|
162
|
+
sig = ''
|
163
|
+
options.each { |arg|
|
164
|
+
if arg.respond_to?(:id)
|
165
|
+
sig += "#{arg.class}/##{arg.id}"
|
166
|
+
elsif arg.is_a?(Array)
|
167
|
+
arg.each do |val|
|
168
|
+
sig += benny_method_args_sig(*val)
|
169
|
+
end
|
170
|
+
elsif arg.is_a?(Hash)
|
171
|
+
arg.keys.sort.each do |key|
|
172
|
+
sig += benny_method_args_sig(key) + benny_method_args_sig(*(arg[key]))
|
173
|
+
end
|
174
|
+
else
|
175
|
+
sig += Digest::SHA1.hexdigest(Marshal.dump(arg))
|
176
|
+
end
|
177
|
+
}
|
178
|
+
sig
|
179
|
+
end
|
180
|
+
|
181
|
+
def benny_method_index(*options)
|
182
|
+
self.class_variable_get(:@@BENNY_METHOD_INDEXES).push(*(options.map(&:to_s)))
|
183
|
+
|
184
|
+
options.each do |method_name|
|
185
|
+
|
186
|
+
define_method "#{method_name}_with_benny_cache" do |*method_opts|
|
187
|
+
@_benny_method_local_cache ||= {}
|
188
|
+
#puts "benny cache method: #{method_name}_with_benny_cache #{method_opts.inspect}"
|
189
|
+
|
190
|
+
model_id = self.id
|
191
|
+
base_method_index = self.class.benny_method_cache_full_index(model_id, method_name)
|
192
|
+
|
193
|
+
sig = self.class.benny_method_args_sig(*method_opts)
|
194
|
+
|
195
|
+
args_method_index = "#{base_method_index}/args/#{sig}"
|
196
|
+
|
197
|
+
self.class.benny_method_store_method_args_index(base_method_index, args_method_index)
|
198
|
+
|
199
|
+
return @_benny_method_local_cache[args_method_index] if @_benny_method_local_cache[args_method_index]
|
200
|
+
|
201
|
+
return_data = BennyCache::Config.store.fetch(args_method_index) {
|
202
|
+
self.send("#{method_name}_without_benny_cache", *method_opts)
|
203
|
+
}
|
204
|
+
|
205
|
+
@_benny_method_local_cache[args_method_index] = return_data
|
206
|
+
return_data
|
207
|
+
|
208
|
+
end
|
209
|
+
alias_method "#{method_name}_without_benny_cache", method_name
|
210
|
+
alias_method method_name, "#{method_name}_with_benny_cache"
|
211
|
+
alias_method "#{method_name}!", "#{method_name}_without_benny_cache"
|
212
|
+
|
213
|
+
end
|
214
|
+
|
215
|
+
end
|
216
|
+
|
217
|
+
##
|
218
|
+
# Retrieves a model from the cache. If the model is no in the cache, BennyCache will load it from the database
|
219
|
+
# and store in the cache.
|
220
|
+
#
|
221
|
+
# agent = Agent.benny_model_cache(1)
|
222
|
+
#
|
223
|
+
# If the agent with id of 1 is not in the cache, it will make an ActiveRecord call to popuplate the cache,
|
224
|
+
# and return the model, like so:
|
225
|
+
# Agent.find(1)
|
226
|
+
#
|
227
|
+
# If you have declared separate data indexes, you can pass a hash and and BennyCache will use
|
228
|
+
# ActiveRelation#where to populate the hash
|
229
|
+
#
|
230
|
+
# Agent.benny_model_cache(:user_id => 999)
|
231
|
+
#
|
232
|
+
# To populate cache, BennyCache will call
|
233
|
+
#
|
234
|
+
# Agent.where(:user_id => 999)
|
235
|
+
#
|
236
|
+
def benny_model_cache(options)
|
237
|
+
ns = self.get_benny_model_ns
|
238
|
+
|
239
|
+
if options.is_a?(Hash)
|
240
|
+
key_format = []
|
241
|
+
key = []
|
242
|
+
options.keys.sort.each do |k|
|
243
|
+
key_format << "#{k.to_s}/:#{k.to_s}"
|
244
|
+
key << "#{k.to_s}/#{options[k].to_s}"
|
245
|
+
end
|
246
|
+
|
247
|
+
key = key.join('/')
|
248
|
+
|
249
|
+
key_format = key_format.join('/')
|
250
|
+
|
251
|
+
raise "undefined cache key format #{ns}/#{key_format}" unless self.class_variable_get(:@@BENNY_MODEL_INDEXES).include?(key_format)
|
252
|
+
|
253
|
+
BennyCache::Config.store.fetch("#{ns}/#{key}") {
|
254
|
+
self.where(options).first
|
255
|
+
}
|
256
|
+
else # should be a number/id
|
257
|
+
BennyCache::Config.store.fetch("#{ns}/#{options}") {
|
258
|
+
self.find(options)
|
259
|
+
}
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module BennyCache
|
2
|
+
module Related
|
3
|
+
def self.included(base) #:nodoc:
|
4
|
+
base.send :include, BennyCache::Base
|
5
|
+
|
6
|
+
base.extend BennyCache::ClassMethods
|
7
|
+
unless(base.class_variable_defined? :@@benny_related_indexes)
|
8
|
+
base.class_variable_set(:@@benny_related_indexes, [])
|
9
|
+
end
|
10
|
+
|
11
|
+
unless(base.class_variable_defined? :@@benny_related_methods)
|
12
|
+
base.class_variable_set(:@@benny_related_methods, [])
|
13
|
+
end
|
14
|
+
|
15
|
+
if base.respond_to?(:after_save)
|
16
|
+
base.after_save :benny_cache_clear_related
|
17
|
+
end
|
18
|
+
|
19
|
+
if base.respond_to?(:after_destroy)
|
20
|
+
base.after_destroy :benny_cache_clear_related
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def benny_cache_clear_related
|
25
|
+
self.class.class_variable_get(:@@benny_related_indexes).each do |key|
|
26
|
+
local_field, klass, data_cache = key.split('/')
|
27
|
+
local_field = local_field[1, local_field.length]
|
28
|
+
const = benny_constantize(klass)
|
29
|
+
id = self.send(local_field)
|
30
|
+
const.benny_data_cache_delete(id, data_cache) if id
|
31
|
+
end
|
32
|
+
|
33
|
+
self.class.class_variable_get(:@@benny_related_methods).each do |key|
|
34
|
+
local_field, klass, method_cache = key.split('/')
|
35
|
+
local_field = local_field[1, local_field.length]
|
36
|
+
const = benny_constantize(klass)
|
37
|
+
id = self.send(local_field)
|
38
|
+
const.benny_method_cache_delete(id, method_cache) if id
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
module ClassMethods
|
45
|
+
|
46
|
+
def benny_related_index(*options)
|
47
|
+
index_keys = options.map {|idx| idx.is_a?(Array) ? idx.map{ |jdx| "#{jdx.to_s}/:#{jdx.to_s}"}.join("/") : idx }
|
48
|
+
self.class_variable_get(:@@benny_related_indexes).push(*index_keys)
|
49
|
+
end
|
50
|
+
|
51
|
+
def benny_related_method(*options)
|
52
|
+
index_keys = options.map {|idx| idx.is_a?(Array) ? idx.map{ |jdx| "#{jdx.to_s}/:#{jdx.to_s}"}.join("/") : idx }
|
53
|
+
self.class_variable_get(:@@benny_related_methods).push(*index_keys)
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require_relative "../spec_helper"
|
2
|
+
describe BennyCache::Cache do
|
3
|
+
it "is a class" do
|
4
|
+
BennyCache::Cache
|
5
|
+
end
|
6
|
+
|
7
|
+
it "can be instantiated" do
|
8
|
+
c = BennyCache::Cache.new
|
9
|
+
c.should be_true
|
10
|
+
end
|
11
|
+
|
12
|
+
describe do
|
13
|
+
before(:each) do
|
14
|
+
@c = BennyCache::Cache.new
|
15
|
+
@key = "foo"
|
16
|
+
@val = "bar"
|
17
|
+
end
|
18
|
+
|
19
|
+
methods = %w(fetch read write delete)
|
20
|
+
methods.each do |m|
|
21
|
+
it "should respond to #{m}" do
|
22
|
+
@c.respond_to?(m).should be_true
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should write and read keyed data" do
|
27
|
+
@c.write(@key, @val)
|
28
|
+
@c.read(@key).should == @val
|
29
|
+
end
|
30
|
+
|
31
|
+
it "can delete keys" do
|
32
|
+
@c.write(@key, @val)
|
33
|
+
@c.read(@key).should == @val
|
34
|
+
@c.delete(@key)
|
35
|
+
@c.read(@key).should be_nil
|
36
|
+
end
|
37
|
+
|
38
|
+
it "#fetch can set a nil val with a block" do
|
39
|
+
@c.read(@key).should be_nil
|
40
|
+
set_val = @c.fetch(@key) {
|
41
|
+
@val
|
42
|
+
}
|
43
|
+
set_val.should == @val
|
44
|
+
@c.read(@key).should == @val
|
45
|
+
end
|
46
|
+
|
47
|
+
it "#clear should remove all cached data" do
|
48
|
+
key2 = "baz"
|
49
|
+
val2 = "bin"
|
50
|
+
@c.write(@key, @val)
|
51
|
+
@c.write(key2, val2)
|
52
|
+
@c.read(@key).should == @val
|
53
|
+
@c.read(key2).should == val2
|
54
|
+
@c.clear
|
55
|
+
@c.read(@key).should be_nil
|
56
|
+
@c.read(key2).should be_nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require_relative "../spec_helper"
|
2
|
+
|
3
|
+
require 'mocha_standalone'
|
4
|
+
|
5
|
+
describe BennyCache::Config do
|
6
|
+
it "should exist" do
|
7
|
+
BennyCache::Config.should be_true
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should default to a BennyCache::Cache" do
|
11
|
+
BennyCache::Config.store = nil
|
12
|
+
BennyCache::Config.store.class.should == BennyCache::Cache
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require_relative "../spec_helper"
|
2
|
+
|
3
|
+
require 'mocha_standalone'
|
4
|
+
|
5
|
+
describe BennyCache::Model do
|
6
|
+
|
7
|
+
|
8
|
+
describe "method caching" do
|
9
|
+
before(:each) do
|
10
|
+
@model = ModelCacheFake.new
|
11
|
+
@model.id = 1
|
12
|
+
@model.other_id = 123
|
13
|
+
@model.x = 12
|
14
|
+
@model.y = 36
|
15
|
+
@store = BennyCache::Cache.new
|
16
|
+
BennyCache::Config.store=@store
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should call the original once method if uncached" do
|
20
|
+
@model.expects(:method_to_cache_without_benny_cache).with(:foo).returns(:stuff) # only once!
|
21
|
+
@model.expects(:method_to_cache_without_benny_cache).with(:bar).returns(:other_stuff)
|
22
|
+
|
23
|
+
rv = @model.method_to_cache :foo
|
24
|
+
rv.should == :stuff
|
25
|
+
rv = @model.method_to_cache :foo # should hit cache
|
26
|
+
rv.should == :stuff
|
27
|
+
rv = @model.method_to_cache :bar
|
28
|
+
rv.should == :other_stuff
|
29
|
+
|
30
|
+
model_base_index = "Benny/ModelCacheFake/1/method/method_to_cache"
|
31
|
+
rv = BennyCache::Config.store.read(model_base_index)
|
32
|
+
rv.class.should == Array
|
33
|
+
rv.size.should == 2
|
34
|
+
|
35
|
+
rv[0].should =~ /Benny\/ModelCacheFake\/1\/method\/method_to_cache\/args\/\w+$/
|
36
|
+
rv[1].should =~ /Benny\/ModelCacheFake\/1\/method\/method_to_cache\/args\/\w+$/
|
37
|
+
|
38
|
+
rv[0].should_not == rv[1]
|
39
|
+
|
40
|
+
puts rv.inspect
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should method cache result data structures locally" do
|
44
|
+
data = @model.method_to_cache_with_base_data
|
45
|
+
data.should == [:a, :b, :c]
|
46
|
+
data.push :d
|
47
|
+
|
48
|
+
@model.method_to_cache_with_base_data.should == [:a, :b, :c, :d]
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
it "should be able to delete the cached method data" do
|
54
|
+
@model.expects(:method_to_cache_without_benny_cache).with(:foo).returns(:stuff) # only once!
|
55
|
+
|
56
|
+
rv = @model.method_to_cache :foo
|
57
|
+
rv.should == :stuff
|
58
|
+
rv = @model.method_to_cache :foo # should hit cache
|
59
|
+
rv.should == :stuff
|
60
|
+
model_base_index = "Benny/ModelCacheFake/1/method/method_to_cache"
|
61
|
+
rv = BennyCache::Config.store.read(model_base_index)
|
62
|
+
rv.size.should == 1
|
63
|
+
|
64
|
+
ModelCacheFake.benny_method_store_method_args_indexes_delete(@model.id, :method_to_cache)
|
65
|
+
|
66
|
+
model_base_index = "Benny/ModelCacheFake/1/method/method_to_cache"
|
67
|
+
rv = BennyCache::Config.store.read(model_base_index)
|
68
|
+
rv.should be_nil
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should use the same cache index for reorder hash params" do
|
72
|
+
@model.expects(:method_to_cache_without_benny_cache).returns(:stuff) # only once!
|
73
|
+
|
74
|
+
rv = @model.method_to_cache :foo => :bar, :baz => :bin
|
75
|
+
rv.should == :stuff
|
76
|
+
rv = @model.method_to_cache :baz => :bin, :foo => :bar # should use same key
|
77
|
+
rv.should == :stuff
|
78
|
+
model_base_index = "Benny/ModelCacheFake/1/method/method_to_cache"
|
79
|
+
rv = BennyCache::Config.store.read(model_base_index)
|
80
|
+
rv.size.should == 1
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|