record-cache 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +8 -8
  2. data/lib/record_cache/base.rb +4 -4
  3. data/lib/record_cache/datastore/active_record_30.rb +1 -1
  4. data/lib/record_cache/datastore/active_record_31.rb +1 -1
  5. data/lib/record_cache/datastore/active_record_32.rb +2 -2
  6. data/lib/record_cache/datastore/active_record_40.rb +445 -0
  7. data/lib/record_cache/datastore/active_record_41.rb +446 -0
  8. data/lib/record_cache/strategy/full_table_cache.rb +1 -1
  9. data/lib/record_cache/strategy/util.rb +20 -3
  10. data/lib/record_cache/version.rb +1 -1
  11. data/spec/db/create-record-cache-db_and_user.sql +5 -0
  12. data/spec/db/database.yml +7 -0
  13. data/spec/db/schema.rb +9 -15
  14. data/spec/initializers/backward_compatibility.rb +32 -0
  15. data/spec/lib/active_record/visitor_spec.rb +1 -1
  16. data/spec/lib/base_spec.rb +2 -2
  17. data/spec/lib/dispatcher_spec.rb +1 -1
  18. data/spec/lib/multi_read_spec.rb +1 -1
  19. data/spec/lib/query_spec.rb +1 -1
  20. data/spec/lib/statistics_spec.rb +1 -1
  21. data/spec/lib/strategy/base_spec.rb +39 -39
  22. data/spec/lib/strategy/full_table_cache_spec.rb +18 -18
  23. data/spec/lib/strategy/index_cache_spec.rb +58 -52
  24. data/spec/lib/strategy/query_cache_spec.rb +1 -1
  25. data/spec/lib/strategy/unique_index_on_id_cache_spec.rb +57 -45
  26. data/spec/lib/strategy/unique_index_on_string_cache_spec.rb +47 -45
  27. data/spec/lib/strategy/util_spec.rb +49 -43
  28. data/spec/lib/version_store_spec.rb +1 -1
  29. data/spec/models/apple.rb +1 -2
  30. data/spec/spec_helper.rb +16 -7
  31. data/spec/support/matchers/hit_cache_matcher.rb +1 -1
  32. data/spec/support/matchers/miss_cache_matcher.rb +1 -1
  33. data/spec/support/matchers/use_cache_matcher.rb +1 -1
  34. metadata +63 -17
  35. data/spec/support/after_commit.rb +0 -73
@@ -1,26 +1,26 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe RecordCache::Strategy::FullTableCache do
3
+ RSpec.describe RecordCache::Strategy::FullTableCache do
4
4
 
5
5
  it "should retrieve a Language from the cache" do
6
- expect{ Language.where(:locale => 'en-US').all }.to miss_cache(Language).on(:full_table).times(1)
7
- expect{ Language.where(:locale => 'en-US').all }.to hit_cache(Language).on(:full_table).times(1)
6
+ expect { Language.where(:locale => 'en-US').load }.to miss_cache(Language).on(:full_table).times(1)
7
+ expect { Language.where(:locale => 'en-US').load }.to hit_cache(Language).on(:full_table).times(1)
8
8
  end
9
9
 
10
10
  it "should retrieve all Languages from cache" do
11
- expect{ Language.all }.to miss_cache(Language).on(:full_table).times(1)
12
- expect{ Language.all }.to hit_cache(Language).on(:full_table).times(1)
11
+ expect { Language.all.load }.to miss_cache(Language).on(:full_table).times(1)
12
+ expect { Language.all.load }.to hit_cache(Language).on(:full_table).times(1)
13
13
  expect(Language.all.map(&:locale).sort).to eq(%w(du-NL en-GB en-US hu))
14
14
  end
15
15
 
16
16
  context "logging" do
17
17
  it "should write hit to the debug log" do
18
- Language.all
19
- expect{ Language.all }.to log(:debug, "FullTableCache hit for model Language")
18
+ Language.all.load
19
+ expect { Language.all.load }.to log(:debug, "FullTableCache hit for model Language")
20
20
  end
21
21
 
22
22
  it "should write miss to the debug log" do
23
- expect{ Language.all }.to log(:debug, "FullTableCache miss for model Language")
23
+ expect{ Language.all.load }.to log(:debug, "FullTableCache miss for model Language")
24
24
  end
25
25
  end
26
26
 
@@ -29,38 +29,38 @@ describe RecordCache::Strategy::FullTableCache do
29
29
  expect(Language.record_cache[:full_table].cacheable?("any query")).to be_truthy
30
30
  end
31
31
  end
32
-
32
+
33
33
  context "record_change" do
34
34
  before(:each) do
35
- @Languages = Language.all
35
+ @Languages = Language.all.load
36
36
  end
37
37
 
38
38
  it "should invalidate the cache when a record is added" do
39
- expect{ Language.where(:locale => 'en-US').all }.to hit_cache(Language).on(:full_table).times(1)
39
+ expect{ Language.where(:locale => 'en-US').load }.to hit_cache(Language).on(:full_table).times(1)
40
40
  Language.create!(:name => 'Deutsch', :locale => 'de')
