benschwarz-merb-cache 1.0.0
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/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
|