merb-cache 0.9.7 → 0.9.8
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 +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
|