41
- expect{ Language.where(:locale => 'en-US').all }.to miss_cache(Language).on(:full_table).times(1)
41
+ expect{ Language.where(:locale => 'en-US').load }.to miss_cache(Language).on(:full_table).times(1)
42
42
  end
43
43
 
44
44
  it "should invalidate the cache when any record is deleted" do
45
- expect{ Language.where(:locale => 'en-US').all }.to hit_cache(Language).on(:full_table).times(1)
45
+ expect{ Language.where(:locale => 'en-US').load }.to hit_cache(Language).on(:full_table).times(1)
46
46
  Language.where(:locale => 'hu').first.destroy
47
- expect{ Language.where(:locale => 'en-US').all }.to miss_cache(Language).on(:full_table).times(1)
47
+ expect{ Language.where(:locale => 'en-US').load }.to miss_cache(Language).on(:full_table).times(1)
48
48
  end
49
49
 
50
50
  it "should invalidate the cache when any record is modified" do
51
- expect{ Language.where(:locale => 'en-US').all }.to hit_cache(Language).on(:full_table).times(1)
51
+ expect{ Language.where(:locale => 'en-US').load }.to hit_cache(Language).on(:full_table).times(1)
52
52
  hungarian = Language.where(:locale => 'hu').first
53
53
  hungarian.name = 'Magyar (Magyarorszag)'
54
54
  hungarian.save!
55
- expect{ Language.where(:locale => 'en-US').all }.to miss_cache(Language).on(:full_table).times(1)
55
+ expect{ Language.where(:locale => 'en-US').load }.to miss_cache(Language).on(:full_table).times(1)
56
56
  end
57
57
  end
58
-
58
+
59
59
  context "invalidate" do
60
60
 
61
61
  it "should invalidate the full cache" do
62
62
  Language.record_cache[:full_table].invalidate(-10) # any id
63
- expect{ Language.where(:locale => 'en-US').all }.to miss_cache(Language).on(:full_table).times(1)
63
+ expect{ Language.where(:locale => 'en-US').load }.to miss_cache(Language).on(:full_table).times(1)
64
64
  end
65
65
 
66
66
  end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe RecordCache::Strategy::IndexCache do
3
+ RSpec.describe RecordCache::Strategy::IndexCache do
4
4
 
5
5
  context "initialize" do
6
6
  it "should only accept index cache on DB columns" do
@@ -13,58 +13,64 @@ describe RecordCache::Strategy::IndexCache do
13
13
  end
14
14
 
15
15
  it "should use the id cache to retrieve the actual records" do
16
- expect{ @apples = Apple.where(:store_id => 1).all }.to miss_cache(Apple).on(:store_id).times(1)
17
- expect{ Apple.where(:store_id => 1).all }.to hit_cache(Apple).on(:store_id).times(1)
18
- expect{ Apple.where(:store_id => 1).all }.to hit_cache(Apple).on(:id).times(@apples.size)
16
+ expect{ @apples = Apple.where(:store_id => 1).load }.to miss_cache(Apple).on(:store_id).times(1)
17
+ expect{ Apple.where(:store_id => 1).load }.to hit_cache(Apple).on(:store_id).times(1)
18
+ expect{ Apple.where(:store_id => 1).load }.to hit_cache(Apple).on(:id).times(@apples.size)
19
+ end
20
+
21
+ it "should find cached records through relationship" do
22
+ store = Store.first
23
+ expect{ @apple = store.apples.find(3) }.to use_cache(Apple).on(:id).times(1)
24
+ expect(@apple.name).to eq("Adams Apple 3")
19
25
  end
20
26
 
21
27
  context "logging" do
22
28
  before(:each) do
23
- Apple.where(:store_id => 1).all
29
+ Apple.where(:store_id => 1).load
24
30
  end
25
31
 
26
32
  it "should write hit to the debug log" do
27
- expect{ Apple.where(:store_id => 1).all }.to log(:debug, /IndexCache hit for rc\/apl\/store_id=1v\d+: found 5 ids/)
33
+ expect{ Apple.where(:store_id => 1).load }.to log(:debug, /IndexCache hit for rc\/apl\/store_id=1v\d+: found 5 ids/)
28
34
  end
29
35
 
30
36
  it "should write miss to the debug log" do
31
- expect{ Apple.where(:store_id => 2).all }.to log(:debug, /IndexCache miss for rc\/apl\/store_id=2v\d+: found no ids/)
37
+ expect{ Apple.where(:store_id => 2).load }.to log(:debug, /IndexCache miss for rc\/apl\/store_id=2v\d+: found no ids/)
32
38
  end
33
39
  end
34
40
 
35
41
  context "cacheable?" do
36
42
  before(:each) do
37
- @store1_apples = Apple.where(:store_id => 1).all
38
- @store2_apples = Apple.where(:store_id => 2).all
43
+ @store1_apples = Apple.where(:store_id => 1).load
44
+ @store2_apples = Apple.where(:store_id => 2).load
39
45
  end
40
46
 
41
47
  it "should hit the cache for a single index id" do
