cached_record 0.1.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.
- 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
|