merb-cache 0.9.7 → 0.9.8
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +2 -2
- data/README +207 -143
- data/Rakefile +55 -10
- data/TODO +0 -2
- data/lib/merb-cache/cache.rb +84 -0
- data/lib/merb-cache/core_ext/enumerable.rb +9 -0
- data/lib/merb-cache/core_ext/hash.rb +20 -0
- data/lib/merb-cache/merb_ext/controller.rb +167 -0
- data/lib/merb-cache/stores/fundamental/abstract_store.rb +101 -0
- data/lib/merb-cache/stores/fundamental/file_store.rb +112 -0
- data/lib/merb-cache/stores/fundamental/memcached_store.rb +112 -0
- data/lib/merb-cache/stores/strategy/abstract_strategy_store.rb +123 -0
- data/lib/merb-cache/stores/strategy/action_store.rb +56 -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/page_store.rb +64 -0
- data/lib/merb-cache/stores/strategy/sha1_store.rb +62 -0
- data/lib/merb-cache.rb +8 -7
- data/spec/merb-cache/cache_spec.rb +88 -0
- data/spec/merb-cache/core_ext/enumerable_spec.rb +22 -0
- data/spec/merb-cache/core_ext/hash_spec.rb +20 -0
- data/spec/merb-cache/merb_ext/controller_spec.rb +284 -0
- data/spec/merb-cache/stores/fundamental/abstract_store_spec.rb +166 -0
- data/spec/merb-cache/stores/fundamental/file_store_spec.rb +186 -0
- data/spec/merb-cache/stores/fundamental/memcached_store_spec.rb +243 -0
- data/spec/merb-cache/stores/strategy/abstract_strategy_store_spec.rb +78 -0
- data/spec/merb-cache/stores/strategy/action_store_spec.rb +189 -0
- data/spec/merb-cache/stores/strategy/adhoc_store_spec.rb +225 -0
- data/spec/merb-cache/stores/strategy/gzip_store_spec.rb +51 -0
- data/spec/merb-cache/stores/strategy/page_store_spec.rb +111 -0
- data/spec/merb-cache/stores/strategy/sha1_store_spec.rb +75 -0
- data/spec/spec_helper.rb +69 -72
- metadata +42 -31
- data/lib/merb-cache/cache-action.rb +0 -144
- data/lib/merb-cache/cache-fragment.rb +0 -95
- data/lib/merb-cache/cache-page.rb +0 -203
- data/lib/merb-cache/cache-store/database-activerecord.rb +0 -88
- data/lib/merb-cache/cache-store/database-datamapper.rb +0 -79
- data/lib/merb-cache/cache-store/database-sequel.rb +0 -78
- data/lib/merb-cache/cache-store/database.rb +0 -144
- data/lib/merb-cache/cache-store/dummy.rb +0 -106
- data/lib/merb-cache/cache-store/file.rb +0 -194
- data/lib/merb-cache/cache-store/memcache.rb +0 -199
- data/lib/merb-cache/cache-store/memory.rb +0 -168
- data/lib/merb-cache/merb-cache.rb +0 -165
- data/lib/merb-cache/merbtasks.rb +0 -6
- data/spec/config/database.yml +0 -14
- data/spec/controller.rb +0 -101
- data/spec/log/merb_test.log +0 -433
- data/spec/merb-cache-action_spec.rb +0 -162
- data/spec/merb-cache-fragment_spec.rb +0 -100
- data/spec/merb-cache-page_spec.rb +0 -150
- data/spec/merb-cache_spec.rb +0 -15
- data/spec/views/cache_controller/action1.html.erb +0 -4
- data/spec/views/cache_controller/action2.html.haml +0 -4
@@ -0,0 +1,189 @@
|
|
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_nil
|
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
|
+
end
|
68
|
+
|
69
|
+
describe "#write_all" do
|
70
|
+
it "should pass the normalized dispatch as the key to the fundamental store" do
|
71
|
+
@dummy.should_receive(:write_all).with("TestController#action", @controller.body, {}, {})
|
72
|
+
|
73
|
+
@store.write_all(@controller)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should not store to the context cache if the dispatch is not storable" do
|
77
|
+
@dummy.should_not_receive(:write_all)
|
78
|
+
|
79
|
+
@store.write_all(:foo).should be_nil
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should use the controller instance's body as the data" do
|
83
|
+
@controller.should_receive(:body)
|
84
|
+
|
85
|
+
@store.write_all(@controller)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "examples" do
|
90
|
+
class MLBSchedule < Merb::Controller
|
91
|
+
cache :index
|
92
|
+
|
93
|
+
def index
|
94
|
+
"MLBSchedule index"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
class MLBScores < Merb::Controller
|
99
|
+
cache :index, :show
|
100
|
+
cache :overview
|
101
|
+
cache :short, :params => :page
|
102
|
+
cache :stats, :params => [:start_date, :end_date]
|
103
|
+
cache :ticker, :expire_in => 10
|
104
|
+
|
105
|
+
eager_cache :index, [MLBSchedule, :index]
|
106
|
+
eager_cache :overview, :index
|
107
|
+
eager_cache(:short, :params => :page) {|c| c.params[:page] = (c.params[:page].to_i + 1).to_s}
|
108
|
+
|
109
|
+
def index
|
110
|
+
"MLBScores index"
|
111
|
+
end
|
112
|
+
|
113
|
+
def show(team)
|
114
|
+
"MLBScores show(#{team})"
|
115
|
+
end
|
116
|
+
|
117
|
+
def overview(team = :all)
|
118
|
+
"MLBScores overview(#{team})"
|
119
|
+
end
|
120
|
+
|
121
|
+
def short(team = :all)
|
122
|
+
"MLBScores short(#{team})[#{params[:page]}]"
|
123
|
+
end
|
124
|
+
|
125
|
+
def stats(start_date, end_date, team = :all)
|
126
|
+
"MLBScores stats(#{team}, #{start_date}, #{end_date})"
|
127
|
+
end
|
128
|
+
|
129
|
+
def ticker
|
130
|
+
"MLBScores ticker"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should cache the index action on the first request" do
|
135
|
+
dispatch_to(MLBScores, :index)
|
136
|
+
|
137
|
+
@dummy.data("MLBScores#index").should == "MLBScores index"
|
138
|
+
end
|
139
|
+
|
140
|
+
it "should cache the show action by the team parameter using the action arguments" do
|
141
|
+
dispatch_to(MLBScores, :show, :team => :redsox)
|
142
|
+
|
143
|
+
@dummy.data("MLBScores#show", :team => 'redsox').should == "MLBScores show(redsox)"
|
144
|
+
end
|
145
|
+
|
146
|
+
it "should cache the overview action by the default parameter if none is given" do
|
147
|
+
dispatch_to(MLBScores, :overview)
|
148
|
+
|
149
|
+
@dummy.data("MLBScores#overview", :team => :all).should == "MLBScores overview(all)"
|
150
|
+
end
|
151
|
+
|
152
|
+
it "should cache the short action by the team & page parameters" do
|
153
|
+
dispatch_to(MLBScores, :short, :team => :bosux, :page => 4)
|
154
|
+
|
155
|
+
@dummy.data("MLBScores#short", :team => 'bosux', :page => '4').should == "MLBScores short(bosux)[4]"
|
156
|
+
end
|
157
|
+
|
158
|
+
it "should cache the stats action by team, start_date & end_date parameters" do
|
159
|
+
start_date, end_date = Time.today.to_s, Time.now.to_s
|
160
|
+
dispatch_to(MLBScores, :stats, :start_date => start_date, :end_date => end_date)
|
161
|
+
|
162
|
+
@dummy.data("MLBScores#stats", :team => :all, :start_date => start_date, :end_date => end_date).should == "MLBScores stats(all, #{start_date}, #{end_date})"
|
163
|
+
end
|
164
|
+
|
165
|
+
it "should cache the ticker action with an expire_in condition" do
|
166
|
+
dispatch_to(MLBScores, :ticker)
|
167
|
+
|
168
|
+
@dummy.conditions("MLBScores#ticker")[:expire_in].should == 10
|
169
|
+
end
|
170
|
+
|
171
|
+
it "should eager cache MLBSchedule#index after a request to MLBScores#index" do
|
172
|
+
dispatch_to(MLBScores, :index)
|
173
|
+
|
174
|
+
@dummy.data("MLBSchedule#index").should == "MLBSchedule index"
|
175
|
+
end
|
176
|
+
|
177
|
+
it "should eager cache :index after a request to :overview" do
|
178
|
+
dispatch_to(MLBScores, :overview)
|
179
|
+
|
180
|
+
@dummy.data("MLBScores#index").should == "MLBScores index"
|
181
|
+
end
|
182
|
+
|
183
|
+
it "should eager cache the next :short page" do
|
184
|
+
dispatch_to(MLBScores, :short, :team => :bosux, :page => 4)
|
185
|
+
|
186
|
+
@dummy.data("MLBScores#short", :team => 'bosux', :page => '5').should == "MLBScores short(bosux)[5]"
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
@@ -0,0 +1,225 @@
|
|
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 return the first non-nil result of a writeable store" do
|
57
|
+
unwritable, writable = mock(:unwritable_store), mock(:writable_store)
|
58
|
+
unwritable.should_receive(:write).and_return nil
|
59
|
+
writable.should_receive(:write).and_return true
|
60
|
+
|
61
|
+
adhoc = Merb::Cache::AdhocStore.new
|
62
|
+
adhoc.stores = [unwritable, writable]
|
63
|
+
adhoc.write(:foo).should be_true
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should stop calling writable after the first non-nil result" do
|
67
|
+
unwritable, writable, unused = mock(:unwritable_store), mock(:writable_store), mock(:unused_store)
|
68
|
+
unwritable.stub!(:write).and_return nil
|
69
|
+
writable.should_receive(:write).and_return true
|
70
|
+
unused.should_not_receive(:write)
|
71
|
+
|
72
|
+
adhoc = Merb::Cache::AdhocStore.new
|
73
|
+
adhoc.stores = [unwritable, writable, unused]
|
74
|
+
adhoc.write(:foo).should be_true
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should return nil if none of the stores are writable" do
|
78
|
+
unwritable = mock(:unwritable_store)
|
79
|
+
unwritable.should_receive(:write).exactly(3).times.and_return(nil)
|
80
|
+
|
81
|
+
adhoc = Merb::Cache::AdhocStore.new
|
82
|
+
adhoc.stores = [unwritable, unwritable, unwritable]
|
83
|
+
adhoc.write(:foo).should be_nil
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "#write_all" do
|
88
|
+
it "should return false if a store returns nil for write_all" do
|
89
|
+
unwritable, writable = mock(:unwritable_store), mock(:writable_store)
|
90
|
+
unwritable.should_receive(:write_all).and_return nil
|
91
|
+
writable.should_receive(:write_all).and_return "bar"
|
92
|
+
|
93
|
+
adhoc = Merb::Cache::AdhocStore.new
|
94
|
+
adhoc.stores = [unwritable, writable]
|
95
|
+
adhoc.write_all(:foo).should be_false
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should always call write_all on every store" do
|
99
|
+
unwritable, writable, used = mock(:unwritable_store), mock(:writable_store), mock(:used_store)
|
100
|
+
unwritable.stub!(:write_all).and_return nil
|
101
|
+
writable.should_receive(:write_all).and_return true
|
102
|
+
used.should_receive(:write_all).and_return true
|
103
|
+
|
104
|
+
adhoc = Merb::Cache::AdhocStore.new
|
105
|
+
adhoc.stores = [unwritable, writable, used]
|
106
|
+
adhoc.write_all(:foo).should be_false
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe "#fetch" do
|
111
|
+
it "should return a call to read if it is non-nil" do
|
112
|
+
adhoc = Merb::Cache::AdhocStore.new
|
113
|
+
adhoc.should_receive(:read).and_return "bar"
|
114
|
+
adhoc.fetch(:foo).should == "bar"
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should return the first non-nil result of a fetchable store" do
|
118
|
+
unfetchable, fetchable = mock(:unfetchable_store), mock(:fetchable_store)
|
119
|
+
unfetchable.should_receive(:fetch).and_return nil
|
120
|
+
fetchable.should_receive(:fetch).and_return true
|
121
|
+
|
122
|
+
adhoc = Merb::Cache::AdhocStore.new
|
123
|
+
adhoc.stores = [unfetchable, fetchable]
|
124
|
+
adhoc.should_receive(:read).and_return nil
|
125
|
+
adhoc.fetch(:foo).should be_true
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should return the value of the block if none of the stores are fetchable" do
|
129
|
+
adhoc = Merb::Cache::AdhocStore.new
|
130
|
+
adhoc.fetch(:foo) {
|
131
|
+
'foo'
|
132
|
+
|
133
|
+
}.should == 'foo'
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should stop calling fetch after the first non-nil result" do
|
137
|
+
unfetchable, fetchable, unused = mock(:unwritable_store), mock(:writable_store), mock(:unused_store)
|
138
|
+
unfetchable.stub!(:fetch).and_return nil
|
139
|
+
fetchable.should_receive(:fetch).and_return true
|
140
|
+
unused.should_not_receive(:fetch)
|
141
|
+
|
142
|
+
adhoc = Merb::Cache::AdhocStore.new
|
143
|
+
adhoc.stores = [unfetchable, fetchable, unused]
|
144
|
+
adhoc.should_receive(:read).and_return nil
|
145
|
+
adhoc.fetch(:foo).should be_true
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
describe "#exists?" do
|
150
|
+
it "should return the first non-nil result of a readable store" do
|
151
|
+
unreadable, readable = mock(:unreadable_store), mock(:readable_store)
|
152
|
+
unreadable.should_receive(:exists?).and_return nil
|
153
|
+
readable.should_receive(:exists?).and_return true
|
154
|
+
|
155
|
+
adhoc = Merb::Cache::AdhocStore.new
|
156
|
+
adhoc.stores = [unreadable, readable]
|
157
|
+
adhoc.exists?(:foo).should be_true
|
158
|
+
end
|
159
|
+
|
160
|
+
it "should stop calling readable after the first non-nil result" do
|
161
|
+
unreadable, readable, unused = mock(:unreadable_store), mock(:readable_store), mock(:unused_store)
|
162
|
+
unreadable.stub!(:exists?).and_return nil
|
163
|
+
readable.should_receive(:exists?).and_return true
|
164
|
+
unused.should_not_receive(:exists?)
|
165
|
+
|
166
|
+
adhoc = Merb::Cache::AdhocStore.new
|
167
|
+
adhoc.stores = [unreadable, readable, unused]
|
168
|
+
adhoc.exists?(:foo).should be_true
|
169
|
+
end
|
170
|
+
|
171
|
+
it "should return nil if none of the stores are readable" do
|
172
|
+
unreadable = mock(:unreadable_store)
|
173
|
+
unreadable.should_receive(:exists?).exactly(3).times.and_return(nil)
|
174
|
+
|
175
|
+
adhoc = Merb::Cache::AdhocStore.new
|
176
|
+
adhoc.stores = [unreadable, unreadable, unreadable]
|
177
|
+
adhoc.exists?(:foo).should be_nil
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
describe "#delete" do
|
182
|
+
it "should return false if all stores returns nil for delete" do
|
183
|
+
undeletable = mock(:undeletable_store)
|
184
|
+
undeletable.should_receive(:delete).and_return nil
|
185
|
+
|
186
|
+
adhoc = Merb::Cache::AdhocStore.new
|
187
|
+
adhoc.stores = [undeletable]
|
188
|
+
adhoc.delete(:foo).should be_false
|
189
|
+
end
|
190
|
+
|
191
|
+
it "should always call delete on every store" do
|
192
|
+
undeletable, deletable, used = mock(:undeletable_store), mock(:deletable_store), mock(:used_store)
|
193
|
+
undeletable.stub!(:delete).and_return nil
|
194
|
+
deletable.should_receive(:delete).and_return true
|
195
|
+
used.should_receive(:delete).and_return true
|
196
|
+
|
197
|
+
adhoc = Merb::Cache::AdhocStore.new
|
198
|
+
adhoc.stores = [undeletable, deletable, used]
|
199
|
+
adhoc.delete(:foo).should be_true
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
describe "#delete_all!" do
|
204
|
+
it "should return false if a store returns nil for write_all" do
|
205
|
+
undeletable, deletable = mock(:undeletable_store), mock(:deletable_store)
|
206
|
+
undeletable.should_receive(:delete_all!).and_return nil
|
207
|
+
deletable.should_receive(:delete_all!).and_return true
|
208
|
+
|
209
|
+
adhoc = Merb::Cache::AdhocStore.new
|
210
|
+
adhoc.stores = [undeletable, deletable]
|
211
|
+
adhoc.delete_all!.should be_false
|
212
|
+
end
|
213
|
+
|
214
|
+
it "should always call write_all on every store" do
|
215
|
+
undeletable, deletable, used = mock(:undeletable_store), mock(:deletable_store), mock(:used_store)
|
216
|
+
undeletable.stub!(:delete_all!).and_return nil
|
217
|
+
deletable.should_receive(:delete_all!).and_return true
|
218
|
+
used.should_receive(:delete_all!).and_return true
|
219
|
+
|
220
|
+
adhoc = Merb::Cache::AdhocStore.new
|
221
|
+
adhoc.stores = [undeletable, deletable, used]
|
222
|
+
adhoc.delete_all!.should be_false
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../../spec_helper'
|
2
|
+
require File.dirname(__FILE__) + '/abstract_strategy_store_spec'
|
3
|
+
|
4
|
+
describe Merb::Cache::GzipStore do
|
5
|
+
it_should_behave_like 'all strategy stores'
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
@klass = Merb::Cache::GzipStore
|
9
|
+
@store = Merb::Cache::GzipStore[DummyStore].new
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#writable?" do
|
13
|
+
it "should always be true" do
|
14
|
+
@store.writable?(:foo).should be_true
|
15
|
+
@store.writable?('foo').should be_true
|
16
|
+
@store.writable?(123).should be_true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#read" do
|
21
|
+
it "should return nil if hash does not exist as a key in any context store" do
|
22
|
+
@store.stores.each {|s| s.should_receive(:read).with(:foo, :bar => :baz).and_return nil}
|
23
|
+
|
24
|
+
@store.read(:foo, :bar => :baz).should be_nil
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should return the data from the context store when there is a hash key match" do
|
28
|
+
@store.stores.first.should_receive(:read).with(:foo, {}).and_return @store.compress("bar")
|
29
|
+
|
30
|
+
@store.read(:foo).should == "bar"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#write" do
|
35
|
+
it "should pass the hashed key to the context store" do
|
36
|
+
@store.stores.first.should_receive(:write).with(:foo, @store.compress('body'), {}, {}).and_return true
|
37
|
+
|
38
|
+
@store.write(:foo, 'body').should be_true
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should use the parameters to create the hashed key" do
|
42
|
+
@store.stores.first.should_receive(:write).with(:foo, @store.compress('body'), {:bar => :baz}, {}).and_return true
|
43
|
+
|
44
|
+
@store.write(:foo, 'body', :bar => :baz).should be_true
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "#fetch" do
|
49
|
+
# not sure how to spec this yet
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../../spec_helper'
|
2
|
+
require File.dirname(__FILE__) + '/abstract_strategy_store_spec'
|
3
|
+
|
4
|
+
describe Merb::Cache::PageStore do
|
5
|
+
it_should_behave_like 'all strategy stores'
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
Merb::Cache.stores.clear
|
9
|
+
Thread.current[:'merb-cache'] = nil
|
10
|
+
|
11
|
+
@klass = Merb::Cache::PageStore[:dummy]
|
12
|
+
Merb::Cache.register(:dummy, DummyStore)
|
13
|
+
Merb::Cache.register(:default, @klass)
|
14
|
+
|
15
|
+
@store = Merb::Cache[:default]
|
16
|
+
@dummy = @store.stores.first
|
17
|
+
end
|
18
|
+
|
19
|
+
def dispatch(url, attrs = {})
|
20
|
+
Merb::Dispatcher.handle(request_for(url, attrs))
|
21
|
+
end
|
22
|
+
|
23
|
+
def request_for(url, attrs = {})
|
24
|
+
Merb::Request.new(Rack::MockRequest.env_for(url, attrs))
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "examples" do
|
28
|
+
|
29
|
+
class NhlScores < Merb::Controller
|
30
|
+
provides :xml, :json, :yaml
|
31
|
+
|
32
|
+
cache :index, :show
|
33
|
+
cache :overview
|
34
|
+
|
35
|
+
eager_cache(:index, :overview) {|c| c.request.env['REQUEST_PATH'] = c.url(:overview)}
|
36
|
+
eager_cache :overview, :index
|
37
|
+
|
38
|
+
def index
|
39
|
+
"NHLScores index"
|
40
|
+
end
|
41
|
+
|
42
|
+
def show(team)
|
43
|
+
"NHLScores show(#{team})"
|
44
|
+
end
|
45
|
+
|
46
|
+
def overview
|
47
|
+
"NHLScores overview"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
before(:each) do
|
52
|
+
Merb::Router.prepare do |r|
|
53
|
+
r.match("/").to(:controller => "nhl_scores", :action => "index").name(:index)
|
54
|
+
r.match("/show/:team").to(:controller => "nhl_scores", :action => "show").name(:show)
|
55
|
+
r.match("/overview").to(:controller => "nhl_scores", :action => "overview").name(:overview)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
# NOTE: the "REQUEST_URI" => ... stuff will be removed after has_query_params? is in core.
|
61
|
+
it "should cache the index action on the first request" do
|
62
|
+
dispatch(url(:index), "REQUEST_URI" => url(:index))
|
63
|
+
|
64
|
+
@dummy.data("/index.html").should == "NHLScores index"
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should cache the yaml version of the index action request" do
|
68
|
+
dispatch(url(:index), "HTTP_ACCEPT" => "application/x-yaml", "REQUEST_URI" => url(:index))
|
69
|
+
|
70
|
+
@dummy.data("/index.yaml").should == "NHLScores index"
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should cache the show action when the team parameter is a route parameter" do
|
74
|
+
dispatch(url(:show, :team => 'redwings'), "REQUEST_URI" => url(:show, :team => 'redwings'))
|
75
|
+
|
76
|
+
@dummy.data("/show/redwings.html").should == "NHLScores show(redwings)"
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should cache the xml version of a request" do
|
80
|
+
dispatch(url(:show, :team => 'redwings'), "HTTP_ACCEPT" => "application/xml", "REQUEST_URI" => url(:show, :team => 'redwings'))
|
81
|
+
|
82
|
+
@dummy.data("/show/redwings.xml").should == "NHLScores show(redwings)"
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
it "should not cache the show action when the team parameter is not a route parameter" do
|
87
|
+
pending "the has_query_params? is implemented in merb-core"
|
88
|
+
dispatch_to(NhlScores, :show, :team => 'readwings', "REQUEST_URI" => url(:show, :team => 'redwings'))
|
89
|
+
|
90
|
+
@dummy.vault.should be_empty
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should not cache the action when a there is a query string parameter" do
|
94
|
+
dispatch(url(:index, :page => 2))
|
95
|
+
|
96
|
+
@dummy.data(url(:index)).should be_nil
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should not cache a POST request" do
|
100
|
+
dispatch(url(:index), "REQUEST_METHOD" => "POST")
|
101
|
+
|
102
|
+
@dummy.vault.should be_empty
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should not eager cache during an eager cache, causing an infinit loop of eagerness" do
|
106
|
+
dispatch(url(:overview), "REQUEST_URI" => url(:overview))
|
107
|
+
|
108
|
+
@dummy.data("/overview.html").should == "NHLScores overview"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../../spec_helper'
|
2
|
+
require File.dirname(__FILE__) + '/abstract_strategy_store_spec'
|
3
|
+
|
4
|
+
describe Merb::Cache::SHA1Store do
|
5
|
+
it_should_behave_like 'all strategy stores'
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
@klass = Merb::Cache::SHA1Store
|
9
|
+
@store = Merb::Cache::SHA1Store[DummyStore].new
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#writable?" do
|
13
|
+
it "should be true if the key is a string, symbol, or number" do
|
14
|
+
@store.writable?(:foo).should be_true
|
15
|
+
@store.writable?('foo').should be_true
|
16
|
+
@store.writable?(123).should be_true
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should be false if none of the context caches are writable" do
|
20
|
+
@store.stores.each {|s| s.should_receive(:writable?).and_return false}
|
21
|
+
|
22
|
+
@store.writable?(:foo).should be_false
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#read" do
|
27
|
+
it "should return nil if hash does not exist as a key in any context store" do
|
28
|
+
@store.stores.each {|s| s.should_receive(:read).with(@store.digest(:foo, :bar => :baz)).and_return nil}
|
29
|
+
|
30
|
+
@store.read(:foo, :bar => :baz).should be_nil
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should return the data from the context store when there is a hash key match" do
|
34
|
+
@store.stores.first.should_receive(:read).with(@store.digest(:foo)).and_return :bar
|
35
|
+
|
36
|
+
@store.read(:foo).should == :bar
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "#write" do
|
41
|
+
it "should pass the hashed key to the context store" do
|
42
|
+
@store.stores.first.should_receive(:write).with(@store.digest(:foo), 'body', {}, {}).and_return true
|
43
|
+
|
44
|
+
@store.write(:foo, 'body').should be_true
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should use the parameters to create the hashed key" do
|
48
|
+
@store.stores.first.should_receive(:write).with(@store.digest(:foo, :bar => :baz), 'body', {}, {}).and_return true
|
49
|
+
|
50
|
+
@store.write(:foo, 'body', :bar => :baz).should be_true
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "#fetch" do
|
55
|
+
it "should return nil if the arguments are not storable" do
|
56
|
+
@store.fetch(mock(:request)) {'body'}.should be_nil
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "#digest" do
|
63
|
+
it "should produce the same digest for the exact same key and parameters" do
|
64
|
+
@store.digest(:foo, :bar => :baz).should == @store.digest(:foo, :bar => :baz)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should use the string result of the parameter arguments to_param in the hash" do
|
68
|
+
@store.digest(:foo, :bar => :baz).should_not == @store.digest(:foo)
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should use the key argument in the hash" do
|
72
|
+
@store.digest('', :bar => :baz).should_not == @store.digest('')
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|