42
- expect{ Apple.where(:store_id => 1).all }.to hit_cache(Apple).on(:store_id).times(1)
48
+ expect{ Apple.where(:store_id => 1).load }.to hit_cache(Apple).on(:store_id).times(1)
43
49
  end
44
50
 
45
51
  it "should hit the cache for a single index id with other where clauses" do
46
- expect{ Apple.where(:store_id => 1).where(:name => "applegate").all }.to hit_cache(Apple).on(:store_id).times(1)
52
+ expect{ Apple.where(:store_id => 1).where(:name => "applegate").load }.to hit_cache(Apple).on(:store_id).times(1)
47
53
  end
48
54
 
49
55
  it "should hit the cache for a single index id with (simple) sort clauses" do
50
- expect{ Apple.where(:store_id => 1).order("name ASC").all }.to hit_cache(Apple).on(:store_id).times(1)
56
+ expect{ Apple.where(:store_id => 1).order("name ASC").load }.to hit_cache(Apple).on(:store_id).times(1)
51
57
  end
52
58
 
53
59
  #Allow limit == 1 by filtering records after cache hit. Needed for has_one
54
60
  it "should not hit the cache for a single index id with limit > 0" do
55
- expect{ Apple.where(:store_id => 1).limit(2).all }.to_not hit_cache(Apple).on(:store_id)
61
+ expect{ Apple.where(:store_id => 1).limit(2).load }.to_not hit_cache(Apple).on(:store_id)
56
62
  end
57
63
 
58
64
  it "should not hit the cache when an :id where clause is defined" do
59
65
  # this query should make use of the :id cache, which is faster
60
- expect{ Apple.where(:store_id => 1).where(:id => 1).all }.to_not hit_cache(Apple).on(:store_id)
66
+ expect{ Apple.where(:store_id => 1).where(:id => 1).load }.to_not hit_cache(Apple).on(:store_id)
61
67
  end
62
68
  end
63
-
69
+
64
70
  context "record_change" do
65
71
  before(:each) do
66
- @store1_apples = Apple.where(:store_id => 1).order('id ASC').all
67
- @store2_apples = Apple.where(:store_id => 2).order('id ASC').all
72
+ @store1_apples = Apple.where(:store_id => 1).order('id ASC').to_a
73
+ @store2_apples = Apple.where(:store_id => 2).order('id ASC').to_a
68
74
  end
69
75
 
70
76
  [false, true].each do |fresh|
@@ -76,14 +82,14 @@ describe RecordCache::Strategy::IndexCache do
76
82
  @destroyed.destroy
77
83
  # check the cache hit/miss on the index that contained that apple
78
84
  if fresh
79
- expect{ @apples = Apple.where(:store_id => 1).order('id ASC').all }.to hit_cache(Apple).on(:store_id).times(1)
85
+ expect{ @apples = Apple.where(:store_id => 1).order('id ASC').load }.to hit_cache(Apple).on(:store_id).times(1)
80
86
  else
81
- expect{ @apples = Apple.where(:store_id => 1).order('id ASC').all }.to miss_cache(Apple).on(:store_id).times(1)
87
+ expect{ @apples = Apple.where(:store_id => 1).order('id ASC').load }.to miss_cache(Apple).on(:store_id).times(1)
82
88
  end
83
89
  expect(@apples.size).to eq(@store1_apples.size - 1)
84
90
  expect(@apples.map(&:id)).to eq(@store1_apples.map(&:id) - [@destroyed.id])
85
91
  # and the index should be cached again
86
- expect{ Apple.where(:store_id => 1).all }.to hit_cache(Apple).on(:store_id).times(1)
92
+ expect{ Apple.where(:store_id => 1).load }.to hit_cache(Apple).on(:store_id).times(1)
87
93
  end
88
94
 
89
95
  it "should #{fresh ? 'update' : 'invalidate'} the index when a record in the index is created and the current index is #{fresh ? '' : 'not '}fresh" do
@@ -93,14 +99,14 @@ describe RecordCache::Strategy::IndexCache do
93
99
  @new_apple_in_store1 = Apple.create!(:name => "Fresh Apple", :store_id => 1)
94
100
  # check the cache hit/miss on the index that contains that apple
95
101
  if fresh
96
- expect{ @apples = Apple.where(:store_id => 1).order('id ASC').all }.to hit_cache(Apple).on(:store_id).times(1)
102
+ expect{ @apples = Apple.where(:store_id => 1).order('id ASC').load }.to hit_cache(Apple).on(:store_id).times(1)
97
103
  else
98
- expect{ @apples = Apple.where(:store_id => 1).order('id ASC').all }.to miss_cache(Apple).on(:store_id).times(1)
104
+ expect{ @apples = Apple.where(:store_id => 1).order('id ASC').load }.to miss_cache(Apple).on(:store_id).times(1)
99
105
  end
100
106
  expect(@apples.size).to eq(@store1_apples.size + 1)
101
107
  expect(@apples.map(&:id)).to eq(@store1_apples.map(&:id) + [@new_apple_in_store1.id])
102
108
  # and the index should be cached again
103
- expect{ Apple.where(:store_id => 1).all }.to hit_cache(Apple).on(:store_id).times(1)
109
+ expect{ Apple.where(:store_id => 1).load }.to hit_cache(Apple).on(:store_id).times(1)
104
110
  end
