benschwarz-merb-cache 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README +224 -0
- data/Rakefile +17 -0
- data/lib/merb-cache.rb +15 -0
- data/lib/merb-cache/cache.rb +91 -0
- data/lib/merb-cache/cache_request.rb +48 -0
- data/lib/merb-cache/core_ext/enumerable.rb +9 -0
- data/lib/merb-cache/core_ext/hash.rb +21 -0
- data/lib/merb-cache/merb_ext/controller/class_methods.rb +244 -0
- data/lib/merb-cache/merb_ext/controller/instance_methods.rb +163 -0
- data/lib/merb-cache/stores/fundamental/abstract_store.rb +101 -0
- data/lib/merb-cache/stores/fundamental/file_store.rb +113 -0
- data/lib/merb-cache/stores/fundamental/memcached_store.rb +110 -0
- data/lib/merb-cache/stores/strategy/abstract_strategy_store.rb +119 -0
- data/lib/merb-cache/stores/strategy/action_store.rb +61 -0
- data/lib/merb-cache/stores/strategy/adhoc_store.rb +69 -0
- data/lib/merb-cache/stores/strategy/gzip_store.rb +63 -0
- data/lib/merb-cache/stores/strategy/mintcache_store.rb +75 -0
- data/lib/merb-cache/stores/strategy/page_store.rb +68 -0
- data/lib/merb-cache/stores/strategy/sha1_store.rb +62 -0
- data/spec/merb-cache/cache_request_spec.rb +78 -0
- data/spec/merb-cache/cache_spec.rb +88 -0
- data/spec/merb-cache/core_ext/enumerable_spec.rb +26 -0
- data/spec/merb-cache/core_ext/hash_spec.rb +51 -0
- data/spec/merb-cache/merb_ext/controller_spec.rb +5 -0
- data/spec/merb-cache/stores/fundamental/abstract_store_spec.rb +118 -0
- data/spec/merb-cache/stores/fundamental/file_store_spec.rb +205 -0
- data/spec/merb-cache/stores/fundamental/memcached_store_spec.rb +258 -0
- data/spec/merb-cache/stores/strategy/abstract_strategy_store_spec.rb +78 -0
- data/spec/merb-cache/stores/strategy/action_store_spec.rb +208 -0
- data/spec/merb-cache/stores/strategy/adhoc_store_spec.rb +227 -0
- data/spec/merb-cache/stores/strategy/gzip_store_spec.rb +68 -0
- data/spec/merb-cache/stores/strategy/mintcache_store_spec.rb +59 -0
- data/spec/merb-cache/stores/strategy/page_store_spec.rb +146 -0
- data/spec/merb-cache/stores/strategy/sha1_store_spec.rb +84 -0
- data/spec/spec_helper.rb +95 -0
- metadata +112 -0
@@ -0,0 +1,78 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../../spec_helper'
|
2
|
+
require File.dirname(__FILE__) + '/../fundamental/abstract_store_spec'
|
3
|
+
|
4
|
+
|
5
|
+
describe Merb::Cache::AbstractStrategyStore do
|
6
|
+
describe 'all strategy stores', :shared => true do
|
7
|
+
it_should_behave_like 'all stores'
|
8
|
+
|
9
|
+
before(:each) do
|
10
|
+
Merb::Cache.stores.clear
|
11
|
+
Thread.current[:'merb-cache'] = nil
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "contextualizing method", :shared => true do
|
15
|
+
it "should return a subclass of itself" do
|
16
|
+
subclass = @klass.[](Class.new(Merb::Cache::AbstractStore))
|
17
|
+
subclass.superclass.should == @klass
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should set the contextualized_stores attributes" do
|
21
|
+
subclass = @klass.[](context_class = Class.new(Merb::Cache::AbstractStore))
|
22
|
+
subclass.contextualized_stores.first.should == context_class
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe ".contextualize" do
|
27
|
+
it_should_behave_like "contextualizing method"
|
28
|
+
end
|
29
|
+
|
30
|
+
describe ".[]" do
|
31
|
+
it_should_behave_like "contextualizing method"
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#initialize" do
|
35
|
+
it "should create an instance of the any context classes" do
|
36
|
+
subclass = @klass.[](context_class = Class.new(Merb::Cache::AbstractStore))
|
37
|
+
instance = subclass.new({})
|
38
|
+
instance.stores.first.class.superclass.should == Merb::Cache::AbstractStore
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should lookup the instance of any context names" do
|
42
|
+
Merb::Cache.register(:foo, Class.new(Merb::Cache::AbstractStore))
|
43
|
+
subclass = @klass.[](:foo)
|
44
|
+
Merb::Cache.should_receive(:[]).with(:foo)
|
45
|
+
subclass.new({})
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "#clone" do
|
50
|
+
it "should clone each context instance" do
|
51
|
+
subclass = @klass.[](context_class = Class.new(Merb::Cache::AbstractStore))
|
52
|
+
instance = mock(:instance)
|
53
|
+
context_class.should_receive(:new).and_return(instance)
|
54
|
+
instance.should_receive(:clone)
|
55
|
+
|
56
|
+
subclass.new.clone
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "#write_all" do
|
61
|
+
it "should not raise a NotImplementedError error" do
|
62
|
+
lambda { @store.write_all('foo', 'bar') }.should_not raise_error(NotImplementedError)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should accept a string key" do
|
66
|
+
@store.write_all('foo', 'bar')
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should accept a symbol as a key" do
|
70
|
+
@store.write_all(:foo, :bar)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should accept parameters and conditions" do
|
74
|
+
@store.write_all('foo', 'bar', {:params => :hash}, :conditions => :hash)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,208 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../../spec_helper'
|
2
|
+
require File.dirname(__FILE__) + '/abstract_strategy_store_spec'
|
3
|
+
|
4
|
+
describe Merb::Cache::ActionStore do
|
5
|
+
it_should_behave_like 'all strategy stores'
|
6
|
+
|
7
|
+
# this could be cleaned up a bit
|
8
|
+
before(:each) do
|
9
|
+
Merb::Cache.stores.clear
|
10
|
+
Thread.current[:'merb-cache'] = nil
|
11
|
+
|
12
|
+
@klass = Merb::Cache::ActionStore[:dummy]
|
13
|
+
Merb::Cache.register(:dummy, DummyStore)
|
14
|
+
Merb::Cache.register(:default, @klass)
|
15
|
+
|
16
|
+
@store = Merb::Cache[:default]
|
17
|
+
@dummy = @store.stores.first
|
18
|
+
|
19
|
+
class TestController < Merb::Controller; def action; end; end
|
20
|
+
@controller = TestController.new(fake_request)
|
21
|
+
@controller.stub!(:action_name).and_return :action
|
22
|
+
@controller.stub!(:body).and_return 'body'
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#writable?" do
|
26
|
+
it "should be false if the key argument is not an instance of a controller" do
|
27
|
+
@store.writable?(:foo).should be_false
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should be false if the fundamental store cannot write the normalized key" do
|
31
|
+
@store.stores.first.should_receive(:writable?).and_return false
|
32
|
+
|
33
|
+
@store.writable?(@controller).should be_false
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should be true if the key is a controller instance and the fundamental store is writable" do
|
37
|
+
@store.writable?(@controller).should be_true
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "#read" do
|
42
|
+
it "should pass the normalized dispatch as the key to the context cache" do
|
43
|
+
@dummy.should_receive(:read).with("TestController#action", {})
|
44
|
+
|
45
|
+
@store.read(@controller)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "#write" do
|
50
|
+
it "should pass the normalized dispatch as the key to the fundamental store" do
|
51
|
+
@dummy.should_receive(:write).with("TestController#action", @controller.body, {}, {})
|
52
|
+
|
53
|
+
@store.write(@controller)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should not store to the context cache if the dispatch is not storable" do
|
57
|
+
@dummy.should_not_receive(:write)
|
58
|
+
|
59
|
+
@store.write(:foo).should be_false
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should use the controller instance's body as the data" do
|
63
|
+
@controller.should_receive(:body)
|
64
|
+
|
65
|
+
@store.write(@controller)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should write" do
|
69
|
+
@store.write(@controller).should be_true
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "#write_all" do
|
74
|
+
it "should pass the normalized dispatch as the key to the fundamental store" do
|
75
|
+
@dummy.should_receive(:write_all).with("TestController#action", @controller.body, {}, {})
|
76
|
+
|
77
|
+
@store.write_all(@controller)
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should not store to the context cache if the dispatch is not storable" do
|
81
|
+
@dummy.should_not_receive(:write_all)
|
82
|
+
|
83
|
+
@store.write_all(:foo).should be_false
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should use the controller instance's body as the data" do
|
87
|
+
@controller.should_receive(:body)
|
88
|
+
|
89
|
+
@store.write_all(@controller)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "#exists?" do
|
94
|
+
it "should return a boolean" do
|
95
|
+
@store.write(@controller)
|
96
|
+
@store.exists?(@controller).should be_true
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe "examples" do
|
101
|
+
class MLBSchedule < Merb::Controller
|
102
|
+
cache :index
|
103
|
+
|
104
|
+
def index
|
105
|
+
"MLBSchedule index"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
class MLBScores < Merb::Controller
|
110
|
+
cache :index, :show
|
111
|
+
cache :overview
|
112
|
+
cache :short, :params => :page
|
113
|
+
cache :stats, :params => [:start_date, :end_date]
|
114
|
+
cache :ticker, :expire_in => 10
|
115
|
+
|
116
|
+
eager_cache :index, [MLBSchedule, :index]
|
117
|
+
eager_cache [:overview, :show], :index
|
118
|
+
eager_cache(:short, :params => :page) do |params, env|
|
119
|
+
{:params => params.merge(:page => (params[:page].to_i + 1).to_s)}
|
120
|
+
end
|
121
|
+
|
122
|
+
def index
|
123
|
+
"MLBScores index"
|
124
|
+
end
|
125
|
+
|
126
|
+
def show(team)
|
127
|
+
"MLBScores show(#{team})"
|
128
|
+
end
|
129
|
+
|
130
|
+
def overview(team = :all)
|
131
|
+
"MLBScores overview(#{team})"
|
132
|
+
end
|
133
|
+
|
134
|
+
def short(team = :all)
|
135
|
+
"MLBScores short(#{team})[#{params[:page]}]"
|
136
|
+
end
|
137
|
+
|
138
|
+
def stats(start_date, end_date, team = :all)
|
139
|
+
"MLBScores stats(#{team}, #{start_date}, #{end_date})"
|
140
|
+
end
|
141
|
+
|
142
|
+
def ticker
|
143
|
+
"MLBScores ticker"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should cache the index action on the first request" do
|
148
|
+
dispatch_to(MLBScores, :index)
|
149
|
+
|
150
|
+
@dummy.data("MLBScores#index").should == "MLBScores index"
|
151
|
+
end
|
152
|
+
|
153
|
+
it "should cache the show action by the team parameter using the action arguments" do
|
154
|
+
dispatch_to(MLBScores, :show, :team => :redsox)
|
155
|
+
|
156
|
+
@dummy.data("MLBScores#show", :team => 'redsox').should == "MLBScores show(redsox)"
|
157
|
+
end
|
158
|
+
|
159
|
+
it "should cache the overview action by the default parameter if none is given" do
|
160
|
+
dispatch_to(MLBScores, :overview)
|
161
|
+
|
162
|
+
@dummy.data("MLBScores#overview", :team => :all).should == "MLBScores overview(all)"
|
163
|
+
end
|
164
|
+
|
165
|
+
it "should cache the short action by the team & page parameters" do
|
166
|
+
dispatch_to(MLBScores, :short, :team => :bosux, :page => 4)
|
167
|
+
|
168
|
+
@dummy.data("MLBScores#short", :team => 'bosux', :page => '4').should == "MLBScores short(bosux)[4]"
|
169
|
+
end
|
170
|
+
|
171
|
+
it "should cache the stats action by team, start_date & end_date parameters" do
|
172
|
+
start_date, end_date = Time.today.to_s, Time.now.to_s
|
173
|
+
dispatch_to(MLBScores, :stats, :start_date => start_date, :end_date => end_date)
|
174
|
+
|
175
|
+
@dummy.data("MLBScores#stats", :team => :all, :start_date => start_date, :end_date => end_date).should == "MLBScores stats(all, #{start_date}, #{end_date})"
|
176
|
+
end
|
177
|
+
|
178
|
+
it "should cache the ticker action with an expire_in condition" do
|
179
|
+
dispatch_to(MLBScores, :ticker)
|
180
|
+
|
181
|
+
@dummy.conditions("MLBScores#ticker")[:expire_in].should == 10
|
182
|
+
end
|
183
|
+
|
184
|
+
it "should eager cache MLBSchedule#index after a request to MLBScores#index" do
|
185
|
+
dispatch_to(MLBScores, :index)
|
186
|
+
|
187
|
+
@dummy.data("MLBSchedule#index").should == "MLBSchedule index"
|
188
|
+
end
|
189
|
+
|
190
|
+
it "should eager cache :index after a request to :overview" do
|
191
|
+
dispatch_to(MLBScores, :overview)
|
192
|
+
|
193
|
+
@dummy.data("MLBScores#index").should == "MLBScores index"
|
194
|
+
end
|
195
|
+
|
196
|
+
it "should eager cache :index after a request to :show" do
|
197
|
+
dispatch_to(MLBScores, :show, :team => :redsox)
|
198
|
+
|
199
|
+
@dummy.data("MLBScores#index").should == "MLBScores index"
|
200
|
+
end
|
201
|
+
|
202
|
+
it "should eager cache the next :short page" do
|
203
|
+
dispatch_to(MLBScores, :short, :team => :bosux, :page => 4)
|
204
|
+
|
205
|
+
@dummy.data("MLBScores#short", :team => 'bosux', :page => '5').should == "MLBScores short(bosux)[5]"
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
@@ -0,0 +1,227 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../../spec_helper'
|
2
|
+
require File.dirname(__FILE__) + '/abstract_strategy_store_spec'
|
3
|
+
|
4
|
+
describe Merb::Cache::AdhocStore do
|
5
|
+
it_should_behave_like 'all stores'
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
Merb::Cache.stores.clear
|
9
|
+
Thread.current[:'merb-cache'] = nil
|
10
|
+
Merb::Cache.register(:dummy, DummyStore)
|
11
|
+
@store = Merb::Cache::AdhocStore[:dummy]
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#initialize" do
|
15
|
+
it "should lookup all store names" do
|
16
|
+
names = [:first, :second, :third]
|
17
|
+
names.each {|n| Merb::Cache.should_receive(:[]).with(n)}
|
18
|
+
|
19
|
+
Merb::Cache::AdhocStore[*names]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#writable?" do
|
24
|
+
it "should return the first non-nil result of a writeable store" do
|
25
|
+
unwritable, writable = mock(:unwritable_store), mock(:writable_store)
|
26
|
+
unwritable.should_receive(:writable?).and_return nil
|
27
|
+
writable.should_receive(:writable?).and_return true
|
28
|
+
|
29
|
+
adhoc = Merb::Cache::AdhocStore.new
|
30
|
+
adhoc.stores = [unwritable, writable]
|
31
|
+
adhoc.writable?(:foo).should be_true
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should stop calling writable after the first non-nil result" do
|
35
|
+
unwritable, writable, unused = mock(:unwritable_store), mock(:writable_store), mock(:unused_store)
|
36
|
+
unwritable.stub!(:writable?).and_return nil
|
37
|
+
writable.should_receive(:writable?).and_return true
|
38
|
+
unused.should_not_receive(:writable?)
|
39
|
+
|
40
|
+
adhoc = Merb::Cache::AdhocStore.new
|
41
|
+
adhoc.stores = [unwritable, writable, unused]
|
42
|
+
adhoc.writable?(:foo).should be_true
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should return nil if none of the stores are writable" do
|
46
|
+
unwritable = mock(:unwritable_store)
|
47
|
+
unwritable.should_receive(:writable?).exactly(3).times.and_return(nil)
|
48
|
+
|
49
|
+
adhoc = Merb::Cache::AdhocStore.new
|
50
|
+
adhoc.stores = [unwritable, unwritable, unwritable]
|
51
|
+
adhoc.writable?(:foo).should be_nil
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "#write" do
|
56
|
+
it "should write"
|
57
|
+
|
58
|
+
it "should return the first non-nil result of a writeable store" do
|
59
|
+
unwritable, writable = mock(:unwritable_store), mock(:writable_store)
|
60
|
+
unwritable.should_receive(:write).and_return nil
|
61
|
+
writable.should_receive(:write).and_return true
|
62
|
+
|
63
|
+
adhoc = Merb::Cache::AdhocStore.new
|
64
|
+
adhoc.stores = [unwritable, writable]
|
65
|
+
adhoc.write(:foo).should be_true
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should stop calling writable after the first non-nil result" do
|
69
|
+
unwritable, writable, unused = mock(:unwritable_store), mock(:writable_store), mock(:unused_store)
|
70
|
+
unwritable.stub!(:write).and_return nil
|
71
|
+
writable.should_receive(:write).and_return true
|
72
|
+
unused.should_not_receive(:write)
|
73
|
+
|
74
|
+
adhoc = Merb::Cache::AdhocStore.new
|
75
|
+
adhoc.stores = [unwritable, writable, unused]
|
76
|
+
adhoc.write(:foo).should be_true
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should return nil if none of the stores are writable" do
|
80
|
+
unwritable = mock(:unwritable_store)
|
81
|
+
unwritable.should_receive(:write).exactly(3).times.and_return(nil)
|
82
|
+
|
83
|
+
adhoc = Merb::Cache::AdhocStore.new
|
84
|
+
adhoc.stores = [unwritable, unwritable, unwritable]
|
85
|
+
adhoc.write(:foo).should be_nil
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "#write_all" do
|
90
|
+
it "should return false if a store returns nil for write_all" do
|
91
|
+
unwritable, writable = mock(:unwritable_store), mock(:writable_store)
|
92
|
+
unwritable.should_receive(:write_all).and_return nil
|
93
|
+
writable.should_receive(:write_all).and_return "bar"
|
94
|
+
|
95
|
+
adhoc = Merb::Cache::AdhocStore.new
|
96
|
+
adhoc.stores = [unwritable, writable]
|
97
|
+
adhoc.write_all(:foo).should be_false
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should always call write_all on every store" do
|
101
|
+
unwritable, writable, used = mock(:unwritable_store), mock(:writable_store), mock(:used_store)
|
102
|
+
unwritable.stub!(:write_all).and_return nil
|
103
|
+
writable.should_receive(:write_all).and_return true
|
104
|
+
used.should_receive(:write_all).and_return true
|
105
|
+
|
106
|
+
adhoc = Merb::Cache::AdhocStore.new
|
107
|
+
adhoc.stores = [unwritable, writable, used]
|
108
|
+
adhoc.write_all(:foo).should be_false
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe "#fetch" do
|
113
|
+
it "should return a call to read if it is non-nil" do
|
114
|
+
adhoc = Merb::Cache::AdhocStore.new
|
115
|
+
adhoc.should_receive(:read).and_return "bar"
|
116
|
+
adhoc.fetch(:foo).should == "bar"
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should return the first non-nil result of a fetchable store" do
|
120
|
+
unfetchable, fetchable = mock(:unfetchable_store), mock(:fetchable_store)
|
121
|
+
unfetchable.should_receive(:fetch).and_return nil
|
122
|
+
fetchable.should_receive(:fetch).and_return true
|
123
|
+
|
124
|
+
adhoc = Merb::Cache::AdhocStore.new
|
125
|
+
adhoc.stores = [unfetchable, fetchable]
|
126
|
+
adhoc.should_receive(:read).and_return nil
|
127
|
+
adhoc.fetch(:foo).should be_true
|
128
|
+
end
|
129
|
+
|
130
|
+
it "should return the value of the block if none of the stores are fetchable" do
|
131
|
+
adhoc = Merb::Cache::AdhocStore.new
|
132
|
+
adhoc.fetch(:foo) {
|
133
|
+
'foo'
|
134
|
+
|
135
|
+
}.should == 'foo'
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should stop calling fetch after the first non-nil result" do
|
139
|
+
unfetchable, fetchable, unused = mock(:unwritable_store), mock(:writable_store), mock(:unused_store)
|
140
|
+
unfetchable.stub!(:fetch).and_return nil
|
141
|
+
fetchable.should_receive(:fetch).and_return true
|
142
|
+
unused.should_not_receive(:fetch)
|
143
|
+
|
144
|
+
adhoc = Merb::Cache::AdhocStore.new
|
145
|
+
adhoc.stores = [unfetchable, fetchable, unused]
|
146
|
+
adhoc.should_receive(:read).and_return nil
|
147
|
+
adhoc.fetch(:foo).should be_true
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
describe "#exists?" do
|
152
|
+
it "should return the first non-nil result of a readable store" do
|
153
|
+
unreadable, readable = mock(:unreadable_store), mock(:readable_store)
|
154
|
+
unreadable.should_receive(:exists?).and_return nil
|
155
|
+
readable.should_receive(:exists?).and_return true
|
156
|
+
|
157
|
+
adhoc = Merb::Cache::AdhocStore.new
|
158
|
+
adhoc.stores = [unreadable, readable]
|
159
|
+
adhoc.exists?(:foo).should be_true
|
160
|
+
end
|
161
|
+
|
162
|
+
it "should stop calling readable after the first non-nil result" do
|
163
|
+
unreadable, readable, unused = mock(:unreadable_store), mock(:readable_store), mock(:unused_store)
|
164
|
+
unreadable.stub!(:exists?).and_return nil
|
165
|
+
readable.should_receive(:exists?).and_return true
|
166
|
+
unused.should_not_receive(:exists?)
|
167
|
+
|
168
|
+
adhoc = Merb::Cache::AdhocStore.new
|
169
|
+
adhoc.stores = [unreadable, readable, unused]
|
170
|
+
adhoc.exists?(:foo).should be_true
|
171
|
+
end
|
172
|
+
|
173
|
+
it "should return nil if none of the stores are readable" do
|
174
|
+
unreadable = mock(:unreadable_store)
|
175
|
+
unreadable.should_receive(:exists?).exactly(3).times.and_return(nil)
|
176
|
+
|
177
|
+
adhoc = Merb::Cache::AdhocStore.new
|
178
|
+
adhoc.stores = [unreadable, unreadable, unreadable]
|
179
|
+
adhoc.exists?(:foo).should be_false
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
describe "#delete" do
|
184
|
+
it "should return false if all stores returns nil for delete" do
|
185
|
+
undeletable = mock(:undeletable_store)
|
186
|
+
undeletable.should_receive(:delete).and_return nil
|
187
|
+
|
188
|
+
adhoc = Merb::Cache::AdhocStore.new
|
189
|
+
adhoc.stores = [undeletable]
|
190
|
+
adhoc.delete(:foo).should be_false
|
191
|
+
end
|
192
|
+
|
193
|
+
it "should always call delete on every store" do
|
194
|
+
undeletable, deletable, used = mock(:undeletable_store), mock(:deletable_store), mock(:used_store)
|
195
|
+
undeletable.stub!(:delete).and_return nil
|
196
|
+
deletable.should_receive(:delete).and_return true
|
197
|
+
used.should_receive(:delete).and_return true
|
198
|
+
|
199
|
+
adhoc = Merb::Cache::AdhocStore.new
|
200
|
+
adhoc.stores = [undeletable, deletable, used]
|
201
|
+
adhoc.delete(:foo).should be_true
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
describe "#delete_all!" do
|
206
|
+
it "should return false if a store returns nil for write_all" do
|
207
|
+
undeletable, deletable = mock(:undeletable_store), mock(:deletable_store)
|
208
|
+
undeletable.should_receive(:delete_all!).and_return nil
|
209
|
+
deletable.should_receive(:delete_all!).and_return true
|
210
|
+
|
211
|
+
adhoc = Merb::Cache::AdhocStore.new
|
212
|
+
adhoc.stores = [undeletable, deletable]
|
213
|
+
adhoc.delete_all!.should be_false
|
214
|
+
end
|
215
|
+
|
216
|
+
it "should always call write_all on every store" do
|
217
|
+
undeletable, deletable, used = mock(:undeletable_store), mock(:deletable_store), mock(:used_store)
|
218
|
+
undeletable.stub!(:delete_all!).and_return nil
|
219
|
+
deletable.should_receive(:delete_all!).and_return true
|
220
|
+
used.should_receive(:delete_all!).and_return true
|
221
|
+
|
222
|
+
adhoc = Merb::Cache::AdhocStore.new
|
223
|
+
adhoc.stores = [undeletable, deletable, used]
|
224
|
+
adhoc.delete_all!.should be_false
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|