record-cache 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/lib/record_cache.rb +2 -1
- data/lib/record_cache/base.rb +63 -22
- data/lib/record_cache/datastore/active_record.rb +5 -3
- data/lib/record_cache/datastore/active_record_30.rb +95 -38
- data/lib/record_cache/datastore/active_record_31.rb +157 -54
- data/lib/record_cache/datastore/active_record_32.rb +444 -0
- data/lib/record_cache/dispatcher.rb +47 -47
- data/lib/record_cache/multi_read.rb +14 -1
- data/lib/record_cache/query.rb +36 -25
- data/lib/record_cache/statistics.rb +5 -5
- data/lib/record_cache/strategy/base.rb +49 -19
- data/lib/record_cache/strategy/full_table_cache.rb +81 -0
- data/lib/record_cache/strategy/index_cache.rb +38 -36
- data/lib/record_cache/strategy/unique_index_cache.rb +130 -0
- data/lib/record_cache/strategy/util.rb +12 -12
- data/lib/record_cache/test/resettable_version_store.rb +2 -9
- data/lib/record_cache/version.rb +1 -1
- data/lib/record_cache/version_store.rb +23 -16
- data/spec/db/schema.rb +12 -0
- data/spec/db/seeds.rb +10 -0
- data/spec/lib/active_record/visitor_spec.rb +22 -0
- data/spec/lib/base_spec.rb +21 -0
- data/spec/lib/dispatcher_spec.rb +24 -46
- data/spec/lib/multi_read_spec.rb +6 -6
- data/spec/lib/query_spec.rb +43 -43
- data/spec/lib/statistics_spec.rb +28 -28
- data/spec/lib/strategy/base_spec.rb +98 -87
- data/spec/lib/strategy/full_table_cache_spec.rb +68 -0
- data/spec/lib/strategy/index_cache_spec.rb +112 -69
- data/spec/lib/strategy/query_cache_spec.rb +83 -0
- data/spec/lib/strategy/unique_index_on_id_cache_spec.rb +317 -0
- data/spec/lib/strategy/unique_index_on_string_cache_spec.rb +168 -0
- data/spec/lib/strategy/util_spec.rb +67 -49
- data/spec/lib/version_store_spec.rb +22 -41
- data/spec/models/address.rb +9 -0
- data/spec/models/apple.rb +1 -1
- data/spec/models/banana.rb +21 -2
- data/spec/models/language.rb +5 -0
- data/spec/models/person.rb +1 -1
- data/spec/models/store.rb +2 -1
- data/spec/spec_helper.rb +7 -4
- data/spec/support/after_commit.rb +2 -0
- data/spec/support/matchers/hit_cache_matcher.rb +10 -6
- data/spec/support/matchers/log.rb +45 -0
- data/spec/support/matchers/miss_cache_matcher.rb +10 -6
- data/spec/support/matchers/use_cache_matcher.rb +10 -6
- metadata +156 -161
- data/lib/record_cache/strategy/id_cache.rb +0 -93
- data/lib/record_cache/strategy/request_cache.rb +0 -49
- data/spec/lib/strategy/id_cache_spec.rb +0 -168
- data/spec/lib/strategy/request_cache_spec.rb +0 -85
@@ -1,93 +0,0 @@
|
|
1
|
-
module RecordCache
|
2
|
-
module Strategy
|
3
|
-
class IdCache < Base
|
4
|
-
|
5
|
-
# Can the cache retrieve the records based on this query?
|
6
|
-
def cacheable?(query)
|
7
|
-
ids = query.where_ids(:id)
|
8
|
-
ids && (query.limit.nil? || (query.limit == 1 && ids.size == 1))
|
9
|
-
end
|
10
|
-
|
11
|
-
# Update the version store and the record store
|
12
|
-
def record_change(record, action)
|
13
|
-
key = cache_key(record.id)
|
14
|
-
if action == :destroy
|
15
|
-
version_store.delete(key)
|
16
|
-
else
|
17
|
-
# update the version store and add the record to the cache
|
18
|
-
new_version = version_store.increment(key)
|
19
|
-
record_store.write(versioned_key(key, new_version), Util.serialize(record))
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
# Handle invalidation call
|
24
|
-
def invalidate(id)
|
25
|
-
version_store.delete(cache_key(id))
|
26
|
-
end
|
27
|
-
|
28
|
-
protected
|
29
|
-
|
30
|
-
# retrieve the record(s) with the given id(s) as an array
|
31
|
-
def fetch_records(query)
|
32
|
-
ids = query.where_ids(:id)
|
33
|
-
query.wheres.delete(:id) # make sure CacheCase.filter! does not see this where anymore
|
34
|
-
id_to_key_map = ids.inject({}){|h,id| h[id] = cache_key(id); h }
|
35
|
-
# retrieve the current version of the records
|
36
|
-
current_versions = version_store.current_multi(id_to_key_map)
|
37
|
-
# get the keys for the records for which a current version was found
|
38
|
-
id_to_version_key_map = Hash[id_to_key_map.map{ |id, key| current_versions[id] ? [id, versioned_key(key, current_versions[id])] : nil }]
|
39
|
-
# retrieve the records from the cache
|
40
|
-
records = id_to_version_key_map.size > 0 ? from_cache(id_to_version_key_map) : []
|
41
|
-
# query the records with missing ids
|
42
|
-
id_to_key_map.except!(*records.map(&:id))
|
43
|
-
# logging (only in debug mode!) and statistics
|
44
|
-
log_id_cache_hit(ids, id_to_key_map.keys) if RecordCache::Base.logger.debug?
|
45
|
-
statistics.add(ids.size, records.size) if statistics.active?
|
46
|
-
# retrieve records from DB in case there are some missing ids
|
47
|
-
records += from_db(id_to_key_map, id_to_version_key_map) if id_to_key_map.size > 0
|
48
|
-
# return the array
|
49
|
-
records
|
50
|
-
end
|
51
|
-
|
52
|
-
private
|
53
|
-
|
54
|
-
# ---------------------------- Querying ------------------------------------
|
55
|
-
|
56
|
-
# retrieve the records from the cache with the given keys
|
57
|
-
def from_cache(id_to_versioned_key_map)
|
58
|
-
records = record_store.read_multi(*(id_to_versioned_key_map.values)).values.compact
|
59
|
-
records.map{ |record| Util.deserialize(record) }
|
60
|
-
end
|
61
|
-
|
62
|
-
# retrieve the records with the given ids from the database
|
63
|
-
def from_db(id_to_key_map, id_to_version_key_map)
|
64
|
-
RecordCache::Base.without_record_cache do
|
65
|
-
# retrieve the records from the database
|
66
|
-
records = @base.where(:id => id_to_key_map.keys).to_a
|
67
|
-
records.each do |record|
|
68
|
-
versioned_key = id_to_version_key_map[record.id]
|
69
|
-
unless versioned_key
|
70
|
-
# renew the key in the version store in case it was missing
|
71
|
-
key = id_to_key_map[record.id]
|
72
|
-
versioned_key = versioned_key(key, version_store.renew(key))
|
73
|
-
end
|
74
|
-
# store the record based on the versioned key
|
75
|
-
record_store.write(versioned_key, Util.serialize(record))
|
76
|
-
end
|
77
|
-
records
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
# ------------------------- Utility methods ----------------------------
|
82
|
-
|
83
|
-
# log cache hit/miss to debug log
|
84
|
-
def log_id_cache_hit(ids, missing_ids)
|
85
|
-
hit = missing_ids.empty? ? "hit" : ids.size == missing_ids.size ? "miss" : "partial hit"
|
86
|
-
missing = missing_ids.empty? || ids.size == missing_ids.size ? "" : ": missing #{missing_ids.inspect}"
|
87
|
-
msg = "IdCache #{hit} for ids #{ids.size == 1 ? ids.first : ids.inspect}#{missing}"
|
88
|
-
RecordCache::Base.logger.debug(msg)
|
89
|
-
end
|
90
|
-
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
@@ -1,49 +0,0 @@
|
|
1
|
-
# Remembers the queries performed during a single Request.
|
2
|
-
# If the same query is requested again the result is provided straight from local memory.
|
3
|
-
#
|
4
|
-
# Records are invalidated per model-klass, when any record is created, updated or destroyed.
|
5
|
-
module RecordCache
|
6
|
-
module Strategy
|
7
|
-
|
8
|
-
class RequestCache < Base
|
9
|
-
@@request_store = {}
|
10
|
-
|
11
|
-
# call before each request: in application_controller.rb
|
12
|
-
# before_filter { |c| RecordCache::Strategy::RequestCache.clear }
|
13
|
-
def self.clear
|
14
|
-
@@request_store.clear
|
15
|
-
end
|
16
|
-
|
17
|
-
# Handle record change
|
18
|
-
def record_change(record, action)
|
19
|
-
@@request_store.delete(@base.name)
|
20
|
-
end
|
21
|
-
|
22
|
-
# Handle invalidation call
|
23
|
-
def invalidate(value)
|
24
|
-
@@request_store.delete(@base.name)
|
25
|
-
end
|
26
|
-
|
27
|
-
# return the records from the request cache, execute block in case
|
28
|
-
# this is the first time this query is performed during this request
|
29
|
-
def fetch(query, &block)
|
30
|
-
klass_store = (@@request_store[@base.name] ||= {})
|
31
|
-
key = query.cache_key
|
32
|
-
# logging (only in debug mode!) and statistics
|
33
|
-
log_cache_hit(key, klass_store.key?(key)) if RecordCache::Base.logger.debug?
|
34
|
-
statistics.add(1, klass_store.key?(key) ? 1 : 0) if statistics.active?
|
35
|
-
klass_store[key] ||= yield
|
36
|
-
end
|
37
|
-
|
38
|
-
private
|
39
|
-
|
40
|
-
# ------------------------- Utility methods ----------------------------
|
41
|
-
|
42
|
-
# log cache hit/miss to debug log
|
43
|
-
def log_cache_hit(key, hit)
|
44
|
-
RecordCache::Base.logger.debug("RequestCache #{hit ? 'hit' : 'miss'} for #{key}")
|
45
|
-
end
|
46
|
-
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
@@ -1,168 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe RecordCache::Strategy::IdCache do
|
4
|
-
|
5
|
-
it "should retrieve an Apple from the cache" do
|
6
|
-
lambda{ Apple.find(1) }.should miss_cache(Apple).on(:id).times(1)
|
7
|
-
lambda{ Apple.find(1) }.should hit_cache(Apple).on(:id).times(1)
|
8
|
-
end
|
9
|
-
|
10
|
-
it "should retrieve cloned records" do
|
11
|
-
@apple_1a = Apple.find(1)
|
12
|
-
@apple_1b = Apple.find(1)
|
13
|
-
@apple_1a.should == @apple_1b
|
14
|
-
@apple_1a.object_id.should_not == @apple_1b.object_id
|
15
|
-
end
|
16
|
-
|
17
|
-
context "logging" do
|
18
|
-
before(:each) do
|
19
|
-
Apple.find(1)
|
20
|
-
end
|
21
|
-
|
22
|
-
it "should write full hits to the debug log" do
|
23
|
-
mock(RecordCache::Base.logger).debug(/IdCache hit for ids 1|^(?!IdCache)/).times(any_times)
|
24
|
-
Apple.find(1)
|
25
|
-
end
|
26
|
-
|
27
|
-
it "should write full miss to the debug log" do
|
28
|
-
mock(RecordCache::Base.logger).debug(/IdCache miss for ids 2|^(?!IdCache)/).times(any_times)
|
29
|
-
Apple.find(2)
|
30
|
-
end
|
31
|
-
|
32
|
-
it "should write partial hits to the debug log" do
|
33
|
-
mock(RecordCache::Base.logger).debug(/IdCache partial hit for ids \[1, 2\]: missing \[2\]|^(?!IdCache)/).times(any_times)
|
34
|
-
Apple.where(:id => [1,2]).all
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
context "cacheable?" do
|
39
|
-
before(:each) do
|
40
|
-
# fill cache
|
41
|
-
@apple1 = Apple.find(1)
|
42
|
-
@apple2 = Apple.find(2)
|
43
|
-
end
|
44
|
-
|
45
|
-
it "should use the cache when a single id is requested" do
|
46
|
-
lambda{ Apple.where(:id => 1).all }.should hit_cache(Apple).on(:id).times(1)
|
47
|
-
end
|
48
|
-
|
49
|
-
it "should use the cache when a multiple ids are requested" do
|
50
|
-
lambda{ Apple.where(:id => [1, 2]).all }.should hit_cache(Apple).on(:id).times(2)
|
51
|
-
end
|
52
|
-
|
53
|
-
it "should use the cache when a single id is requested and the limit is 1" do
|
54
|
-
lambda{ Apple.where(:id => 1).limit(1).all }.should hit_cache(Apple).on(:id).times(1)
|
55
|
-
end
|
56
|
-
|
57
|
-
it "should not use the cache when a single id is requested and the limit is > 1" do
|
58
|
-
lambda{ Apple.where(:id => 1).limit(2).all }.should_not use_cache(Apple).on(:id)
|
59
|
-
end
|
60
|
-
|
61
|
-
it "should not use the cache when multiple ids are requested and the limit is 1" do
|
62
|
-
lambda{ Apple.where(:id => [1, 2]).limit(1).all }.should_not use_cache(Apple).on(:id)
|
63
|
-
end
|
64
|
-
|
65
|
-
it "should use the cache when a single id is requested together with other where clauses" do
|
66
|
-
lambda{ Apple.where(:id => 1).where(:name => "Adams Apple x").all }.should hit_cache(Apple).on(:id).times(1)
|
67
|
-
end
|
68
|
-
|
69
|
-
it "should use the cache when a multiple ids are requested together with other where clauses" do
|
70
|
-
lambda{ Apple.where(:id => [1,2]).where(:name => "Adams Apple x").all }.should hit_cache(Apple).on(:id).times(2)
|
71
|
-
end
|
72
|
-
|
73
|
-
it "should use the cache when a single id is requested together with (simple) sort clauses" do
|
74
|
-
lambda{ Apple.where(:id => 1).order("name ASC").all }.should hit_cache(Apple).on(:id).times(1)
|
75
|
-
end
|
76
|
-
|
77
|
-
it "should use the cache when a multiple ids are requested together with (simple) sort clauses" do
|
78
|
-
lambda{ Apple.where(:id => [1,2]).order("name ASC").all }.should hit_cache(Apple).on(:id).times(2)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
context "record_change" do
|
83
|
-
before(:each) do
|
84
|
-
# fill cache
|
85
|
-
@apple1 = Apple.find(1)
|
86
|
-
@apple2 = Apple.find(2)
|
87
|
-
end
|
88
|
-
|
89
|
-
it "should invalidate destroyed records" do
|
90
|
-
lambda{ Apple.where(:id => 1).all }.should hit_cache(Apple).on(:id).times(1)
|
91
|
-
@apple1.destroy
|
92
|
-
lambda{ @apples = Apple.where(:id => 1).all }.should miss_cache(Apple).on(:id).times(1)
|
93
|
-
@apples.should == []
|
94
|
-
# try again, to make sure the "missing record" is not cached
|
95
|
-
lambda{ Apple.where(:id => 1).all }.should miss_cache(Apple).on(:id).times(1)
|
96
|
-
end
|
97
|
-
|
98
|
-
it "should add updated records directly to the cache" do
|
99
|
-
@apple1.name = "Applejuice"
|
100
|
-
@apple1.save!
|
101
|
-
lambda{ @apple = Apple.find(1) }.should hit_cache(Apple).on(:id).times(1)
|
102
|
-
@apple.name.should == "Applejuice"
|
103
|
-
end
|
104
|
-
|
105
|
-
it "should add created records directly to the cache" do
|
106
|
-
@new_apple = Apple.create!(:name => "Fresh Apple", :store_id => 1)
|
107
|
-
lambda{ @apple = Apple.find(@new_apple.id) }.should hit_cache(Apple).on(:id).times(1)
|
108
|
-
@apple.name.should == "Fresh Apple"
|
109
|
-
end
|
110
|
-
|
111
|
-
it "should add updated records to the cache, also when multiple ids are queried" do
|
112
|
-
@apple1.name = "Applejuice"
|
113
|
-
@apple1.save!
|
114
|
-
lambda{ @apples = Apple.where(:id => [1, 2]).order('id ASC').all }.should hit_cache(Apple).on(:id).times(2)
|
115
|
-
@apples.map(&:name).should == ["Applejuice", "Adams Apple 2"]
|
116
|
-
end
|
117
|
-
|
118
|
-
end
|
119
|
-
|
120
|
-
context "invalidate" do
|
121
|
-
before(:each) do
|
122
|
-
@apple1 = Apple.find(1)
|
123
|
-
@apple2 = Apple.find(2)
|
124
|
-
end
|
125
|
-
|
126
|
-
it "should invalidate single records" do
|
127
|
-
Apple.record_cache[:id].invalidate(1)
|
128
|
-
lambda{ Apple.find(1) }.should miss_cache(Apple).on(:id).times(1)
|
129
|
-
end
|
130
|
-
|
131
|
-
it "should only miss the cache for the invalidated record when multiple ids are queried" do
|
132
|
-
# miss on 1
|
133
|
-
Apple.record_cache[:id].invalidate(1)
|
134
|
-
lambda{ Apple.where(:id => [1, 2]).all }.should miss_cache(Apple).on(:id).times(1)
|
135
|
-
# hit on 2
|
136
|
-
Apple.record_cache[:id].invalidate(1)
|
137
|
-
lambda{ Apple.where(:id => [1, 2]).all }.should hit_cache(Apple).on(:id).times(1)
|
138
|
-
# nothing invalidated, both hit
|
139
|
-
lambda{ Apple.where(:id => [1, 2]).all }.should hit_cache(Apple).on(:id).times(2)
|
140
|
-
end
|
141
|
-
|
142
|
-
it "should invalidate records when using update_all" do
|
143
|
-
Apple.where(:id => [3,4,5]).all # fill id cache on all Adam Store apples
|
144
|
-
lambda{ @apples = Apple.where(:id => [1, 2, 3, 4, 5]).order('id ASC').all }.should hit_cache(Apple).on(:id).times(5)
|
145
|
-
@apples.map(&:name).should == ["Adams Apple 1", "Adams Apple 2", "Adams Apple 3", "Adams Apple 4", "Adams Apple 5"]
|
146
|
-
# update 3 of the 5 apples in the Adam Store
|
147
|
-
Apple.where(:id => [1,2,3]).update_all(:name => "Uniform Apple")
|
148
|
-
lambda{ @apples = Apple.where(:id => [1, 2, 3, 4, 5]).order('id ASC').all }.should hit_cache(Apple).on(:id).times(2)
|
149
|
-
@apples.map(&:name).should == ["Uniform Apple", "Uniform Apple", "Uniform Apple", "Adams Apple 4", "Adams Apple 5"]
|
150
|
-
end
|
151
|
-
|
152
|
-
it "should invalidate reflection indexes when a has_many relation is updated" do
|
153
|
-
# assign different apples to store 2
|
154
|
-
lambda{ Apple.where(:store_id => 1).all }.should hit_cache(Apple).on(:id).times(2)
|
155
|
-
store2_apple_ids = Apple.where(:store_id => 2).map(&:id)
|
156
|
-
store1 = Store.find(1)
|
157
|
-
store1.apple_ids = store2_apple_ids
|
158
|
-
store1.save!
|
159
|
-
# the apples that used to belong to store 2 are now in store 1 (incremental update)
|
160
|
-
lambda{ @apple1 = Apple.find(store2_apple_ids.first) }.should hit_cache(Apple).on(:id).times(1)
|
161
|
-
@apple1.store_id.should == 1
|
162
|
-
# the apples that used to belong to store 1 are now homeless (cache invalidated)
|
163
|
-
lambda{ @homeless_apple = Apple.find(1) }.should miss_cache(Apple).on(:id).times(1)
|
164
|
-
@homeless_apple.store_id.should == nil
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
end
|
@@ -1,85 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe RecordCache::Strategy::RequestCache do
|
4
|
-
|
5
|
-
it "should retrieve a record from the Request Cache" do
|
6
|
-
lambda{ Store.find(1) }.should miss_cache(Store)
|
7
|
-
lambda{ Store.find(1) }.should hit_cache(Store).on(:request_cache).times(1)
|
8
|
-
end
|
9
|
-
|
10
|
-
it "should retrieve the same record when the same query is used" do
|
11
|
-
@store_1 = Store.find(1)
|
12
|
-
@store_2 = Store.find(1)
|
13
|
-
@store_1.should == @store_2
|
14
|
-
@store_1.object_id.should == @store_2.object_id
|
15
|
-
end
|
16
|
-
|
17
|
-
context "logging" do
|
18
|
-
before(:each) do
|
19
|
-
Store.find(1)
|
20
|
-
end
|
21
|
-
|
22
|
-
it "should write hit to the debug log" do
|
23
|
-
mock(RecordCache::Base.logger).debug(/RequestCache hit for id=1\.L1|^(?!RequestCache)/).times(any_times)
|
24
|
-
Store.find(1)
|
25
|
-
end
|
26
|
-
|
27
|
-
it "should write miss to the debug log" do
|
28
|
-
mock(RecordCache::Base.logger).debug(/^RequestCache miss for id=2.L1|^(?!RequestCache)/).times(any_times)
|
29
|
-
Store.find(2)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
context "record_change" do
|
34
|
-
before(:each) do
|
35
|
-
# cache query in request cache
|
36
|
-
@store1 = Store.find(1)
|
37
|
-
@store2 = Store.find(2)
|
38
|
-
end
|
39
|
-
|
40
|
-
it "should remove all records from the cache for a specific model when one record is destroyed" do
|
41
|
-
lambda{ Store.find(1) }.should hit_cache(Store).on(:request_cache).times(1)
|
42
|
-
lambda{ Store.find(2) }.should hit_cache(Store).on(:request_cache).times(1)
|
43
|
-
@store1.destroy
|
44
|
-
lambda{ Store.find(2) }.should miss_cache(Store).on(:request_cache).times(1)
|
45
|
-
end
|
46
|
-
|
47
|
-
it "should remove all records from the cache for a specific model when one record is updated" do
|
48
|
-
lambda{ Store.find(1) }.should hit_cache(Store).on(:request_cache).times(1)
|
49
|
-
lambda{ Store.find(2) }.should hit_cache(Store).on(:request_cache).times(1)
|
50
|
-
@store1.name = "Store E"
|
51
|
-
@store1.save!
|
52
|
-
lambda{ Store.find(1) }.should miss_cache(Store).on(:request_cache).times(1)
|
53
|
-
lambda{ Store.find(2) }.should miss_cache(Store).on(:request_cache).times(1)
|
54
|
-
end
|
55
|
-
|
56
|
-
it "should remove all records from the cache for a specific model when one record is created" do
|
57
|
-
lambda{ Store.find(1) }.should hit_cache(Store).on(:request_cache).times(1)
|
58
|
-
lambda{ Store.find(2) }.should hit_cache(Store).on(:request_cache).times(1)
|
59
|
-
Store.create!(:name => "New Apple Store")
|
60
|
-
lambda{ Store.find(1) }.should miss_cache(Store).on(:request_cache).times(1)
|
61
|
-
lambda{ Store.find(2) }.should miss_cache(Store).on(:request_cache).times(1)
|
62
|
-
end
|
63
|
-
|
64
|
-
end
|
65
|
-
|
66
|
-
context "invalidate" do
|
67
|
-
before(:each) do
|
68
|
-
# cache query in request cache
|
69
|
-
@store1 = Store.find(1)
|
70
|
-
@store2 = Store.find(2)
|
71
|
-
end
|
72
|
-
|
73
|
-
it "should remove all records from the cache when clear is explicitly called" do
|
74
|
-
lambda{ Store.find(1) }.should hit_cache(Store).on(:request_cache).times(1)
|
75
|
-
RecordCache::Strategy::RequestCache.clear
|
76
|
-
lambda{ Store.find(1) }.should miss_cache(Store).on(:request_cache).times(1)
|
77
|
-
end
|
78
|
-
|
79
|
-
it "should remove all records from the cache when invalidate is called" do
|
80
|
-
lambda{ Store.find(1) }.should hit_cache(Store).on(:request_cache).times(1)
|
81
|
-
Store.record_cache.invalidate(:request_cache, @store2)
|
82
|
-
lambda{ Store.find(1) }.should miss_cache(Store).on(:request_cache).times(1)
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|