benny_cache 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|