105
111
 
106
112
  it "should #{fresh ? 'update' : 'invalidate'} two indexes when the indexed value is updated and the current index is #{fresh ? '' : 'not '}fresh" do
@@ -113,25 +119,25 @@ describe RecordCache::Strategy::IndexCache do
113
119
  @apple_moved_from_store1_to_store2.save!
114
120
  # check the cache hit/miss on the indexes that contained/contains that apple
115
121
  if fresh
116
- expect{ @apples1 = Apple.where(:store_id => 1).order('id ASC').all }.to hit_cache(Apple).on(:store_id).times(1)
117
- expect{ @apples2 = Apple.where(:store_id => 2).order('id ASC').all }.to hit_cache(Apple).on(:store_id).times(1)
122
+ expect{ @apples1 = Apple.where(:store_id => 1).order('id ASC').load }.to hit_cache(Apple).on(:store_id).times(1)
123
+ expect{ @apples2 = Apple.where(:store_id => 2).order('id ASC').load }.to hit_cache(Apple).on(:store_id).times(1)
118
124
  else
119
- expect{ @apples1 = Apple.where(:store_id => 1).order('id ASC').all }.to miss_cache(Apple).on(:store_id).times(1)
120
- expect{ @apples2 = Apple.where(:store_id => 2).order('id ASC').all }.to miss_cache(Apple).on(:store_id).times(1)
125
+ expect{ @apples1 = Apple.where(:store_id => 1).order('id ASC').load }.to miss_cache(Apple).on(:store_id).times(1)
126
+ expect{ @apples2 = Apple.where(:store_id => 2).order('id ASC').load }.to miss_cache(Apple).on(:store_id).times(1)
121
127
  end
122
128
  expect(@apples1.size).to eq(@store1_apples.size - 1)
123
129
  expect(@apples2.size).to eq(@store2_apples.size + 1)
124
130
  expect(@apples1.map(&:id)).to eq(@store1_apples.map(&:id) - [@apple_moved_from_store1_to_store2.id])
125
131
  expect(@apples2.map(&:id)).to eq([@apple_moved_from_store1_to_store2.id] + @store2_apples.map(&:id))
126
132
  # and the index should be cached again
127
- expect{ Apple.where(:store_id => 1).all }.to hit_cache(Apple).on(:store_id).times(1)
128
- expect{ Apple.where(:store_id => 2).all }.to hit_cache(Apple).on(:store_id).times(1)
133
+ expect{ Apple.where(:store_id => 1).load }.to hit_cache(Apple).on(:store_id).times(1)
134
+ expect{ Apple.where(:store_id => 2).load }.to hit_cache(Apple).on(:store_id).times(1)
129
135
  end
130
136
 
131
137
  it "should #{fresh ? 'update' : 'invalidate'} multiple indexes when several values on different indexed attributes are updated at once and one of the indexes is #{fresh ? '' : 'not '}fresh" do
132
138
  # find the apples for person 1 and 5 (Chase)
133
- @person4_apples = Apple.where(:person_id => 4).all # Fry's Apples
134
- @person5_apples = Apple.where(:person_id => 5).all # Chases' Apples
139
+ @person4_apples = Apple.where(:person_id => 4).to_a # Fry's Apples
140
+ @person5_apples = Apple.where(:person_id => 5).to_a # Chases' Apples
135
141
  # make sure person indexes are no longer fresh
136
142
  Apple.record_cache.invalidate(:person_id, 4) unless fresh
137
143
  Apple.record_cache.invalidate(:person_id, 5) unless fresh
@@ -141,14 +147,14 @@ describe RecordCache::Strategy::IndexCache do
141
147
  @apple_moved_from_s1to2_p5to4.person_id = 4
142
148
  @apple_moved_from_s1to2_p5to4.save!
143
149
  # check the cache hit/miss on the indexes that contained/contains that apple
144
- expect{ @apples_s1 = Apple.where(:store_id => 1).order('id ASC').all }.to hit_cache(Apple).on(:store_id).times(1)
145
- expect{ @apples_s2 = Apple.where(:store_id => 2).order('id ASC').all }.to hit_cache(Apple).on(:store_id).times(1)
150
+ expect{ @apples_s1 = Apple.where(:store_id => 1).order('id ASC').load }.to hit_cache(Apple).on(:store_id).times(1)
151
+ expect{ @apples_s2 = Apple.where(:store_id => 2).order('id ASC').load }.to hit_cache(Apple).on(:store_id).times(1)
146
152
  if fresh
147
- expect{ @apples_p1 = Apple.where(:person_id => 4).order('id ASC').all }.to hit_cache(Apple).on(:person_id).times(1)
148
- expect{ @apples_p2 = Apple.where(:person_id => 5).order('id ASC').all }.to hit_cache(Apple).on(:person_id).times(1)
153
+ expect{ @apples_p1 = Apple.where(:person_id => 4).order('id ASC').load }.to hit_cache(Apple).on(:person_id).times(1)
154
+ expect{ @apples_p2 = Apple.where(:person_id => 5).order('id ASC').load }.to hit_cache(Apple).on(:person_id).times(1)
149
155
  else
