cached_model 1.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +49 -1
- data/Rakefile +1 -1
- data/lib/cached_model.rb +79 -25
- data/test/test_cached_model.rb +181 -20
- metadata +3 -2
data/README
CHANGED
@@ -4,12 +4,30 @@ Rubyforge Project:
|
|
4
4
|
|
5
5
|
http://rubyforge.org/projects/rctools/
|
6
6
|
|
7
|
+
Documentation:
|
8
|
+
|
9
|
+
http://dev.robotcoop.com/Libraries/cached_model/
|
10
|
+
|
7
11
|
== About
|
8
12
|
|
9
13
|
CachedModel stores Rails ActiveRecord objects in memcache allowing for very
|
10
14
|
fast retrievals. CachedModel uses the ActiveRecord::Locking to ensure that
|
11
15
|
you don't perform multiple updates.
|
12
16
|
|
17
|
+
== CachedModel Doesn't...
|
18
|
+
|
19
|
+
CachedModel is not magic.
|
20
|
+
|
21
|
+
CachedModel only accelerates simple finds for single rows.
|
22
|
+
|
23
|
+
CachedModel won't cache every query you run.
|
24
|
+
|
25
|
+
CachedModel isn't smart enough to determine the dependencies between your
|
26
|
+
queries so that it can accelerate more complicated queries. Without these
|
27
|
+
smarts you'll only end up with a broken application.
|
28
|
+
|
29
|
+
If you want to cache more complicated queries you need do it by hand.
|
30
|
+
|
13
31
|
== Using CachedModel
|
14
32
|
|
15
33
|
First, install the cached_model gem:
|
@@ -50,7 +68,7 @@ Then make Rails load the gem:
|
|
50
68
|
$ tail -n 4 config/environment.rb
|
51
69
|
# Include your application configuration below
|
52
70
|
|
53
|
-
|
71
|
+
require 'cached_model'
|
54
72
|
|
55
73
|
Then edit your ActiveRecord model to inherit from CachedModel instead of
|
56
74
|
ActiveRecord::Base:
|
@@ -64,3 +82,33 @@ ActiveRecord::Base:
|
|
64
82
|
belongs_to :point
|
65
83
|
belongs_to :route
|
66
84
|
|
85
|
+
== Extra Features
|
86
|
+
|
87
|
+
=== Local Cache
|
88
|
+
|
89
|
+
CachedModel also incorporates an in-process cache, but it is disabled by
|
90
|
+
default. In order to enable the in-process cache enable it in your
|
91
|
+
environment.rb:
|
92
|
+
|
93
|
+
CachedModel.use_local_cache = true
|
94
|
+
|
95
|
+
And add a after_filter that flushes the local cache:
|
96
|
+
|
97
|
+
class ApplicationController < ActionController::Base
|
98
|
+
|
99
|
+
after_filter { CachedModel.cache_reset }
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
IF YOU DO NOT ADD THE AFTER FILTER YOU WILL EXPERIENCE EXTREME PROCESS GROWTH.
|
104
|
+
|
105
|
+
=== Memcache
|
106
|
+
|
107
|
+
Memcache may be disabled and the TTL for objects stored in memcache may be
|
108
|
+
changed:
|
109
|
+
|
110
|
+
CachedModel.use_memcache = false
|
111
|
+
CachedModel.ttl = 86400
|
112
|
+
|
113
|
+
The default TTL for memcache objects is 900 seconds.
|
114
|
+
|
data/Rakefile
CHANGED
@@ -8,7 +8,7 @@ $VERBOSE = nil
|
|
8
8
|
|
9
9
|
spec = Gem::Specification.new do |s|
|
10
10
|
s.name = 'cached_model'
|
11
|
-
s.version = '1.0
|
11
|
+
s.version = '1.1.0'
|
12
12
|
s.summary = 'An ActiveRecord::Base model that caches records'
|
13
13
|
s.authors = 'Robert Cottrell, Eric Hodel'
|
14
14
|
s.email = 'bob@robotcoop.com'
|
data/lib/cached_model.rb
CHANGED
@@ -9,12 +9,53 @@ require 'memcache_util' unless $TESTING == :cached_model
|
|
9
9
|
|
10
10
|
class CachedModel < ActiveRecord::Base
|
11
11
|
|
12
|
-
KEY = 'active_record'
|
13
|
-
TTL = 60 * 15 # seconds
|
14
|
-
|
15
12
|
@cache_local = {}
|
13
|
+
@use_local_cache = false
|
14
|
+
@use_memcache = true
|
15
|
+
@ttl = 60 * 15
|
16
16
|
|
17
|
-
class << self
|
17
|
+
class << self
|
18
|
+
|
19
|
+
##
|
20
|
+
# The local process cache. You shouldn't touch me.
|
21
|
+
|
22
|
+
attr_reader :cache_local
|
23
|
+
|
24
|
+
##
|
25
|
+
# Enables or disables use of the local cache.
|
26
|
+
#
|
27
|
+
# NOTE if you enable this you must call #cache_reset or you will
|
28
|
+
# experience uncontrollable process growth!
|
29
|
+
#
|
30
|
+
# Defaults to false.
|
31
|
+
|
32
|
+
attr_writer :use_local_cache
|
33
|
+
|
34
|
+
##
|
35
|
+
# Enables or disables the use of memcache.
|
36
|
+
|
37
|
+
attr_writer :use_memcache
|
38
|
+
|
39
|
+
##
|
40
|
+
# Memcache record time-to-live for stored records.
|
41
|
+
|
42
|
+
attr_accessor :ttl
|
43
|
+
|
44
|
+
##
|
45
|
+
# Returns true if use of the local cache is enabled.
|
46
|
+
|
47
|
+
def use_local_cache?
|
48
|
+
return @use_local_cache
|
49
|
+
end
|
50
|
+
|
51
|
+
##
|
52
|
+
# Returns true if use of memcache is enabled.
|
53
|
+
|
54
|
+
def use_memcache?
|
55
|
+
return @use_memcache
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
18
59
|
|
19
60
|
##
|
20
61
|
# Override the flawed assumption ActiveRecord::Base makes about inheritance.
|
@@ -22,7 +63,7 @@ class CachedModel < ActiveRecord::Base
|
|
22
63
|
def self.descends_from_active_record?
|
23
64
|
superclass == CachedModel
|
24
65
|
end
|
25
|
-
|
66
|
+
|
26
67
|
##
|
27
68
|
# Override the flawed assumption ActiveRecord::Base makes about inheritance.
|
28
69
|
|
@@ -36,21 +77,21 @@ class CachedModel < ActiveRecord::Base
|
|
36
77
|
end
|
37
78
|
end
|
38
79
|
|
39
|
-
##
|
80
|
+
##
|
40
81
|
# Invalidate the cache entry for an record. The update method will
|
41
82
|
# automatically invalidate the cache when updates are made through
|
42
83
|
# ActiveRecord model record. However, several methods update tables with
|
43
84
|
# direct sql queries for effeciency. These methods should call this method
|
44
85
|
# to invalidate the cache after making those changes.
|
45
|
-
#
|
86
|
+
#
|
46
87
|
# NOTE - if a SQL query updates multiple rows with one query, there is
|
47
88
|
# currently no way to invalidate the affected entries unless the entire
|
48
89
|
# cache is dumped or until the TTL expires, so try not to do this.
|
49
90
|
|
50
91
|
def self.cache_delete(klass, id)
|
51
92
|
key = "#{klass}:#{id}"
|
52
|
-
CachedModel.cache_local.delete key
|
53
|
-
Cache.delete "
|
93
|
+
CachedModel.cache_local.delete key if CachedModel.use_local_cache?
|
94
|
+
Cache.delete "active_record:#{key}" if CachedModel.use_memcache?
|
54
95
|
end
|
55
96
|
|
56
97
|
##
|
@@ -58,7 +99,7 @@ class CachedModel < ActiveRecord::Base
|
|
58
99
|
# filter at the beginning of each request.
|
59
100
|
|
60
101
|
def self.cache_reset
|
61
|
-
CachedModel.cache_local.clear
|
102
|
+
CachedModel.cache_local.clear if CachedModel.use_local_cache?
|
62
103
|
end
|
63
104
|
|
64
105
|
##
|
@@ -73,12 +114,14 @@ class CachedModel < ActiveRecord::Base
|
|
73
114
|
if ($TESTING and $TESTING != :cached_model) or
|
74
115
|
args.length != 1 or not Fixnum === args.first then
|
75
116
|
records = super
|
117
|
+
# Rails requires two levels of indirection to look up a record
|
118
|
+
return records if args.first == :all and @skip_find_hack
|
76
119
|
return records if RAILS_ENV == 'test'
|
77
120
|
case records
|
78
121
|
when Array then
|
79
122
|
records.each { |r| r.cache_store }
|
80
123
|
when CachedModel then
|
81
|
-
records.cache_store
|
124
|
+
records.cache_store # Model.find 1 gets cached here
|
82
125
|
end
|
83
126
|
return records
|
84
127
|
end
|
@@ -86,26 +129,33 @@ class CachedModel < ActiveRecord::Base
|
|
86
129
|
# Try to find the record in the local cache.
|
87
130
|
id = args.first
|
88
131
|
cache_key_local = "#{name}:#{id}"
|
89
|
-
|
90
|
-
|
132
|
+
if CachedModel.use_local_cache? then
|
133
|
+
record = CachedModel.cache_local[cache_key_local]
|
134
|
+
return record unless record.nil?
|
135
|
+
end
|
91
136
|
|
92
137
|
# Try to find the record in memcache and add it to the local cache
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
138
|
+
if CachedModel.use_memcache? then
|
139
|
+
record = Cache.get "active_record:#{cache_key_local}"
|
140
|
+
unless record.nil? then
|
141
|
+
if CachedModel.use_local_cache? then
|
142
|
+
CachedModel.cache_local[cache_key_local] = record
|
143
|
+
end
|
144
|
+
return record
|
145
|
+
end
|
97
146
|
end
|
98
147
|
|
99
|
-
# Fetch the record from the DB
|
148
|
+
# Fetch the record from the DB. Inside the mulitple levels of indirection
|
149
|
+
# of find it will get cached.
|
100
150
|
#
|
101
151
|
# We don't want the subsequent find_by_sql to loop back here, so guard
|
102
152
|
# the call.
|
103
153
|
#
|
104
|
-
# NOTE
|
154
|
+
# NOTE This guard is not thread safe, beware use of CachedModel where
|
155
|
+
# ActiveRecord's thread safety is disabled.
|
105
156
|
begin
|
106
157
|
@skip_find_hack = true
|
107
158
|
record = super(args).first
|
108
|
-
record.cache_store
|
109
159
|
ensure
|
110
160
|
@skip_find_hack = false
|
111
161
|
end
|
@@ -160,8 +210,8 @@ class CachedModel < ActiveRecord::Base
|
|
160
210
|
# Remove this record from the cache.
|
161
211
|
|
162
212
|
def cache_delete
|
163
|
-
cache_local.delete cache_key_local
|
164
|
-
Cache.delete cache_key_memcache
|
213
|
+
cache_local.delete cache_key_local if CachedModel.use_local_cache?
|
214
|
+
Cache.delete cache_key_memcache if CachedModel.use_memcache?
|
165
215
|
end
|
166
216
|
|
167
217
|
##
|
@@ -175,7 +225,7 @@ class CachedModel < ActiveRecord::Base
|
|
175
225
|
# The memcache key for this record.
|
176
226
|
|
177
227
|
def cache_key_memcache
|
178
|
-
return "
|
228
|
+
return "active_record:#{cache_key_local}"
|
179
229
|
end
|
180
230
|
|
181
231
|
##
|
@@ -192,8 +242,12 @@ class CachedModel < ActiveRecord::Base
|
|
192
242
|
def cache_store
|
193
243
|
obj = dup
|
194
244
|
obj.send :instance_variable_set, :@attributes, attributes_before_type_cast
|
195
|
-
|
196
|
-
|
245
|
+
if CachedModel.use_local_cache? then
|
246
|
+
cache_local[cache_key_local] = obj
|
247
|
+
end
|
248
|
+
if CachedModel.use_memcache? then
|
249
|
+
Cache.put cache_key_memcache, obj, CachedModel.ttl
|
250
|
+
end
|
197
251
|
end
|
198
252
|
|
199
253
|
end
|
data/test/test_cached_model.rb
CHANGED
@@ -12,6 +12,32 @@ class ActiveRecord::Base
|
|
12
12
|
|
13
13
|
attr_accessor :id, :attributes
|
14
14
|
|
15
|
+
def self.find(*args)
|
16
|
+
args.flatten!
|
17
|
+
case args.first
|
18
|
+
when :first then
|
19
|
+
return find(:all, *args)
|
20
|
+
when :all then
|
21
|
+
[new]
|
22
|
+
else
|
23
|
+
case args.length
|
24
|
+
when 1 then
|
25
|
+
return find(:first, *args) if Fixnum === args.first
|
26
|
+
raise "Dunno what to do"
|
27
|
+
when 2 then
|
28
|
+
return new
|
29
|
+
when 3 then
|
30
|
+
return [new, new, new]
|
31
|
+
else
|
32
|
+
raise "Dunno what to do"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.find_by_sql(query)
|
38
|
+
return [new]
|
39
|
+
end
|
40
|
+
|
15
41
|
def self.next_id
|
16
42
|
@count += 1
|
17
43
|
return @count
|
@@ -25,17 +51,6 @@ class ActiveRecord::Base
|
|
25
51
|
'id'
|
26
52
|
end
|
27
53
|
|
28
|
-
def self.find(*args)
|
29
|
-
args.flatten!
|
30
|
-
return [new] if args.length == 1 and Fixnum === args.first
|
31
|
-
return new if args.length == 2
|
32
|
-
return [new, new, new] if args.length == 3
|
33
|
-
end
|
34
|
-
|
35
|
-
def self.find_by_sql(query)
|
36
|
-
return [new]
|
37
|
-
end
|
38
|
-
|
39
54
|
def initialize
|
40
55
|
@id = ActiveRecord::Base.next_id
|
41
56
|
@attributes = { :data => 'data' }
|
@@ -102,14 +117,26 @@ end
|
|
102
117
|
|
103
118
|
class TestCachedModel < Test::Unit::TestCase
|
104
119
|
|
120
|
+
DEFAULT_USE_LOCAL_CACHE = CachedModel.use_local_cache?
|
121
|
+
DEFAULT_USE_MEMCACHE = CachedModel.use_memcache?
|
122
|
+
|
105
123
|
def setup
|
106
124
|
@model = Concrete.new
|
107
125
|
Cache.cache = {}
|
108
126
|
Cache.ttl = {}
|
109
127
|
CachedModel.cache_local = {}
|
128
|
+
CachedModel.use_local_cache = DEFAULT_USE_LOCAL_CACHE
|
129
|
+
CachedModel.use_memcache = DEFAULT_USE_MEMCACHE
|
130
|
+
end
|
131
|
+
|
132
|
+
def teardown
|
133
|
+
CachedModel.use_local_cache = DEFAULT_USE_LOCAL_CACHE
|
134
|
+
CachedModel.use_memcache = DEFAULT_USE_MEMCACHE
|
110
135
|
end
|
111
136
|
|
112
137
|
def test_class_cache_delete
|
138
|
+
CachedModel.use_local_cache = true
|
139
|
+
CachedModel.use_memcache = true
|
113
140
|
util_set
|
114
141
|
|
115
142
|
CachedModel.cache_delete @model.class, @model.id
|
@@ -118,7 +145,53 @@ class TestCachedModel < Test::Unit::TestCase
|
|
118
145
|
assert_equal true, Cache.cache.empty?
|
119
146
|
end
|
120
147
|
|
148
|
+
def test_class_cache_delete_without_local_cache
|
149
|
+
CachedModel.use_local_cache = false
|
150
|
+
CachedModel.use_memcache = true
|
151
|
+
util_set
|
152
|
+
|
153
|
+
CachedModel.cache_delete @model.class, @model.id
|
154
|
+
|
155
|
+
assert_equal false, CachedModel.cache_local.empty?
|
156
|
+
assert_equal true, Cache.cache.empty?
|
157
|
+
end
|
158
|
+
|
159
|
+
def test_class_cache_delete_without_memcache
|
160
|
+
CachedModel.use_local_cache = true
|
161
|
+
CachedModel.use_memcache = false
|
162
|
+
util_set
|
163
|
+
|
164
|
+
CachedModel.cache_delete @model.class, @model.id
|
165
|
+
|
166
|
+
assert_equal true, CachedModel.cache_local.empty?
|
167
|
+
assert_equal false, Cache.cache.empty?
|
168
|
+
end
|
169
|
+
|
121
170
|
def test_class_cache_reset
|
171
|
+
CachedModel.use_local_cache = true
|
172
|
+
CachedModel.use_memcache = true
|
173
|
+
util_set
|
174
|
+
|
175
|
+
CachedModel.cache_reset
|
176
|
+
|
177
|
+
assert_equal true, CachedModel.cache_local.empty?
|
178
|
+
assert_equal false, Cache.cache.empty?
|
179
|
+
end
|
180
|
+
|
181
|
+
def test_class_cache_reset_without_local_cache
|
182
|
+
CachedModel.use_local_cache = false
|
183
|
+
CachedModel.use_memcache = true
|
184
|
+
util_set
|
185
|
+
|
186
|
+
CachedModel.cache_reset
|
187
|
+
|
188
|
+
assert_equal false, CachedModel.cache_local.empty?
|
189
|
+
assert_equal false, Cache.cache.empty?
|
190
|
+
end
|
191
|
+
|
192
|
+
def test_class_cache_reset_without_memcache
|
193
|
+
CachedModel.use_local_cache = true
|
194
|
+
CachedModel.use_memcache = false
|
122
195
|
util_set
|
123
196
|
|
124
197
|
CachedModel.cache_reset
|
@@ -133,45 +206,78 @@ class TestCachedModel < Test::Unit::TestCase
|
|
133
206
|
end
|
134
207
|
|
135
208
|
def test_class_find_complex
|
209
|
+
CachedModel.use_local_cache = true
|
210
|
+
CachedModel.use_memcache = true
|
211
|
+
|
136
212
|
record = Concrete.find(1, :order => 'lock_version')
|
213
|
+
|
137
214
|
assert_equal @model.id + 1, record.id
|
138
215
|
|
139
216
|
assert_equal record, CachedModel.cache_local[record.cache_key_local]
|
140
217
|
assert_equal record, Cache.cache[record.cache_key_memcache]
|
141
218
|
end
|
142
219
|
|
220
|
+
def test_class_find_complex_without_local_cache
|
221
|
+
CachedModel.use_local_cache = false
|
222
|
+
CachedModel.use_memcache = true
|
223
|
+
|
224
|
+
record = Concrete.find(1, :order => 'lock_version')
|
225
|
+
|
226
|
+
assert_equal @model.id + 1, record.id
|
227
|
+
|
228
|
+
assert_equal nil, CachedModel.cache_local[record.cache_key_local]
|
229
|
+
assert_equal record, Cache.cache[record.cache_key_memcache]
|
230
|
+
end
|
231
|
+
|
232
|
+
def test_class_find_complex_without_memcache
|
233
|
+
CachedModel.use_local_cache = true
|
234
|
+
CachedModel.use_memcache = false
|
235
|
+
|
236
|
+
record = Concrete.find(1, :order => 'lock_version')
|
237
|
+
|
238
|
+
assert_equal @model.id + 1, record.id
|
239
|
+
|
240
|
+
assert_equal record, CachedModel.cache_local[record.cache_key_local]
|
241
|
+
assert_equal nil, Cache.cache[record.cache_key_memcache]
|
242
|
+
end
|
243
|
+
|
143
244
|
def test_class_find_in_local_cache
|
245
|
+
CachedModel.use_local_cache = true
|
144
246
|
util_set
|
145
247
|
|
146
248
|
record = Concrete.find(1, :order => 'lock_version')
|
147
249
|
assert_equal @model.id + 1, record.id
|
148
250
|
|
149
251
|
assert_equal record, CachedModel.cache_local[record.cache_key_local]
|
150
|
-
assert_equal record, Cache.cache[record.cache_key_memcache]
|
151
252
|
end
|
152
253
|
|
153
254
|
def test_class_find_in_memcache
|
255
|
+
CachedModel.use_local_cache = true
|
256
|
+
CachedModel.use_memcache = true
|
154
257
|
util_set
|
155
258
|
CachedModel.cache_reset
|
156
259
|
|
157
260
|
record = Concrete.find @model.id
|
261
|
+
|
158
262
|
assert_equal @model, record
|
159
263
|
|
160
264
|
assert_equal record, CachedModel.cache_local[record.cache_key_local]
|
161
265
|
end
|
162
266
|
|
163
267
|
def test_class_find_multiple
|
268
|
+
CachedModel.use_local_cache = true
|
164
269
|
ids = [@model.id + 1, @model.id + 2, @model.id + 3]
|
165
270
|
records = Concrete.find(*ids)
|
166
271
|
assert_equal ids, records.map { |r| r.id }
|
167
272
|
|
168
|
-
assert_equal ids.map { |i| "#{@model.class}:#{i}" },
|
169
|
-
CachedModel.cache_local.keys
|
170
|
-
assert_equal ids.map { |i| "
|
171
|
-
Cache.cache.keys
|
273
|
+
assert_equal ids.map { |i| "#{@model.class}:#{i}" }.sort,
|
274
|
+
CachedModel.cache_local.keys.sort
|
275
|
+
assert_equal ids.map { |i| "active_record:#{@model.class}:#{i}" }.sort,
|
276
|
+
Cache.cache.keys.sort
|
172
277
|
end
|
173
278
|
|
174
279
|
def test_class_find_not_cached
|
280
|
+
CachedModel.use_local_cache = true
|
175
281
|
record = Concrete.find @model.id + 1
|
176
282
|
assert_equal @model.id + 1, record.id
|
177
283
|
|
@@ -180,6 +286,7 @@ class TestCachedModel < Test::Unit::TestCase
|
|
180
286
|
end
|
181
287
|
|
182
288
|
def test_class_find_by_sql
|
289
|
+
CachedModel.use_local_cache = true
|
183
290
|
q = "SELECT * FROM concrete WHERE (concrete.id = #{@model.id + 1}) LIMIT 1"
|
184
291
|
record = Concrete.find_by_sql(q).first
|
185
292
|
assert_equal @model.id + 1, record.id
|
@@ -207,7 +314,28 @@ class TestCachedModel < Test::Unit::TestCase
|
|
207
314
|
CachedModel.class_name_of_active_record_descendant(STILameness)
|
208
315
|
end
|
209
316
|
|
317
|
+
def test_class_ttl
|
318
|
+
assert_equal 900, CachedModel.ttl
|
319
|
+
CachedModel.ttl = 800
|
320
|
+
assert_equal 800, CachedModel.ttl
|
321
|
+
end
|
322
|
+
|
323
|
+
def test_class_use_local_cache_eh
|
324
|
+
CachedModel.use_local_cache = true
|
325
|
+
assert_equal true, CachedModel.use_local_cache?
|
326
|
+
CachedModel.use_local_cache = false
|
327
|
+
assert_equal false, CachedModel.use_local_cache?
|
328
|
+
end
|
329
|
+
|
330
|
+
def test_class_use_memcache_eh
|
331
|
+
CachedModel.use_memcache = true
|
332
|
+
assert_equal true, CachedModel.use_memcache?
|
333
|
+
CachedModel.use_memcache = false
|
334
|
+
assert_equal false, CachedModel.use_memcache?
|
335
|
+
end
|
336
|
+
|
210
337
|
def test_cache_delete
|
338
|
+
CachedModel.use_local_cache = true
|
211
339
|
util_set
|
212
340
|
|
213
341
|
@model.cache_delete
|
@@ -221,7 +349,7 @@ class TestCachedModel < Test::Unit::TestCase
|
|
221
349
|
end
|
222
350
|
|
223
351
|
def test_cache_key_memcache
|
224
|
-
assert_equal "
|
352
|
+
assert_equal "active_record:#{@model.class}:#{@model.id}",
|
225
353
|
@model.cache_key_memcache
|
226
354
|
end
|
227
355
|
|
@@ -230,16 +358,48 @@ class TestCachedModel < Test::Unit::TestCase
|
|
230
358
|
end
|
231
359
|
|
232
360
|
def test_cache_store
|
361
|
+
CachedModel.use_local_cache = true
|
362
|
+
CachedModel.use_memcache = true
|
363
|
+
|
233
364
|
@model.cache_store
|
365
|
+
|
234
366
|
assert_equal false, CachedModel.cache_local.empty?
|
235
367
|
assert_equal false, Cache.cache.empty?
|
236
368
|
|
237
369
|
assert_equal @model, CachedModel.cache_local[@model.cache_key_local]
|
238
370
|
assert_equal @model, Cache.cache[@model.cache_key_memcache]
|
239
|
-
assert_equal CachedModel
|
371
|
+
assert_equal CachedModel.ttl, Cache.ttl[@model.cache_key_memcache]
|
372
|
+
end
|
373
|
+
|
374
|
+
def test_cache_store_without_local_cache
|
375
|
+
CachedModel.use_local_cache = false
|
376
|
+
CachedModel.use_memcache = true
|
377
|
+
|
378
|
+
@model.cache_store
|
379
|
+
|
380
|
+
assert_equal true, CachedModel.cache_local.empty?
|
381
|
+
assert_equal false, Cache.cache.empty?
|
382
|
+
|
383
|
+
assert_equal nil, CachedModel.cache_local[@model.cache_key_local]
|
384
|
+
assert_equal @model, Cache.cache[@model.cache_key_memcache]
|
385
|
+
assert_equal CachedModel.ttl, Cache.ttl[@model.cache_key_memcache]
|
386
|
+
end
|
387
|
+
|
388
|
+
def test_cache_store_without_memcache
|
389
|
+
CachedModel.use_local_cache = true
|
390
|
+
CachedModel.use_memcache = false
|
391
|
+
|
392
|
+
@model.cache_store
|
393
|
+
|
394
|
+
assert_equal false, CachedModel.cache_local.empty?
|
395
|
+
assert_equal true, Cache.cache.empty?
|
396
|
+
|
397
|
+
assert_equal @model, CachedModel.cache_local[@model.cache_key_local]
|
398
|
+
assert_equal nil, Cache.cache[@model.cache_key_memcache]
|
240
399
|
end
|
241
400
|
|
242
401
|
def test_cache_store_with_attributes
|
402
|
+
CachedModel.use_local_cache = true
|
243
403
|
@model.attributes[:extra] = 'extra'
|
244
404
|
@model.cache_store
|
245
405
|
assert_equal false, CachedModel.cache_local.empty?
|
@@ -249,7 +409,7 @@ class TestCachedModel < Test::Unit::TestCase
|
|
249
409
|
mem_model = Cache.cache[@model.cache_key_memcache]
|
250
410
|
assert_equal @model, local_model
|
251
411
|
assert_equal @model, mem_model
|
252
|
-
assert_equal CachedModel
|
412
|
+
assert_equal CachedModel.ttl, Cache.ttl[@model.cache_key_memcache]
|
253
413
|
|
254
414
|
expected = {:data => 'data'}
|
255
415
|
|
@@ -258,6 +418,7 @@ class TestCachedModel < Test::Unit::TestCase
|
|
258
418
|
end
|
259
419
|
|
260
420
|
def test_destroy
|
421
|
+
CachedModel.use_local_cache = true
|
261
422
|
util_set
|
262
423
|
|
263
424
|
@model.destroy
|
@@ -298,7 +459,7 @@ class TestCachedModel < Test::Unit::TestCase
|
|
298
459
|
def util_set(klass = @model.class, id = @model.id, data = @model)
|
299
460
|
key = "#{klass}:#{id}"
|
300
461
|
CachedModel.cache_local[key] = data
|
301
|
-
Cache.cache["
|
462
|
+
Cache.cache["active_record:#{key}"] = data
|
302
463
|
end
|
303
464
|
|
304
465
|
end
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11.6
|
|
3
3
|
specification_version: 1
|
4
4
|
name: cached_model
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 1.0
|
7
|
-
date: 2006-
|
6
|
+
version: 1.1.0
|
7
|
+
date: 2006-02-19 00:00:00 -08:00
|
8
8
|
summary: An ActiveRecord::Base model that caches records
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -25,6 +25,7 @@ required_ruby_version: !ruby/object:Gem::Version::Requirement
|
|
25
25
|
platform: ruby
|
26
26
|
signing_key:
|
27
27
|
cert_chain:
|
28
|
+
post_install_message:
|
28
29
|
authors:
|
29
30
|
- Robert Cottrell, Eric Hodel
|
30
31
|
files:
|