cached_record 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/.travis.yml +11 -0
- data/CHANGELOG.rdoc +5 -0
- data/Gemfile +13 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +391 -0
- data/Rakefile +90 -0
- data/VERSION +1 -0
- data/benchmark/setup.rb +77 -0
- data/cached_record.gemspec +26 -0
- data/config/database.yml +17 -0
- data/db/cached_record.sql +71 -0
- data/lib/cached_record/cache.rb +125 -0
- data/lib/cached_record/orm/active_record.rb +76 -0
- data/lib/cached_record/orm/data_mapper.rb +87 -0
- data/lib/cached_record/orm.rb +188 -0
- data/lib/cached_record/version.rb +7 -0
- data/lib/cached_record.rb +22 -0
- data/lib/gem_ext/redis.rb +25 -0
- data/log/.gitkeep +0 -0
- data/script/console +8 -0
- data/script/setup.rb +37 -0
- data/test/gem_ext/test_redis.rb +35 -0
- data/test/test_helper/coverage.rb +8 -0
- data/test/test_helper/db.rb +14 -0
- data/test/test_helper/minitest.rb +24 -0
- data/test/test_helper/setup.rb +16 -0
- data/test/test_helper.rb +17 -0
- data/test/unit/orm/test_active_record.rb +628 -0
- data/test/unit/orm/test_data_mapper.rb +616 -0
- data/test/unit/test_cache.rb +351 -0
- data/test/unit/test_cached_record.rb +34 -0
- data/test/unit/test_orm.rb +193 -0
- metadata +201 -0
@@ -0,0 +1,351 @@
|
|
1
|
+
require File.expand_path("../../test_helper", __FILE__)
|
2
|
+
|
3
|
+
module Unit
|
4
|
+
class TestCache < MiniTest::Test
|
5
|
+
|
6
|
+
describe CachedRecord::Cache do
|
7
|
+
after do
|
8
|
+
CachedRecord::Cache.instance_variable_set :@stores, nil
|
9
|
+
end
|
10
|
+
|
11
|
+
describe ".memcached" do
|
12
|
+
after do
|
13
|
+
Dalli::Client.unstub :new
|
14
|
+
end
|
15
|
+
it "initiates a Dalli::Client instance" do
|
16
|
+
Dalli::Client.expects(:new).with "127.0.0.1:11211", {}
|
17
|
+
CachedRecord::Cache.memcached :host => "127.0.0.1"
|
18
|
+
end
|
19
|
+
it "memoizes a Dalli::Client instance" do
|
20
|
+
client = mock
|
21
|
+
Dalli::Client.expects(:new).returns client
|
22
|
+
CachedRecord::Cache.memcached
|
23
|
+
assert_equal CachedRecord::Cache.memcached.object_id, client.object_id
|
24
|
+
assert_equal CachedRecord::Cache.memcached.object_id, client.object_id
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe ".redis" do
|
29
|
+
after do
|
30
|
+
Redis.unstub :new
|
31
|
+
end
|
32
|
+
it "initiates a Redis instance" do
|
33
|
+
Redis.expects(:new).with :host => "127.0.0.1"
|
34
|
+
CachedRecord::Cache.redis :host => "127.0.0.1"
|
35
|
+
end
|
36
|
+
it "memoizes a Redis instance" do
|
37
|
+
client = mock
|
38
|
+
Redis.expects(:new).returns client
|
39
|
+
CachedRecord::Cache.redis
|
40
|
+
assert_equal CachedRecord::Cache.redis.object_id, client.object_id
|
41
|
+
assert_equal CachedRecord::Cache.redis.object_id, client.object_id
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "cache store" do
|
46
|
+
describe ".valid_store?" do
|
47
|
+
it "returns whether the passed argument is a valid cache store" do
|
48
|
+
assert_equal true, CachedRecord::Cache.valid_store?("redis")
|
49
|
+
assert_equal true, CachedRecord::Cache.valid_store?("memcached")
|
50
|
+
assert_equal true, CachedRecord::Cache.valid_store?(:redis)
|
51
|
+
assert_equal true, CachedRecord::Cache.valid_store?(:memcached)
|
52
|
+
assert_equal false, CachedRecord::Cache.valid_store?("foo")
|
53
|
+
assert_equal false, CachedRecord::Cache.valid_store?(:foo)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
describe ".store" do
|
57
|
+
describe "with as_cache[:store]" do
|
58
|
+
describe "when valid" do
|
59
|
+
it "returns the specified cache client" do
|
60
|
+
klass = mock
|
61
|
+
klass.expects(:as_cache).returns({:store => :redis})
|
62
|
+
CachedRecord::Cache.expects(:send).with(:redis)
|
63
|
+
CachedRecord::Cache.store(klass)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
describe "when invalid" do
|
67
|
+
it "returns the specified cache client" do
|
68
|
+
klass = mock
|
69
|
+
klass.expects(:as_cache).returns({:store => :foo})
|
70
|
+
assert_raises CachedRecord::Cache::Error do
|
71
|
+
CachedRecord::Cache.store(klass)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
describe "without as_cache[:store]" do
|
77
|
+
before do
|
78
|
+
@klass = mock
|
79
|
+
@klass.stubs(:as_cache).returns({})
|
80
|
+
end
|
81
|
+
describe "with zero cache stores" do
|
82
|
+
it "raises an error" do
|
83
|
+
CachedRecord::Cache.instance_variable_set :@stores, {}
|
84
|
+
assert_raises CachedRecord::Cache::Error do
|
85
|
+
CachedRecord::Cache.store(@klass)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
describe "with one cache store" do
|
90
|
+
it "returns the cache store" do
|
91
|
+
CachedRecord::Cache.instance_variable_set :@stores, {:memcached => mock}
|
92
|
+
CachedRecord::Cache.store(@klass)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
describe "with multiple cache store" do
|
96
|
+
it "raises an error" do
|
97
|
+
CachedRecord::Cache.instance_variable_set :@stores, {:memcached => mock, :redis => mock}
|
98
|
+
assert_raises CachedRecord::Cache::Error do
|
99
|
+
CachedRecord::Cache.store(@klass)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
describe ".cache" do
|
106
|
+
it "returns a Hash" do
|
107
|
+
assert_equal({Dalli::Client => {}, Redis => {}}, CachedRecord::Cache.cache)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
describe ".clear!" do
|
111
|
+
it "returns a Hash" do
|
112
|
+
CachedRecord::Cache.instance_variable_set :@cache, {:foo => :bar}
|
113
|
+
assert_equal({:foo => :bar}, CachedRecord::Cache.cache)
|
114
|
+
|
115
|
+
CachedRecord::Cache.clear!
|
116
|
+
assert_nil CachedRecord::Cache.instance_variable_get(:@cache)
|
117
|
+
|
118
|
+
assert_equal({Dalli::Client => {}, Redis => {}}, CachedRecord::Cache.cache)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
describe ".get" do
|
122
|
+
before do
|
123
|
+
@klass = mock
|
124
|
+
@klass.stubs(:cache_key).returns("mock.123")
|
125
|
+
end
|
126
|
+
describe "without memoization" do
|
127
|
+
before do
|
128
|
+
@klass.stubs(:as_cache).returns({})
|
129
|
+
end
|
130
|
+
describe "with cache entry" do
|
131
|
+
it "returns a cached instance" do
|
132
|
+
store = mock
|
133
|
+
store.expects(:get).with("mock.123").returns('{"id":123}')
|
134
|
+
CachedRecord::Cache.expects(:store).with(@klass).returns(store)
|
135
|
+
|
136
|
+
cached_instance = mock
|
137
|
+
@klass.expects(:load_cache_json).with({"id" => 123}).returns cached_instance
|
138
|
+
|
139
|
+
assert_equal cached_instance, CachedRecord::Cache.get(@klass, 123)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
describe "with memoization" do
|
144
|
+
before do
|
145
|
+
@klass.stubs(:as_cache).returns({:store => :redis, :memoize => true})
|
146
|
+
end
|
147
|
+
describe "without cache entry" do
|
148
|
+
it "returns nil" do
|
149
|
+
store = mock
|
150
|
+
store.expects(:get).with("mock.123").returns(nil)
|
151
|
+
CachedRecord::Cache.expects(:store).with(@klass).returns(store)
|
152
|
+
assert_equal nil, CachedRecord::Cache.get(@klass, 123)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
describe "with cache entry" do
|
156
|
+
before do
|
157
|
+
@store = mock
|
158
|
+
@store.stubs(:get).with("mock.123").returns('{"id":123,"foo":"b@r"}@123456')
|
159
|
+
@store.stubs(:class).returns(Redis)
|
160
|
+
CachedRecord::Cache.stubs(:store).with(@klass).returns(@store)
|
161
|
+
end
|
162
|
+
describe "without memoized instance" do
|
163
|
+
it "returns a memoized instance" do
|
164
|
+
hash = mock
|
165
|
+
instance = mock
|
166
|
+
|
167
|
+
CachedRecord::Cache.expects(:cache).returns(Redis => hash)
|
168
|
+
hash.expects(:[]).with("mock.123").returns(nil)
|
169
|
+
hash.expects(:[]=).with("mock.123", :instance => instance, :epoch_time => 123456)
|
170
|
+
@klass.expects(:load_cache_json).with({"id" => 123,"foo" => "b@r"}).returns instance
|
171
|
+
|
172
|
+
assert_equal instance, CachedRecord::Cache.get(@klass, 123)
|
173
|
+
|
174
|
+
cache = {Redis => {"mock.123" => {:instance => instance, :epoch_time => 123456}}}
|
175
|
+
CachedRecord::Cache.expects(:cache).returns(cache)
|
176
|
+
@klass.expects(:load_cache_json).never
|
177
|
+
|
178
|
+
assert_equal instance, CachedRecord::Cache.get(@klass, 123)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
describe "with memoized instance" do
|
182
|
+
describe "outdated instance" do
|
183
|
+
it "returns a new memoized instance" do
|
184
|
+
hash = mock
|
185
|
+
outdated_instance = mock
|
186
|
+
instance = mock
|
187
|
+
|
188
|
+
CachedRecord::Cache.expects(:cache).returns(Redis => hash)
|
189
|
+
hash.expects(:[]).with("mock.123").returns({:instance => outdated_instance, :epoch_time => 12345})
|
190
|
+
hash.expects(:[]=).with("mock.123", :instance => instance, :epoch_time => 123456)
|
191
|
+
@klass.expects(:load_cache_json).with({"id" => 123,"foo" => "b@r"}).returns instance
|
192
|
+
|
193
|
+
assert_equal instance, CachedRecord::Cache.get(@klass, 123)
|
194
|
+
|
195
|
+
cache = {Redis => {"mock.123" => {:instance => instance, :epoch_time => 123456}}}
|
196
|
+
CachedRecord::Cache.expects(:cache).returns(cache)
|
197
|
+
@klass.expects(:load_cache_json).never
|
198
|
+
|
199
|
+
assert_equal instance, CachedRecord::Cache.get(@klass, 123)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
describe "uptodate instance" do
|
203
|
+
it "returns the memoized instance" do
|
204
|
+
hash = mock
|
205
|
+
instance = mock
|
206
|
+
|
207
|
+
CachedRecord::Cache.expects(:cache).returns(Redis => hash)
|
208
|
+
hash.expects(:[]).with("mock.123").returns({:instance => instance, :epoch_time => 123456})
|
209
|
+
@klass.expects(:load_cache_json).never
|
210
|
+
|
211
|
+
assert_equal instance, CachedRecord::Cache.get(@klass, 123)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
describe ".set" do
|
219
|
+
before do
|
220
|
+
id = 123
|
221
|
+
|
222
|
+
@klass = mock
|
223
|
+
@klass.stubs(:cache_key).with(id).returns("mock.123")
|
224
|
+
|
225
|
+
@instance = mock
|
226
|
+
@instance.stubs(:id).returns(id)
|
227
|
+
@instance.stubs(:class).returns(@klass)
|
228
|
+
@instance.stubs(:to_cache_json).returns('{"id":123}')
|
229
|
+
|
230
|
+
@store = mock
|
231
|
+
CachedRecord::Cache.stubs(:store).returns(@store)
|
232
|
+
end
|
233
|
+
describe "without memoization" do
|
234
|
+
before do
|
235
|
+
@klass.stubs(:as_cache).returns({})
|
236
|
+
end
|
237
|
+
it "stores cache JSON" do
|
238
|
+
@store.expects(:set).with("mock.123", '{"id":123}', nil)
|
239
|
+
CachedRecord::Cache.set @instance
|
240
|
+
end
|
241
|
+
end
|
242
|
+
describe "with memoization" do
|
243
|
+
before do
|
244
|
+
@klass.stubs(:as_cache).returns({:memoize => true})
|
245
|
+
end
|
246
|
+
it "stores cache JSON" do
|
247
|
+
Time.any_instance.expects(:to_i).returns(123456789)
|
248
|
+
@store.expects(:set).with("mock.123", '{"id":123}@123456789', nil)
|
249
|
+
CachedRecord::Cache.set @instance
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
describe ".expire" do
|
254
|
+
before do
|
255
|
+
id = 123
|
256
|
+
|
257
|
+
@klass = mock
|
258
|
+
@klass.stubs(:cache_key).with(id).returns("mock.123")
|
259
|
+
|
260
|
+
@instance = mock
|
261
|
+
@instance.stubs(:id).returns(id)
|
262
|
+
@instance.stubs(:class).returns(@klass)
|
263
|
+
|
264
|
+
@store = mock
|
265
|
+
CachedRecord::Cache.stubs(:store).returns(@store)
|
266
|
+
end
|
267
|
+
describe "without memoization" do
|
268
|
+
before do
|
269
|
+
@klass.stubs(:as_cache).returns({:store => :redis})
|
270
|
+
end
|
271
|
+
it "deletes key from cache store" do
|
272
|
+
@store.expects(:delete).with("mock.123")
|
273
|
+
CachedRecord::Cache.expire @instance
|
274
|
+
end
|
275
|
+
end
|
276
|
+
describe "with memoization" do
|
277
|
+
before do
|
278
|
+
@klass.stubs(:as_cache).returns({:store => :redis, :memoize => true})
|
279
|
+
end
|
280
|
+
it "deletes key from cache store and memoized cache" do
|
281
|
+
hash = mock
|
282
|
+
hash.expects(:delete).with("mock.123")
|
283
|
+
@store.expects(:delete).with("mock.123")
|
284
|
+
CachedRecord::Cache.expects(:cache).returns @store.class => hash
|
285
|
+
CachedRecord::Cache.expire @instance
|
286
|
+
end
|
287
|
+
end
|
288
|
+
end
|
289
|
+
describe ".memoized" do
|
290
|
+
describe "without memoization" do
|
291
|
+
it "returns nil" do
|
292
|
+
klass = mock
|
293
|
+
klass.expects(:as_cache).returns({})
|
294
|
+
instance = mock
|
295
|
+
|
296
|
+
CachedRecord::Cache.expects(:cache).never
|
297
|
+
assert_equal instance, CachedRecord::Cache.memoized(klass, 123, 123456789) { instance }
|
298
|
+
end
|
299
|
+
end
|
300
|
+
describe "with memoization" do
|
301
|
+
before do
|
302
|
+
@klass = mock
|
303
|
+
@klass.stubs(:as_cache).returns({:store => :redis, :memoize => true})
|
304
|
+
@klass.stubs(:cache_key).returns("mock.123")
|
305
|
+
end
|
306
|
+
describe "empty cache hash" do
|
307
|
+
it "returns nil" do
|
308
|
+
hash = mock
|
309
|
+
hash.expects(:[]).with("mock.123")
|
310
|
+
CachedRecord::Cache.expects(:cache).returns Redis => hash
|
311
|
+
assert_nil CachedRecord::Cache.memoized(@klass, 123, 123456789) {}
|
312
|
+
end
|
313
|
+
end
|
314
|
+
describe "matching cache hash entry" do
|
315
|
+
before do
|
316
|
+
@instance = mock
|
317
|
+
end
|
318
|
+
describe "non matching epoch time" do
|
319
|
+
it "returns nil" do
|
320
|
+
hash = mock
|
321
|
+
hash.expects(:[]).with("mock.123").returns :instance => mock, :epoch_time => 123456789
|
322
|
+
hash.expects(:[]=).with("mock.123", {:instance => @instance, :epoch_time => 987654321})
|
323
|
+
|
324
|
+
CachedRecord::Cache.expects(:cache).returns Redis => hash
|
325
|
+
assert_equal @instance, CachedRecord::Cache.memoized(@klass, 123, 987654321) { @instance }
|
326
|
+
end
|
327
|
+
end
|
328
|
+
describe "matching epoch time" do
|
329
|
+
it "returns memoized instance" do
|
330
|
+
hash = mock
|
331
|
+
hash.expects(:[]).with("mock.123").returns :instance => @instance, :epoch_time => 123456789
|
332
|
+
|
333
|
+
CachedRecord::Cache.expects(:cache).returns Redis => hash
|
334
|
+
assert_equal @instance, CachedRecord::Cache.memoized(@klass, 123, 123456789) { mock }
|
335
|
+
end
|
336
|
+
end
|
337
|
+
end
|
338
|
+
end
|
339
|
+
end
|
340
|
+
describe ".split_cache_string" do
|
341
|
+
it "returns an array containing a JSON string and an optional epoch time integer" do
|
342
|
+
assert_equal ["", nil], CachedRecord::Cache.send(:split_cache_string, "")
|
343
|
+
assert_equal ['{"id":123,"foo":"b@r"}', nil], CachedRecord::Cache.send(:split_cache_string, '{"id":123,"foo":"b@r"}')
|
344
|
+
assert_equal ['{"id":123,"foo":"b@r"}', 123456789], CachedRecord::Cache.send(:split_cache_string, '{"id":123,"foo":"b@r"}@123456789')
|
345
|
+
end
|
346
|
+
end
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
end
|
351
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require File.expand_path("../../test_helper", __FILE__)
|
2
|
+
|
3
|
+
module Unit
|
4
|
+
class TestCachedRecord < MiniTest::Test
|
5
|
+
|
6
|
+
describe CachedRecord do
|
7
|
+
it "has the current version" do
|
8
|
+
version = "0.1.0"
|
9
|
+
assert_equal version, CachedRecord::VERSION
|
10
|
+
assert File.read(path "CHANGELOG.rdoc").include?("Version #{version}")
|
11
|
+
assert File.read(path "VERSION").include?(version)
|
12
|
+
end
|
13
|
+
|
14
|
+
describe ".setup" do
|
15
|
+
it "sets up ActiveRecord, DataMapper and Cache" do
|
16
|
+
CachedRecord::Cache.expects(:redis).with(:host => "127.0.0.1")
|
17
|
+
CachedRecord::Cache.expects(:memcached).with(:host => "0.0.0.0")
|
18
|
+
CachedRecord::ORM::ActiveRecord.expects(:setup)
|
19
|
+
CachedRecord::ORM::DataMapper.expects(:setup)
|
20
|
+
CachedRecord.setup :redis => {:host => "127.0.0.1"}, :memcached => {:host => "0.0.0.0"}
|
21
|
+
end
|
22
|
+
|
23
|
+
it "accepts an array of cache stores" do
|
24
|
+
CachedRecord::Cache.expects(:redis)
|
25
|
+
CachedRecord::Cache.expects(:memcached)
|
26
|
+
CachedRecord::ORM::ActiveRecord.expects(:setup)
|
27
|
+
CachedRecord::ORM::DataMapper.expects(:setup)
|
28
|
+
CachedRecord.setup :redis, :memcached
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,193 @@
|
|
1
|
+
require File.expand_path("../../test_helper", __FILE__)
|
2
|
+
|
3
|
+
module Unit
|
4
|
+
class TestORM < MiniTest::Test
|
5
|
+
|
6
|
+
class A
|
7
|
+
include CachedRecord::ORM
|
8
|
+
as_cache :redis, "only" => [:title], :include => [:b], :memoize => [:sequence]
|
9
|
+
def id; end
|
10
|
+
end
|
11
|
+
|
12
|
+
class B
|
13
|
+
include CachedRecord::ORM
|
14
|
+
as_cache :redis, "only" => [:title], :include => [:b], "memoize" => {"calculate" => :@array}
|
15
|
+
end
|
16
|
+
|
17
|
+
class C
|
18
|
+
include CachedRecord::ORM
|
19
|
+
as_cache :redis, :only => [:title], "include" => [:b], :memoize => [:sequence, {:calculate => "@array"}]
|
20
|
+
end
|
21
|
+
|
22
|
+
class D
|
23
|
+
include CachedRecord::ORM
|
24
|
+
as_cache :redis, :only => [:title], :include_root => true
|
25
|
+
end
|
26
|
+
|
27
|
+
describe CachedRecord::ORM do
|
28
|
+
describe "when extended within a class" do
|
29
|
+
|
30
|
+
describe "classes" do
|
31
|
+
it "validates and parses 'as cache json options'" do
|
32
|
+
assert_raises ArgumentError do
|
33
|
+
A.as_cache :foonly => []
|
34
|
+
end
|
35
|
+
assert_raises ArgumentError do
|
36
|
+
A.as_cache :only => :foo
|
37
|
+
end
|
38
|
+
assert_raises ArgumentError do
|
39
|
+
A.as_cache :include => :foo
|
40
|
+
end
|
41
|
+
assert_raises ArgumentError do
|
42
|
+
A.as_cache :memoize => :foo
|
43
|
+
end
|
44
|
+
assert_raises ArgumentError do
|
45
|
+
A.as_cache :include_root => :foo
|
46
|
+
end
|
47
|
+
end
|
48
|
+
it "stores its cache options" do
|
49
|
+
assert_equal({
|
50
|
+
:store => :redis,
|
51
|
+
:as_json => {
|
52
|
+
:only => [:title],
|
53
|
+
:include => [:b],
|
54
|
+
:memoize => {:sequence => :@sequence}
|
55
|
+
}
|
56
|
+
}, A.as_cache)
|
57
|
+
assert_equal({
|
58
|
+
:store => :redis,
|
59
|
+
:as_json => {
|
60
|
+
:only => [:title],
|
61
|
+
:include => [:b],
|
62
|
+
:memoize => {:calculate => :@array}
|
63
|
+
}
|
64
|
+
}, B.as_cache)
|
65
|
+
assert_equal({
|
66
|
+
:store => :redis,
|
67
|
+
:as_json => {
|
68
|
+
:only => [:title],
|
69
|
+
:include => [:b],
|
70
|
+
:memoize => {:sequence => :@sequence, :calculate => :@array}
|
71
|
+
}
|
72
|
+
}, C.as_cache)
|
73
|
+
assert_equal({
|
74
|
+
:store => :redis,
|
75
|
+
:as_json => {
|
76
|
+
:only => [:title],
|
77
|
+
:include_root => true
|
78
|
+
}
|
79
|
+
}, D.as_cache)
|
80
|
+
end
|
81
|
+
it "stores whether it should memoize instances" do
|
82
|
+
options = {}
|
83
|
+
A.expects(:as_cache).with(:foo => :bar).returns(options)
|
84
|
+
A.as_memoized_cache :foo => :bar
|
85
|
+
assert_equal options, {:memoize => true}
|
86
|
+
end
|
87
|
+
it "memoizes its cache options" do
|
88
|
+
options = A.as_cache
|
89
|
+
assert_equal options.object_id, A.as_cache.object_id
|
90
|
+
end
|
91
|
+
it "returns cache keys" do
|
92
|
+
assert_equal "unit.test_orm.a.123", A.cache_key(123)
|
93
|
+
end
|
94
|
+
it "returns the cache root" do
|
95
|
+
assert_equal :a, A.cache_root
|
96
|
+
end
|
97
|
+
it "requires an implemented `uncached` method" do
|
98
|
+
assert_raises NotImplementedError do
|
99
|
+
A.uncached 1
|
100
|
+
end
|
101
|
+
end
|
102
|
+
it "requires an implemented `set_cached_association` method" do
|
103
|
+
assert_raises NotImplementedError do
|
104
|
+
A.send :set_cached_association, :a, :b, :c
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe "instances" do
|
110
|
+
it "requires an implemented `cache_attributes` method" do
|
111
|
+
assert_raises NotImplementedError do
|
112
|
+
A.new.cache_attributes
|
113
|
+
end
|
114
|
+
end
|
115
|
+
it "requires an implemented `cache_foreign_keys` method" do
|
116
|
+
assert_raises NotImplementedError do
|
117
|
+
A.new.cache_foreign_keys
|
118
|
+
end
|
119
|
+
end
|
120
|
+
it "knows its as cache JSON options" do
|
121
|
+
assert_equal({
|
122
|
+
:only => [:title],
|
123
|
+
:include => [:b],
|
124
|
+
:memoize => {:sequence => :@sequence}
|
125
|
+
}, A.new.send(:cache_json_options))
|
126
|
+
assert_equal({
|
127
|
+
:only => [:title],
|
128
|
+
:include => [:b],
|
129
|
+
:memoize => {:calculate => :@array}
|
130
|
+
}, B.new.send(:cache_json_options))
|
131
|
+
assert_equal({
|
132
|
+
:only => [:title],
|
133
|
+
:include => [:b],
|
134
|
+
:memoize => {:sequence => :@sequence, :calculate => :@array}
|
135
|
+
}, C.new.send(:cache_json_options))
|
136
|
+
assert_equal({
|
137
|
+
:only => [:title],
|
138
|
+
:include_root => true
|
139
|
+
}, D.new.send(:cache_json_options))
|
140
|
+
end
|
141
|
+
it "returns a cache JSON string" do
|
142
|
+
hash = mock
|
143
|
+
hash.expects(:to_json)
|
144
|
+
a = A.new
|
145
|
+
a.expects(:as_cache_json).returns(hash)
|
146
|
+
a.to_cache_json
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
describe ".cached" do
|
151
|
+
describe "when not having a cache entry" do
|
152
|
+
it "returns an uncached instance and stores its cache JSON in the cache store" do
|
153
|
+
uncached_instance = A.new
|
154
|
+
uncached_instance.expects(:to_cache_json).returns({})
|
155
|
+
|
156
|
+
A.stubs(:as_cache).returns({:store => :redis, :as_json => {}})
|
157
|
+
A.expects(:uncached).with(123).returns uncached_instance
|
158
|
+
A.expects(:new).returns uncached_instance
|
159
|
+
|
160
|
+
assert_equal uncached_instance, A.cached(123)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
describe "when having a cache entry" do
|
164
|
+
it "returns a cached instance" do
|
165
|
+
cached_instance = mock
|
166
|
+
CachedRecord::Cache.expects(:get).with(A, 123).returns cached_instance
|
167
|
+
assert_equal cached_instance, A.cached(123)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
describe "#cache" do
|
173
|
+
it "delegates to class.cached" do
|
174
|
+
id, instance = 2, A.new
|
175
|
+
instance.expects(:id).returns(id)
|
176
|
+
A.expects(:cached).with(id)
|
177
|
+
assert instance.cache
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
describe "#expire" do
|
182
|
+
it "delegates to CachedRecord::Cache.expire" do
|
183
|
+
instance = A.new
|
184
|
+
CachedRecord::Cache.expects(:expire).with(instance)
|
185
|
+
assert instance.expire
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
end
|
193
|
+
end
|