150
- expect{ @apples_p1 = Apple.where(:person_id => 4).order('id ASC').all }.to miss_cache(Apple).on(:person_id).times(1)
151
- expect{ @apples_p2 = Apple.where(:person_id => 5).order('id ASC').all }.to miss_cache(Apple).on(:person_id).times(1)
156
+ expect{ @apples_p1 = Apple.where(:person_id => 4).order('id ASC').load }.to miss_cache(Apple).on(:person_id).times(1)
157
+ expect{ @apples_p2 = Apple.where(:person_id => 5).order('id ASC').load }.to miss_cache(Apple).on(:person_id).times(1)
152
158
  end
153
159
  expect(@apples_s1.size).to eq(@store1_apples.size - 1)
154
160
  expect(@apples_s2.size).to eq(@store2_apples.size + 1)
@@ -159,10 +165,10 @@ describe RecordCache::Strategy::IndexCache do
159
165
  expect(@apples_p1.map(&:id)).to eq(([@apple_moved_from_s1to2_p5to4.id] + @person4_apples.map(&:id)).sort)
160
166
  expect(@apples_p2.map(&:id)).to eq( (@person5_apples.map(&:id) - [@apple_moved_from_s1to2_p5to4.id]).sort)
161
167
  # and the index should be cached again
162
- expect{ Apple.where(:store_id => 1).all }.to hit_cache(Apple).on(:store_id).times(1)
163
- expect{ Apple.where(:store_id => 2).all }.to hit_cache(Apple).on(:store_id).times(1)
164
- expect{ Apple.where(:person_id => 4).all }.to hit_cache(Apple).on(:person_id).times(1)
165
- expect{ Apple.where(:person_id => 5).all }.to hit_cache(Apple).on(:person_id).times(1)
168
+ expect{ Apple.where(:store_id => 1).load }.to hit_cache(Apple).on(:store_id).times(1)
169
+ expect{ Apple.where(:store_id => 2).load }.to hit_cache(Apple).on(:store_id).times(1)
170
+ expect{ Apple.where(:person_id => 4).load }.to hit_cache(Apple).on(:person_id).times(1)
171
+ expect{ Apple.where(:person_id => 5).load }.to hit_cache(Apple).on(:person_id).times(1)
166
172
  end
167
173
  end
168
174
 
@@ -170,36 +176,36 @@ describe RecordCache::Strategy::IndexCache do
170
176
  # destroy an apple of store 2
171
177
  @store2_apples.first.destroy
172
178
  # index of apples of store 1 are not affected
173
- expect{ @apples = Apple.where(:store_id => 1).order('id ASC').all }.to hit_cache(Apple).on(:store_id).times(1)
179
+ expect{ @apples = Apple.where(:store_id => 1).order('id ASC').load }.to hit_cache(Apple).on(:store_id).times(1)
174
180
  end
175
181
 
176
182
  it "should leave the index alone when a record outside the index is created" do
177
183
  # create an apple for store 2
178
184
  Apple.create!(:name => "Fresh Apple", :store_id => 2)
179
185
  # index of apples of store 1 are not affected
180
- expect{ @apples = Apple.where(:store_id => 1).order('id ASC').all }.to hit_cache(Apple).on(:store_id).times(1)
186
+ expect{ @apples = Apple.where(:store_id => 1).order('id ASC').load }.to hit_cache(Apple).on(:store_id).times(1)
181
187
  end
182
188
  end
183
189
 
184
190
  context "invalidate" do
185
191
  before(:each) do
186
- @store1_apples = Apple.where(:store_id => 1).all
187
- @store2_apples = Apple.where(:store_id => 2).all
188
- @address_1 = Address.where(:store_id => 1).all
189
- @address_2 = Address.where(:store_id => 2).all
192
+ @store1_apples = Apple.where(:store_id => 1).to_a
193
+ @store2_apples = Apple.where(:store_id => 2).to_a
194
+ @address_1 = Address.where(:store_id => 1).to_a
195
+ @address_2 = Address.where(:store_id => 2).to_a
190
196
  end
191
197
 
192
198
  it "should invalidate single index" do
193
199
  Apple.record_cache[:store_id].invalidate(1)
194
- expect{ Apple.where(:store_id => 1).all }.to miss_cache(Apple).on(:store_id).times(1)
200
+ expect{ Apple.where(:store_id => 1).load }.to miss_cache(Apple).on(:store_id).times(1)
195
201
  end
196
202
 
197
203
  it "should invalidate indexes when using update_all" do
198
204
  pending "is there a performant way to invalidate index caches within update_all? only the new value is available, so we should query the old values..."
199
205
  # update 2 apples for index values store 1 and store 2
200
206
  Apple.where(:id => [@store1_apples.first.id, @store2_apples.first.id]).update_all(:store_id => 3)
201
- expect{ @apples_1 = Apple.where(:store_id => 1).all }.to miss_cache(Apple).on(:store_id).times(1)
202
- expect{ @apples_2 = Apple.where(:store_id => 2).all }.to miss_cache(Apple).on(:store_id).times(1)
207
+ expect{ @apples_1 = Apple.where(:store_id => 1).load }.to miss_cache(Apple).on(:store_id).times(1)
208
+ expect{ @apples_2 = Apple.where(:store_id => 2).load }.to miss_cache(Apple).on(:store_id).times(1)
203
209
  expect(@apples_1.map(&:id).sort).to eq(@store1_apples[1..-1].sort)
204
210
  expect(@apples_2.map(&:id).sort).to eq(@store2_apples[1..-1].sort)
205
211
  end
@@ -212,10 +218,10 @@ describe RecordCache::Strategy::IndexCache do
212
218
  store1.apple_ids = store2_apple_ids
213
219
  store1.save!
214
220
  # apples in Store 1 should be all (only) the apples that were in Store 2 (cache invalidated)
215
- expect{ @apples_1 = Apple.where(:store_id => 1).all }.to miss_cache(Apple).on(:store_id).times(1)
221
+ expect{ @apples_1 = Apple.where(:store_id => 1).load }.to miss_cache(Apple).on(:store_id).times(1)
216
222
  expect(@apples_1.map(&:id).sort).to eq(store2_apple_ids)
217
223
  # there are no apples in Store 2 anymore (incremental cache update, as each apples in store 2 was saved separately)
218
- expect{ @apples_2 = Apple.where(:store_id => 2).all }.to hit_cache(Apple).on(:store_id).times(1)
224
+ expect{ @apples_2 = Apple.where(:store_id => 2).load }.to hit_cache(Apple).on(:store_id).times(1)
219
225
  expect(@apples_2).to eq([])
220
226
  end
221
227
 
@@ -15,7 +15,7 @@ require 'spec_helper'
15
15
  # happen to records by another process, while you have already got
16
16
  # references to that records in QueryCache, that you won't see the changes
17
17
  # made by the other process.
18
- describe "QueryCache" do
18
+ RSpec.describe "QueryCache" do
19
19
 
20
20
  it "should retrieve a record from the QueryCache" do
21
21
  ActiveRecord::Base.cache do
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe RecordCache::Strategy::UniqueIndexCache do
3
+ RSpec.describe RecordCache::Strategy::UniqueIndexCache do
4
4
 
5
5
  it "should retrieve an Apple from the cache" do
6
6
  expect{ Apple.find(1) }.to miss_cache(Apple).on(:id).times(1)
@@ -40,9 +40,9 @@ describe RecordCache::Strategy::UniqueIndexCache do
40
40
  it "should write full miss to the debug log" do
41
41
  expect{ Apple.find(2) }.to log(:debug, %(UniqueIndexCache on 'Apple.id' miss for ids 2))
42
42
  end
43
-
43
+
44
44
  it "should write partial hits to the debug log" do
45
- expect{ Apple.where(:id => [1,2]).all }.to log(:debug, %(UniqueIndexCache on 'Apple.id' partial hit for ids [1, 2]: missing [2]))
45
+ expect{ Apple.where(:id => [1,2]).load }.to log(:debug, %(UniqueIndexCache on 'Apple.id' partial hit for ids [1, 2]: missing [2]))
46
46
  end
47
47
  end
48
48
 
@@ -55,50 +55,60 @@ describe RecordCache::Strategy::UniqueIndexCache do
55
55
 
56
56
  # @see https://github.com/orslumen/record-cache/issues/2
57
57
  it "should not use the cache when a lock is used" do
58
- expect{ Apple.lock("any_lock").where(:id => 1).all }.to_not hit_cache(Apple)
58
+ pending("Any_lock is sqlite specific and I'm not aware of a mysql alternative") unless ActiveRecord::Base.connection.adapter_name == "SQLite"
59
+
60
+ expect{ Apple.lock("any_lock").where(:id => 1).load }.to_not hit_cache(Apple)
59
61
  end
60
62
 
61
63
  it "should use the cache when a single id is requested" do
62
- expect{ Apple.where(:id => 1).all }.to hit_cache(Apple).on(:id).times(1)
64
+ expect{ Apple.where(:id => 1).load }.to hit_cache(Apple).on(:id).times(1)
63
65
  end
64
66
 
65
67
  it "should use the cache when a multiple ids are requested" do
66
- expect{ Apple.where(:id => [1, 2]).all }.to hit_cache(Apple).on(:id).times(2)
68
+ expect{ Apple.where(:id => [1, 2]).load }.to hit_cache(Apple).on(:id).times(2)
67
69
  end
68
70
 
69
71
  it "should use the cache when a single id is requested and the limit is 1" do
70
- expect{ Apple.where(:id => 1).limit(1).all }.to hit_cache(Apple).on(:id).times(1)
72
+ expect{ Apple.where(:id => 1).limit(1).load }.to hit_cache(Apple).on(:id).times(1)
71
73
  end
72
74
 
73
75
  it "should not use the cache when a single id is requested and the limit is > 1" do
74
- expect{ Apple.where(:id => 1).limit(2).all }.to_not use_cache(Apple).on(:id)
76
+ expect{ Apple.where(:id => 1).limit(2).load }.to_not use_cache(Apple).on(:id)
75
77
  end
76
78
 
77
79
  it "should not use the cache when multiple ids are requested and the limit is 1" do
78
- expect{ Apple.where(:id => [1, 2]).limit(1).all }.to_not use_cache(Apple).on(:id)
80
+ expect{ Apple.where(:id => [1, 2]).limit(1).load }.to_not use_cache(Apple).on(:id)
79
81
  end
80
82
 
81
83
  it "should use the cache when a single id is requested together with other where clauses" do
82
- expect{ Apple.where(:id => 1).where(:name => "Adams Apple x").all }.to hit_cache(Apple).on(:id).times(1)
84
+ expect{ Apple.where(:id => 1).where(:name => "Adams Apple x").load }.to hit_cache(Apple).on(:id).times(1)
83
85
  end
84
86
 
85
87
  it "should use the cache when a multiple ids are requested together with other where clauses" do
86
- expect{ Apple.where(:id => [1,2]).where(:name => "Adams Apple x").all }.to hit_cache(Apple).on(:id).times(2)
88
+ expect{ Apple.where(:id => [1,2]).where(:name => "Adams Apple x").load }.to hit_cache(Apple).on(:id).times(2)
87
89
  end
88
90
 
89
91
  it "should use the cache when a single id is requested together with (simple) sort clauses" do
90
- expect{ Apple.where(:id => 1).order("name ASC").all }.to hit_cache(Apple).on(:id).times(1)
92
+ expect{ Apple.where(:id => 1).order("name ASC").load }.to hit_cache(Apple).on(:id).times(1)
91
93
  end
92
94
 
93
95
  it "should use the cache when a multiple ids are requested together with (simple) sort clauses" do
94
- expect{ Apple.where(:id => [1,2]).order("name ASC").all }.to hit_cache(Apple).on(:id).times(2)
96
+ expect{ Apple.where(:id => [1,2]).order("name ASC").load }.to hit_cache(Apple).on(:id).times(2)
95
97
  end
96
98
 
97
99
  it "should not use the cache when a join clause is used" do
98
- expect{ Apple.where(:id => [1,2]).joins(:store).all }.to_not use_cache(Apple).on(:id)
100
+ expect{ Apple.where(:id => [1,2]).joins(:store).load }.to_not use_cache(Apple).on(:id)
101
+ end
102
+
103
+ it "should not use the cache when distinct is used in a select" do
104
+ expect{ Apple.select('distinct person_id').where(:id => [1, 2]).load }.not_to hit_cache(Apple).on(:id)
105
+ end
106
+
107
+ it "should not use the cache when distinct is used in a select" do
108
+ expect{ Apple.select('distinct person_id').where(:id => [1, 2]).load }.not_to hit_cache(Apple).on(:id)
99
109
  end
100
110
  end
101
-
111
+
102
112
  context "record_change" do
103
113
  before(:each) do
104
114
  # fill cache
@@ -107,12 +117,12 @@ describe RecordCache::Strategy::UniqueIndexCache do
107
117
  end
108
118
 
109
119
  it "should invalidate destroyed records" do
110
- expect{ Apple.where(:id => 1).all }.to hit_cache(Apple).on(:id).times(1)
120
+ expect{ Apple.where(:id => 1).load }.to hit_cache(Apple).on(:id).times(1)
111
121
  @apple1.destroy
112
- expect{ @apples = Apple.where(:id => 1).all }.to miss_cache(Apple).on(:id).times(1)
122
+ expect{ @apples = Apple.where(:id => 1).load }.to miss_cache(Apple).on(:id).times(1)
113
123
  expect(@apples).to be_empty
114
124
  # try again, to make sure the "missing record" is not cached
115
- expect{ Apple.where(:id => 1).all }.to miss_cache(Apple).on(:id).times(1)
125
+ expect{ Apple.where(:id => 1).load }.to miss_cache(Apple).on(:id).times(1)
116
126
  end
117
127
 
118
128
  it "should add updated records directly to the cache" do
@@ -131,12 +141,12 @@ describe RecordCache::Strategy::UniqueIndexCache do
131
141
  it "should add updated records to the cache, also when multiple ids are queried" do
132
142
  @apple1.name = "Applejuice"
133
143
  @apple1.save!
134
- expect{ @apples = Apple.where(:id => [1, 2]).order('id ASC').all }.to hit_cache(Apple).on(:id).times(2)
144
+ expect{ @apples = Apple.where(:id => [1, 2]).order('id ASC').load }.to hit_cache(Apple).on(:id).times(2)
135
145
  expect(@apples.map(&:name)).to eq(["Applejuice", "Adams Apple 2"])
136
146
  end
137
147
 
138
148
  end
139
-
149
+
140
150
  context "invalidate" do
141
151
  before(:each) do
142
152
  @apple1 = Apple.find(1)
@@ -151,27 +161,27 @@ describe RecordCache::Strategy::UniqueIndexCache do
151
161
  it "should only miss the cache for the invalidated record when multiple ids are queried" do
152
162
  # miss on 1
153
163
  Apple.record_cache[:id].invalidate(1)
154
- expect{ Apple.where(:id => [1, 2]).all }.to miss_cache(Apple).on(:id).times(1)
164
+ expect{ Apple.where(:id => [1, 2]).load }.to miss_cache(Apple).on(:id).times(1)
155
165
  # hit on 2
156
166
  Apple.record_cache[:id].invalidate(1)
157
- expect{ Apple.where(:id => [1, 2]).all }.to hit_cache(Apple).on(:id).times(1)
167
+ expect{ Apple.where(:id => [1, 2]).load }.to hit_cache(Apple).on(:id).times(1)
158
168
  # nothing invalidated, both hit
159
- expect{ Apple.where(:id => [1, 2]).all }.to hit_cache(Apple).on(:id).times(2)
169
+ expect{ Apple.where(:id => [1, 2]).load }.to hit_cache(Apple).on(:id).times(2)
160
170
  end
161
171
 
162
172
  it "should invalidate records when using update_all" do
163
- Apple.where(:id => [3,4,5]).all # fill id cache on all Adam Store apples
164
- expect{ @apples = Apple.where(:id => [1, 2, 3, 4, 5]).order('id ASC').all }.to hit_cache(Apple).on(:id).times(5)
173
+ Apple.where(:id => [3,4,5]).load # fill id cache on all Adam Store apples
174
+ expect{ @apples = Apple.where(:id => [1, 2, 3, 4, 5]).order('id ASC').load }.to hit_cache(Apple).on(:id).times(5)
165
175
  expect(@apples.map(&:name)).to eq(["Adams Apple 1", "Adams Apple 2", "Adams Apple 3", "Adams Apple 4", "Adams Apple 5"])
166
176
  # update 3 of the 5 apples in the Adam Store
167
177
  Apple.where(:id => [1,2,3]).update_all(:name => "Uniform Apple")
168
- expect{ @apples = Apple.where(:id => [1, 2, 3, 4, 5]).order('id ASC').all }.to hit_cache(Apple).on(:id).times(2)
178
+ expect{ @apples = Apple.where(:id => [1, 2, 3, 4, 5]).order('id ASC').load }.to hit_cache(Apple).on(:id).times(2)
169
179
  expect(@apples.map(&:name)).to eq(["Uniform Apple", "Uniform Apple", "Uniform Apple", "Adams Apple 4", "Adams Apple 5"])
170
180
  end
171
181
 
172
182
  it "should invalidate reflection indexes when a has_many relation is updated" do
173
183
  # assign different apples to store 2
174
- expect{ Apple.where(:store_id => 1).all }.to hit_cache(Apple).on(:id).times(2)
184
+ expect{ Apple.where(:store_id => 1).load }.to hit_cache(Apple).on(:id).times(2)
175
185
  store2_apple_ids = Apple.where(:store_id => 2).map(&:id)
176
186
  store1 = Store.find(1)
177
187
  store1.apple_ids = store2_apple_ids
@@ -288,30 +298,32 @@ describe RecordCache::Strategy::UniqueIndexCache do
288
298
  end
289
299
  end
290
300
 
291
- it "should not update the cache for the rolled back inner transaction" do
292
- pending "rails calls after_commit on records that are in a transaction that is rolled back"
293
-
294
- apple1, apple2 = nil
301
+ # does not work for Rails 3.0
302
+ unless ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR == 0
303
+ it "should not update the cache for the rolled back inner transaction" do
304
+ apple1, apple2 = nil
295
305
 
296
- ActiveRecord::Base.transaction do
297
- apple1 = Apple.find(1)
298
- apple1.name = "Committed Apple 1"
299
- apple1.save!
306
+ ActiveRecord::Base.transaction do
307
+ apple1 = Apple.find(1)
308
+ apple1.name = "Committed Apple 1"
309
+ apple1.save!
300
310
 
301
- ActiveRecord::Base.transaction(requires_new: true) do
302
- apple2 = Apple.find(2)
303
- apple2.name = "Rollback Apple 2"
304
- apple2.save!
311
+ ActiveRecord::Base.transaction(requires_new: true) do
312
+ apple2 = Apple.find(2)
313
+ apple2.name = "Rollback Apple 2"
314
+ apple2.save!
305
315
 
306
- raise ActiveRecord::Rollback, "oops"
316
+ raise ActiveRecord::Rollback, "oops"
317
+ end
307
318
  end
308
- end
309
319
 
310
- expect{ apple1 = Apple.find(1) }.to use_cache(Apple).on(:id)
311
- expect(apple1.name).to eq("Committed Apple 1")
320
+ expect{ apple1 = Apple.find(1) }.to use_cache(Apple).on(:id)
321
+ expect(apple1.name).to eq("Committed Apple 1")
312
322
 
313
- expect{ apple2 = Apple.find(2) }.to use_cache(Apple).on(:id)
314
- expect(apple2.name).to eq("Adams Apple 2")
323
+ expect{ apple2 = Apple.find(2) }.to use_cache(Apple).on(:id)
324
+ expect(apple2.name).to eq("Adams Apple 2")
325
+ end
315
326
  end
327
+
316
328
  end
317
329
  end