record-cache 0.1.2 → 0.1.3
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 +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
data/spec/lib/multi_read_spec.rb
CHANGED
@@ -8,7 +8,7 @@ describe RecordCache::MultiRead do
|
|
8
8
|
def read_multi(*keys) "multi" end
|
9
9
|
end
|
10
10
|
store = RecordCache::MultiRead.test(MultiReadSupported.new)
|
11
|
-
store.read_multi("key1", "key2").
|
11
|
+
expect(store.read_multi("key1", "key2")).to eq("multi")
|
12
12
|
end
|
13
13
|
|
14
14
|
it "should delegate to single reads when multi_read is explicitly disabled" do
|
@@ -18,7 +18,7 @@ describe RecordCache::MultiRead do
|
|
18
18
|
end
|
19
19
|
RecordCache::MultiRead.disable(ExplicitlyDisabled)
|
20
20
|
store = RecordCache::MultiRead.test(ExplicitlyDisabled.new)
|
21
|
-
store.read_multi("key1", "key2").
|
21
|
+
expect(store.read_multi("key1", "key2")).to eq({"key1" => "single", "key2" => "single"})
|
22
22
|
end
|
23
23
|
|
24
24
|
it "should delegate to single reads when multi_read throws an error" do
|
@@ -27,7 +27,7 @@ describe RecordCache::MultiRead do
|
|
27
27
|
def read_multi(*keys) raise NotImplementedError.new("multiread not implemented") end
|
28
28
|
end
|
29
29
|
store = RecordCache::MultiRead.test(MultiReadNotImplemented.new)
|
30
|
-
store.read_multi("key1", "key2").
|
30
|
+
expect(store.read_multi("key1", "key2")).to eq({"key1" => "single", "key2" => "single"})
|
31
31
|
end
|
32
32
|
|
33
33
|
it "should delegate to single reads when multi_read is undefined" do
|
@@ -35,17 +35,17 @@ describe RecordCache::MultiRead do
|
|
35
35
|
def read(key) "single" end
|
36
36
|
end
|
37
37
|
store = RecordCache::MultiRead.test(MultiReadNotDefined.new)
|
38
|
-
store.read_multi("key1", "key2").
|
38
|
+
expect(store.read_multi("key1", "key2")).to eq({"key1" => "single", "key2" => "single"})
|
39
39
|
end
|
40
40
|
|
41
41
|
it "should have tested the Version Store" do
|
42
|
-
RecordCache::MultiRead.instance_variable_get(:@tested).
|
42
|
+
expect(RecordCache::MultiRead.instance_variable_get(:@tested)).to include(RecordCache::Base.version_store.instance_variable_get(:@store))
|
43
43
|
end
|
44
44
|
|
45
45
|
it "should have tested all Record Stores" do
|
46
46
|
tested_stores = RecordCache::MultiRead.instance_variable_get(:@tested)
|
47
47
|
RecordCache::Base.stores.values.each do |record_store|
|
48
|
-
tested_stores.
|
48
|
+
expect(tested_stores).to include(record_store)
|
49
49
|
end
|
50
50
|
end
|
51
51
|
end
|
data/spec/lib/query_spec.rb
CHANGED
@@ -4,145 +4,145 @@ describe RecordCache::Query do
|
|
4
4
|
before(:each) do
|
5
5
|
@query = RecordCache::Query.new
|
6
6
|
end
|
7
|
-
|
7
|
+
|
8
8
|
context "wheres" do
|
9
9
|
it "should be an empty hash by default" do
|
10
|
-
@query.wheres.
|
10
|
+
expect(@query.wheres).to eq({})
|
11
11
|
end
|
12
12
|
|
13
13
|
it "should fill wheres on instantiation" do
|
14
14
|
@query = RecordCache::Query.new({:id => 1})
|
15
|
-
@query.wheres.
|
15
|
+
expect(@query.wheres).to eq({:id => 1})
|
16
16
|
end
|
17
17
|
|
18
18
|
it "should keep track of where clauses" do
|
19
19
|
@query.where(:name, "My name")
|
20
20
|
@query.where(:id, [1, 2, 3])
|
21
21
|
@query.where(:height, 1.75)
|
22
|
-
@query.wheres.
|
22
|
+
expect(@query.wheres).to eq({:name => "My name", :id => [1, 2, 3], :height => 1.75})
|
23
23
|
end
|
24
24
|
|
25
|
-
context "
|
25
|
+
context "where_values" do
|
26
26
|
it "should return nil if the attribute is not defined" do
|
27
27
|
@query.where(:idx, 15)
|
28
|
-
@query.
|
28
|
+
expect(@query.where_values(:id)).to be_nil
|
29
29
|
end
|
30
30
|
|
31
31
|
it "should return nil if one the value is nil" do
|
32
32
|
@query.where(:id, nil)
|
33
|
-
@query.
|
33
|
+
expect(@query.where_values(:id)).to be_nil
|
34
34
|
end
|
35
35
|
|
36
36
|
it "should return nil if one of the values is < 1" do
|
37
37
|
@query.where(:id, [2, 0, 8])
|
38
|
-
@query.
|
38
|
+
expect(@query.where_values(:id)).to be_nil
|
39
39
|
end
|
40
40
|
|
41
|
-
it "should return nil
|
41
|
+
it "should return remove nil from the values" do
|
42
42
|
@query.where(:id, ["1", nil, "3"])
|
43
|
-
@query.
|
43
|
+
expect(@query.where_values(:id)).to eq([1,3])
|
44
44
|
end
|
45
45
|
|
46
46
|
it "should retrieve an array of integers when a single integer is provided" do
|
47
47
|
@query.where(:id, 15)
|
48
|
-
@query.
|
48
|
+
expect(@query.where_values(:id)).to eq([15])
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
51
|
it "should retrieve an array of integers when a multiple integers are provided" do
|
52
52
|
@query.where(:id, [2, 4, 8])
|
53
|
-
@query.
|
53
|
+
expect(@query.where_values(:id)).to eq([2, 4, 8])
|
54
54
|
end
|
55
|
-
|
55
|
+
|
56
56
|
it "should retrieve an array of integers when a single string is provided" do
|
57
57
|
@query.where(:id, "15")
|
58
|
-
@query.
|
58
|
+
expect(@query.where_values(:id)).to eq([15])
|
59
59
|
end
|
60
|
-
|
60
|
+
|
61
61
|
it "should retrieve an array of integers when a multiple strings are provided" do
|
62
62
|
@query.where(:id, ["2", "4", "8"])
|
63
|
-
@query.
|
63
|
+
expect(@query.where_values(:id)).to eq([2, 4, 8])
|
64
64
|
end
|
65
|
-
|
66
|
-
it "should cache the array of
|
65
|
+
|
66
|
+
it "should cache the array of values" do
|
67
67
|
@query.where(:id, ["2", "4", "8"])
|
68
|
-
ids1 = @query.
|
69
|
-
ids2 = @query.
|
70
|
-
ids1.object_id.
|
68
|
+
ids1 = @query.where_values(:id)
|
69
|
+
ids2 = @query.where_values(:id)
|
70
|
+
expect(ids1.object_id).to eq(ids2.object_id)
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
-
context "
|
74
|
+
context "where_value" do
|
75
75
|
it "should return nil when multiple integers are provided" do
|
76
76
|
@query.where(:id, [2, 4, 8])
|
77
|
-
@query.
|
77
|
+
expect(@query.where_value(:id)).to be_nil
|
78
78
|
end
|
79
|
-
|
79
|
+
|
80
80
|
it "should return the id when a single integer is provided" do
|
81
81
|
@query.where(:id, 4)
|
82
|
-
@query.
|
82
|
+
expect(@query.where_value(:id)).to eq(4)
|
83
83
|
end
|
84
84
|
|
85
85
|
it "should return the id when a single string is provided" do
|
86
86
|
@query.where(:id, ["4"])
|
87
|
-
@query.
|
87
|
+
expect(@query.where_value(:id)).to eq(4)
|
88
88
|
end
|
89
89
|
end
|
90
90
|
end
|
91
91
|
|
92
92
|
context "sort" do
|
93
93
|
it "should be an empty array by default" do
|
94
|
-
@query.sort_orders.
|
94
|
+
expect(@query.sort_orders).to be_empty
|
95
95
|
end
|
96
96
|
|
97
97
|
it "should keep track of sort orders" do
|
98
98
|
@query.order_by("name", true)
|
99
99
|
@query.order_by("id", false)
|
100
|
-
@query.sort_orders.
|
100
|
+
expect(@query.sort_orders).to eq([ ["name", true], ["id", false] ])
|
101
101
|
end
|
102
102
|
|
103
103
|
it "should convert attribute to string" do
|
104
104
|
@query.order_by(:name, true)
|
105
|
-
@query.sort_orders.
|
105
|
+
expect(@query.sort_orders).to eq([ ["name", true] ])
|
106
106
|
end
|
107
107
|
|
108
108
|
it "should define sorted?" do
|
109
|
-
@query.sorted
|
109
|
+
expect(@query.sorted?).to eq(false)
|
110
110
|
@query.order_by("name", true)
|
111
|
-
@query.sorted
|
111
|
+
expect(@query.sorted?).to eq(true)
|
112
112
|
end
|
113
113
|
end
|
114
|
-
|
114
|
+
|
115
115
|
context "limit" do
|
116
116
|
it "should be +nil+ by default" do
|
117
|
-
@query.limit.
|
117
|
+
expect(@query.limit).to be_nil
|
118
118
|
end
|
119
|
-
|
119
|
+
|
120
120
|
it "should keep track of limit" do
|
121
121
|
@query.limit = 4
|
122
|
-
@query.limit.
|
122
|
+
expect(@query.limit).to eq(4)
|
123
123
|
end
|
124
124
|
|
125
125
|
it "should convert limit to integer" do
|
126
126
|
@query.limit = "4"
|
127
|
-
@query.limit.
|
127
|
+
expect(@query.limit).to eq(4)
|
128
128
|
end
|
129
129
|
end
|
130
|
-
|
130
|
+
|
131
131
|
context "utility" do
|
132
132
|
before(:each) do
|
133
|
-
@query.where(:name, "My name")
|
133
|
+
@query.where(:name, "My name & co")
|
134
134
|
@query.where(:id, [1, 2, 3])
|
135
135
|
@query.order_by("name", true)
|
136
136
|
@query.limit = "4"
|
137
137
|
end
|
138
|
-
|
138
|
+
|
139
139
|
it "should generate a unique key for (request) caching purposes" do
|
140
|
-
@query.cache_key.
|
140
|
+
expect(@query.cache_key).to eq('4+name?name="My name & co"&id=[1, 2, 3]')
|
141
141
|
end
|
142
142
|
|
143
143
|
it "should generate a pretty formatted query" do
|
144
|
-
@query.to_s.
|
144
|
+
expect(@query.to_s).to eq('SELECT name = "My name & co" AND id = [1, 2, 3] ORDER_BY name ASC LIMIT 4')
|
145
145
|
end
|
146
146
|
end
|
147
|
-
|
147
|
+
|
148
148
|
end
|
data/spec/lib/statistics_spec.rb
CHANGED
@@ -8,39 +8,39 @@ describe RecordCache::Statistics do
|
|
8
8
|
|
9
9
|
context "active" do
|
10
10
|
it "should default to false" do
|
11
|
-
RecordCache::Statistics.active
|
11
|
+
expect(RecordCache::Statistics.active?).to be_falsey
|
12
12
|
end
|
13
13
|
|
14
14
|
it "should be activated by start" do
|
15
15
|
RecordCache::Statistics.start
|
16
|
-
RecordCache::Statistics.active
|
16
|
+
expect(RecordCache::Statistics.active?).to be_truthy
|
17
17
|
end
|
18
18
|
|
19
19
|
it "should be deactivated by stop" do
|
20
20
|
RecordCache::Statistics.start
|
21
|
-
RecordCache::Statistics.active
|
21
|
+
expect(RecordCache::Statistics.active?).to be_truthy
|
22
22
|
RecordCache::Statistics.stop
|
23
|
-
RecordCache::Statistics.active
|
23
|
+
expect(RecordCache::Statistics.active?).to be_falsey
|
24
24
|
end
|
25
25
|
|
26
26
|
it "should be toggleable" do
|
27
27
|
RecordCache::Statistics.toggle
|
28
|
-
RecordCache::Statistics.active
|
28
|
+
expect(RecordCache::Statistics.active?).to be_truthy
|
29
29
|
RecordCache::Statistics.toggle
|
30
|
-
RecordCache::Statistics.active
|
30
|
+
expect(RecordCache::Statistics.active?).to be_falsey
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
34
|
context "find" do
|
35
35
|
it "should return {} for unknown base classes" do
|
36
36
|
class UnknownBase; end
|
37
|
-
RecordCache::Statistics.find(UnknownBase).
|
37
|
+
expect(RecordCache::Statistics.find(UnknownBase)).to eq({})
|
38
38
|
end
|
39
39
|
|
40
40
|
it "should create a new counter for unknown strategies" do
|
41
41
|
class UnknownBase; end
|
42
42
|
counter = RecordCache::Statistics.find(UnknownBase, :strategy)
|
43
|
-
counter.calls.
|
43
|
+
expect(counter.calls).to eq(0)
|
44
44
|
end
|
45
45
|
|
46
46
|
it "should retrieve all strategies if only the base is provided" do
|
@@ -48,15 +48,15 @@ describe RecordCache::Statistics do
|
|
48
48
|
counter1 = RecordCache::Statistics.find(KnownBase, :strategy1)
|
49
49
|
counter2 = RecordCache::Statistics.find(KnownBase, :strategy2)
|
50
50
|
counters = RecordCache::Statistics.find(KnownBase)
|
51
|
-
counters.size.
|
52
|
-
counters[:strategy1].
|
53
|
-
counters[:strategy2].
|
51
|
+
expect(counters.size).to eq(2)
|
52
|
+
expect(counters[:strategy1]).to eq(counter1)
|
53
|
+
expect(counters[:strategy2]).to eq(counter2)
|
54
54
|
end
|
55
55
|
|
56
56
|
it "should retrieve the counter for an existing strategy" do
|
57
57
|
class KnownBase; end
|
58
58
|
counter1 = RecordCache::Statistics.find(KnownBase, :strategy1)
|
59
|
-
RecordCache::Statistics.find(KnownBase, :strategy1).
|
59
|
+
expect(RecordCache::Statistics.find(KnownBase, :strategy1)).to eq(counter1)
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
@@ -70,16 +70,16 @@ describe RecordCache::Statistics do
|
|
70
70
|
end
|
71
71
|
|
72
72
|
it "should reset all counters for a specific base" do
|
73
|
-
|
74
|
-
|
75
|
-
|
73
|
+
expect(@counter_a1).to receive(:reset!)
|
74
|
+
expect(@counter_a2).to receive(:reset!)
|
75
|
+
expect(@counter_b1).to_not receive(:reset!)
|
76
76
|
RecordCache::Statistics.reset!(BaseA)
|
77
77
|
end
|
78
78
|
|
79
79
|
it "should reset all counters" do
|
80
|
-
|
81
|
-
|
82
|
-
|
80
|
+
expect(@counter_a1).to receive(:reset!)
|
81
|
+
expect(@counter_a2).to receive(:reset!)
|
82
|
+
expect(@counter_b1).to receive(:reset!)
|
83
83
|
RecordCache::Statistics.reset!
|
84
84
|
end
|
85
85
|
end
|
@@ -90,51 +90,51 @@ describe RecordCache::Statistics do
|
|
90
90
|
end
|
91
91
|
|
92
92
|
it "should be empty by default" do
|
93
|
-
[@counter.calls, @counter.hits, @counter.misses].
|
93
|
+
expect([@counter.calls, @counter.hits, @counter.misses]).to eq([0, 0, 0])
|
94
94
|
end
|
95
95
|
|
96
96
|
it "should delegate active? to RecordCache::Statistics" do
|
97
|
-
|
97
|
+
expect(RecordCache::Statistics).to receive(:active?)
|
98
98
|
@counter.active?
|
99
99
|
end
|
100
100
|
|
101
101
|
it "should add hits and misses" do
|
102
102
|
@counter.add(4, 3)
|
103
|
-
[@counter.calls, @counter.hits, @counter.misses].
|
103
|
+
expect([@counter.calls, @counter.hits, @counter.misses]).to eq([1, 3, 1])
|
104
104
|
end
|
105
105
|
|
106
106
|
it "should sum added hits and misses" do
|
107
107
|
@counter.add(4, 3)
|
108
108
|
@counter.add(1, 1)
|
109
109
|
@counter.add(3, 2)
|
110
|
-
[@counter.calls, @counter.hits, @counter.misses].
|
110
|
+
expect([@counter.calls, @counter.hits, @counter.misses]).to eq([3, 6, 2])
|
111
111
|
end
|
112
112
|
|
113
113
|
it "should reset! hits and misses" do
|
114
114
|
@counter.add(4, 3)
|
115
115
|
@counter.add(1, 1)
|
116
116
|
@counter.reset!
|
117
|
-
[@counter.calls, @counter.hits, @counter.misses].
|
117
|
+
expect([@counter.calls, @counter.hits, @counter.misses]).to eq([0, 0, 0])
|
118
118
|
end
|
119
119
|
|
120
120
|
it "should provide 0.0 percentage for empty counter" do
|
121
|
-
@counter.percentage.
|
121
|
+
expect(@counter.percentage).to eq(0.0)
|
122
122
|
end
|
123
123
|
|
124
124
|
it "should provide percentage" do
|
125
125
|
@counter.add(4, 3)
|
126
|
-
@counter.percentage.
|
126
|
+
expect(@counter.percentage).to eq(75.0)
|
127
127
|
@counter.add(1, 1)
|
128
|
-
@counter.percentage.
|
128
|
+
expect(@counter.percentage).to eq(80.0)
|
129
129
|
@counter.add(5, 2)
|
130
|
-
@counter.percentage.
|
130
|
+
expect(@counter.percentage).to eq(60.0)
|
131
131
|
end
|
132
132
|
|
133
133
|
it "should pretty print on inspect" do
|
134
134
|
@counter.add(4, 3)
|
135
135
|
@counter.add(1, 1)
|
136
136
|
@counter.add(5, 2)
|
137
|
-
@counter.inspect.
|
137
|
+
expect(@counter.inspect).to eq("60.0% (6/10)")
|
138
138
|
end
|
139
139
|
end
|
140
140
|
end
|
@@ -1,75 +1,90 @@
|
|
1
|
-
|
1
|
+
# encoding: utf-8
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
4
|
describe RecordCache::Strategy::Base do
|
5
|
-
|
5
|
+
|
6
|
+
it "should force implementation of self.parse method" do
|
7
|
+
module RecordCache
|
8
|
+
module Strategy
|
9
|
+
class MissingParseCache < Base
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
expect{ RecordCache::Strategy::MissingParseCache.parse(1,2,3) }.to raise_error(NotImplementedError)
|
14
|
+
end
|
15
|
+
|
6
16
|
it "should provide easy access to the Version Store" do
|
7
|
-
Apple.record_cache[:id].send(:version_store).
|
17
|
+
expect(Apple.record_cache[:id].send(:version_store)).to eq(RecordCache::Base.version_store)
|
8
18
|
end
|
9
19
|
|
10
20
|
it "should provide easy access to the Record Store" do
|
11
|
-
Apple.record_cache[:id].send(:record_store).
|
12
|
-
Banana.record_cache[:id].send(:record_store).
|
21
|
+
expect(Apple.record_cache[:id].send(:record_store)).to eq(RecordCache::Base.stores[:shared])
|
22
|
+
expect(Banana.record_cache[:id].send(:record_store)).to eq(RecordCache::Base.stores[:local])
|
13
23
|
end
|
14
24
|
|
15
25
|
it "should provide easy access to the statistics" do
|
16
|
-
Apple.record_cache[:person_id].send(:statistics).
|
17
|
-
Banana.record_cache[:id].send(:statistics).
|
26
|
+
expect(Apple.record_cache[:person_id].send(:statistics)).to eq(RecordCache::Statistics.find(Apple, :person_id))
|
27
|
+
expect(Banana.record_cache[:id].send(:statistics)).to eq(RecordCache::Statistics.find(Banana, :id))
|
18
28
|
end
|
19
29
|
|
20
30
|
it "should retrieve the cache key based on the :key option" do
|
21
|
-
Apple.record_cache[:id].send(:cache_key, 1).
|
31
|
+
expect(Apple.record_cache[:id].send(:cache_key, 1)).to eq("rc/apl/1")
|
22
32
|
end
|
23
33
|
|
24
34
|
it "should retrieve the cache key based on the model name" do
|
25
|
-
Banana.record_cache[:id].send(:cache_key, 1).
|
35
|
+
expect(Banana.record_cache[:id].send(:cache_key, 1)).to eq("rc/Banana/1")
|
26
36
|
end
|
27
37
|
|
28
38
|
it "should define the versioned key" do
|
29
|
-
Banana.record_cache[:id].send(:versioned_key, "rc/Banana/1", 2312423).
|
39
|
+
expect(Banana.record_cache[:id].send(:versioned_key, "rc/Banana/1", 2312423)).to eq("rc/Banana/1v2312423")
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should provide the version_opts" do
|
43
|
+
expect(Apple.record_cache[:id].send(:version_opts)).to eq({:ttl => 300})
|
44
|
+
expect(Banana.record_cache[:id].send(:version_opts)).to eq({})
|
30
45
|
end
|
31
46
|
|
32
47
|
context "filter" do
|
33
48
|
it "should apply filter on :id cache hits" do
|
34
|
-
|
35
|
-
@apples.
|
49
|
+
expect{ @apples = Apple.where(:id => [1,2]).where(:name => "Adams Apple 1").all }.to use_cache(Apple).on(:id)
|
50
|
+
expect(@apples).to eq([Apple.find_by_name("Adams Apple 1")])
|
36
51
|
end
|
37
52
|
|
38
53
|
it "should apply filter on index cache hits" do
|
39
|
-
|
40
|
-
@apples.
|
54
|
+
expect{ @apples = Apple.where(:store_id => 1).where(:name => "Adams Apple 1").all }.to use_cache(Apple).on(:store_id)
|
55
|
+
expect(@apples).to eq([Apple.find_by_name("Adams Apple 1")])
|
41
56
|
end
|
42
57
|
|
43
58
|
it "should return empty array when filter does not match any record" do
|
44
|
-
|
45
|
-
@apples.
|
59
|
+
expect{ @apples = Apple.where(:store_id => 1).where(:name => "Adams Apple Pie").all }.to use_cache(Apple).on(:store_id)
|
60
|
+
expect(@apples).to be_empty
|
46
61
|
end
|
47
62
|
|
48
63
|
it "should filter on text" do
|
49
|
-
|
50
|
-
@apples.
|
64
|
+
expect{ @apples = Apple.where(:id => [1,2]).where(:name => "Adams Apple 1").all }.to use_cache(Apple).on(:id)
|
65
|
+
expect(@apples).to eq([Apple.find_by_name("Adams Apple 1")])
|
51
66
|
end
|
52
67
|
|
53
68
|
it "should filter on integers" do
|
54
|
-
|
55
|
-
@apples.map(&:id).sort.
|
69
|
+
expect{ @apples = Apple.where(:id => [1,2,8,9]).where(:store_id => 2).all }.to use_cache(Apple).on(:id)
|
70
|
+
expect(@apples.map(&:id).sort).to eq([8,9])
|
56
71
|
end
|
57
72
|
|
58
73
|
it "should filter on dates" do
|
59
|
-
|
60
|
-
@people.size.
|
61
|
-
@people.first.name.
|
74
|
+
expect{ @people = Person.where(:id => [1,2,3]).where(:birthday => Date.civil(1953,11,11)).all }.to use_cache(Person).on(:id)
|
75
|
+
expect(@people.size).to eq(1)
|
76
|
+
expect(@people.first.name).to eq("Blue")
|
62
77
|
end
|
63
78
|
|
64
79
|
it "should filter on floats" do
|
65
|
-
|
66
|
-
@people.size.
|
67
|
-
@people.map(&:name).sort.
|
80
|
+
expect{ @people = Person.where(:id => [1,2,3]).where(:height => 1.75).all }.to use_cache(Person).on(:id)
|
81
|
+
expect(@people.size).to eq(2)
|
82
|
+
expect(@people.map(&:name).sort).to eq(["Blue", "Cris"])
|
68
83
|
end
|
69
84
|
|
70
85
|
it "should filter on arrays" do
|
71
|
-
|
72
|
-
@apples.map(&:id).sort.
|
86
|
+
expect{ @apples = Apple.where(:id => [1,2,8,9]).where(:store_id => [2, 4]).all }.to use_cache(Apple).on(:id)
|
87
|
+
expect(@apples.map(&:id).sort).to eq([8,9])
|
73
88
|
end
|
74
89
|
|
75
90
|
it "should filter on multiple fields" do
|
@@ -78,102 +93,102 @@ describe RecordCache::Strategy::Base do
|
|
78
93
|
@apple.name = Apple.find(9).name
|
79
94
|
@apple.save!
|
80
95
|
|
81
|
-
|
82
|
-
@apples.size.
|
83
|
-
@apples.map(&:name).
|
84
|
-
@apples.map(&:id).sort.
|
96
|
+
expect{ @apples = Apple.where(:id => [1,2,3,8,9,10]).where(:store_id => 2).where(:name => @apple.name).all }.to use_cache(Apple).on(:id)
|
97
|
+
expect(@apples.size).to eq(2)
|
98
|
+
expect(@apples.map(&:name)).to eq([@apple.name, @apple.name])
|
99
|
+
expect(@apples.map(&:id).sort).to eq([8,9])
|
85
100
|
end
|
86
101
|
|
87
102
|
end
|
88
103
|
|
89
104
|
context "sort" do
|
90
105
|
it "should apply sort on :id cache hits" do
|
91
|
-
|
92
|
-
@people.map(&:name).
|
106
|
+
expect{ @people = Person.where(:id => [1,2,3]).order("name DESC").all }.to use_cache(Person).on(:id)
|
107
|
+
expect(@people.map(&:name)).to eq(["Cris", "Blue", "Adam"])
|
93
108
|
end
|
94
109
|
|
95
110
|
it "should apply sort on index cache hits" do
|
96
|
-
|
97
|
-
@apples.map(&:person_id).
|
111
|
+
expect{ @apples = Apple.where(:store_id => 1).order("person_id ASC").all }.to use_cache(Apple).on(:store_id)
|
112
|
+
expect(@apples.map(&:person_id)).to eq([nil, nil, 4, 4, 5])
|
98
113
|
end
|
99
114
|
|
100
115
|
it "should default to ASC" do
|
101
|
-
|
102
|
-
@apples.map(&:person_id).
|
116
|
+
expect{ @apples = Apple.where(:store_id => 1).order("person_id").all }.to use_cache(Apple).on(:store_id)
|
117
|
+
expect(@apples.map(&:person_id)).to eq([nil, nil, 4, 4, 5])
|
103
118
|
end
|
104
119
|
|
105
120
|
it "should apply sort nil first for ASC" do
|
106
|
-
|
107
|
-
@apples.map(&:person_id).
|
121
|
+
expect{ @apples = Apple.where(:store_id => 1).order("person_id ASC").all }.to use_cache(Apple).on(:store_id)
|
122
|
+
expect(@apples.map(&:person_id)).to eq([nil, nil, 4, 4, 5])
|
108
123
|
end
|
109
124
|
|
110
125
|
it "should apply sort nil last for DESC" do
|
111
|
-
|
112
|
-
@apples.map(&:person_id).
|
126
|
+
expect{ @apples = Apple.where(:store_id => 1).order("person_id DESC").all }.to use_cache(Apple).on(:store_id)
|
127
|
+
expect(@apples.map(&:person_id)).to eq([5, 4, 4, nil, nil])
|
113
128
|
end
|
114
129
|
|
115
130
|
it "should sort ascending on text" do
|
116
|
-
|
117
|
-
@people.map(&:name).
|
131
|
+
expect{ @people = Person.where(:id => [1,2,3,4]).order("name ASC").all }.to use_cache(Person).on(:id)
|
132
|
+
expect(@people.map(&:name)).to eq(["Adam", "Blue", "Cris", "Fry"])
|
118
133
|
end
|
119
134
|
|
120
135
|
it "should sort descending on text" do
|
121
|
-
|
122
|
-
@people.map(&:name).
|
136
|
+
expect{ @people = Person.where(:id => [1,2,3,4]).order("name DESC").all }.to use_cache(Person).on(:id)
|
137
|
+
expect(@people.map(&:name)).to eq(["Fry", "Cris", "Blue", "Adam"])
|
123
138
|
end
|
124
139
|
|
125
140
|
it "should sort ascending on integers" do
|
126
|
-
|
127
|
-
@people.map(&:id).
|
141
|
+
expect{ @people = Person.where(:id => [1,2,3,4]).order("id ASC").all }.to use_cache(Person).on(:id)
|
142
|
+
expect(@people.map(&:id)).to eq([1,2,3,4])
|
128
143
|
end
|
129
144
|
|
130
145
|
it "should sort descending on integers" do
|
131
|
-
|
132
|
-
@people.map(&:id).
|
146
|
+
expect{ @people = Person.where(:id => [1,2,3,4]).order("id DESC").all }.to use_cache(Person).on(:id)
|
147
|
+
expect(@people.map(&:id)).to eq([4,3,2,1])
|
133
148
|
end
|
134
149
|
|
135
150
|
it "should sort ascending on dates" do
|
136
|
-
|
137
|
-
@people.map(&:birthday).
|
151
|
+
expect{ @people = Person.where(:id => [1,2,3,4]).order("birthday ASC").all }.to use_cache(Person).on(:id)
|
152
|
+
expect(@people.map(&:birthday)).to eq([Date.civil(1953,11,11), Date.civil(1975,03,20), Date.civil(1975,03,20), Date.civil(1985,01,20)])
|
138
153
|
end
|
139
154
|
|
140
155
|
it "should sort descending on dates" do
|
141
|
-
|
142
|
-
@people.map(&:birthday).
|
156
|
+
expect{ @people = Person.where(:id => [1,2,3,4]).order("birthday DESC").all }.to use_cache(Person).on(:id)
|
157
|
+
expect(@people.map(&:birthday)).to eq([Date.civil(1985,01,20), Date.civil(1975,03,20), Date.civil(1975,03,20), Date.civil(1953,11,11)])
|
143
158
|
end
|
144
159
|
|
145
160
|
it "should sort ascending on float" do
|
146
|
-
|
147
|
-
@people.map(&:height).
|
161
|
+
expect{ @people = Person.where(:id => [1,2,3,4]).order("height ASC").all }.to use_cache(Person).on(:id)
|
162
|
+
expect(@people.map(&:height)).to eq([1.69, 1.75, 1.75, 1.83])
|
148
163
|
end
|
149
164
|
|
150
165
|
it "should sort descending on float" do
|
151
|
-
|
152
|
-
@people.map(&:height).
|
166
|
+
expect{ @people = Person.where(:id => [1,2,3,4]).order("height DESC").all }.to use_cache(Person).on(:id)
|
167
|
+
expect(@people.map(&:height)).to eq([1.83, 1.75, 1.75, 1.69])
|
153
168
|
end
|
154
169
|
|
155
170
|
it "should sort on multiple fields (ASC + ASC)" do
|
156
|
-
|
157
|
-
@people.map(&:height).
|
158
|
-
@people.map(&:id).
|
171
|
+
expect{ @people = Person.where(:id => [2,3,4,5]).order("height ASC, id ASC").all }.to use_cache(Person).on(:id)
|
172
|
+
expect(@people.map(&:height)).to eq([1.69, 1.75, 1.75, 1.91])
|
173
|
+
expect(@people.map(&:id)).to eq([4, 2, 3, 5])
|
159
174
|
end
|
160
175
|
|
161
176
|
it "should sort on multiple fields (ASC + DESC)" do
|
162
|
-
|
163
|
-
@people.map(&:height).
|
164
|
-
@people.map(&:id).
|
177
|
+
expect{ @people = Person.where(:id => [2,3,4,5]).order("height ASC, id DESC").all }.to use_cache(Person).on(:id)
|
178
|
+
expect(@people.map(&:height)).to eq([1.69, 1.75, 1.75, 1.91])
|
179
|
+
expect(@people.map(&:id)).to eq([4, 3, 2, 5])
|
165
180
|
end
|
166
181
|
|
167
182
|
it "should sort on multiple fields (DESC + ASC)" do
|
168
|
-
|
169
|
-
@people.map(&:height).
|
170
|
-
@people.map(&:id).
|
183
|
+
expect{ @people = Person.where(:id => [2,3,4,5]).order("height DESC, id ASC").all }.to use_cache(Person).on(:id)
|
184
|
+
expect(@people.map(&:height)).to eq([1.91, 1.75, 1.75, 1.69])
|
185
|
+
expect(@people.map(&:id)).to eq([5, 2, 3, 4])
|
171
186
|
end
|
172
187
|
|
173
188
|
it "should sort on multiple fields (DESC + DESC)" do
|
174
|
-
|
175
|
-
@people.map(&:height).
|
176
|
-
@people.map(&:id).
|
189
|
+
expect{ @people = Person.where(:id => [2,3,4,5]).order("height DESC, id DESC").all }.to use_cache(Person).on(:id)
|
190
|
+
expect(@people.map(&:height)).to eq([1.91, 1.75, 1.75, 1.69])
|
191
|
+
expect(@people.map(&:id)).to eq([5, 3, 2, 4])
|
177
192
|
end
|
178
193
|
|
179
194
|
it "should use mysql style collation" do
|
@@ -192,42 +207,38 @@ describe RecordCache::Strategy::Base do
|
|
192
207
|
ids << Person.create!(:name => "čedriĉ ꜩ Last").id # latin special, with latin non-collateable
|
193
208
|
|
194
209
|
names_asc = ["1 cedric", "a cedric", "cedric 1", "Cedric 2", "ċedriĉ 3", "čedriĉ 4", "ćedriĉ Last", "čedriĉ คฉ Almost last cedric", "čedriĉ ꜩ Last", "sedric 1", "Sedric 2", "คฉ Really last"]
|
195
|
-
|
196
|
-
@people.map(&:name).
|
210
|
+
expect{ @people = Person.where(:id => ids).order("name ASC").all }.to hit_cache(Person).on(:id).times(ids.size)
|
211
|
+
expect(@people.map(&:name)).to eq(names_asc)
|
197
212
|
|
198
|
-
|
199
|
-
@people.map(&:name).
|
213
|
+
expect{ @people = Person.where(:id => ids).order("name DESC").all }.to hit_cache(Person).on(:id).times(ids.size)
|
214
|
+
expect(@people.map(&:name)).to eq(names_asc.reverse)
|
200
215
|
end
|
201
216
|
end
|
202
217
|
|
203
218
|
it "should combine filter and sort" do
|
204
|
-
|
205
|
-
@people.size.
|
206
|
-
@people.map(&:name).
|
219
|
+
expect{ @people = Person.where(:id => [1,2,3]).where(:height => 1.75).order("name DESC").all }.to use_cache(Person).on(:id)
|
220
|
+
expect(@people.size).to eq(2)
|
221
|
+
expect(@people.map(&:name)).to eq(["Cris", "Blue"])
|
207
222
|
|
208
|
-
|
209
|
-
@people.map(&:name).
|
223
|
+
expect{ @people = Person.where(:id => [1,2,3]).where(:height => 1.75).order("name").all }.to hit_cache(Person).on(:id).times(3)
|
224
|
+
expect(@people.map(&:name)).to eq(["Blue", "Cris"])
|
210
225
|
end
|
211
226
|
|
212
227
|
context "NotImplementedError" do
|
213
228
|
before(:each) do
|
214
|
-
@invalid_strategy = RecordCache::Strategy::Base.new(Object, nil, nil, "key")
|
229
|
+
@invalid_strategy = RecordCache::Strategy::Base.new(Object, nil, nil, {:key => "key"})
|
215
230
|
end
|
216
231
|
|
217
232
|
it "should require record_change to be implemented" do
|
218
|
-
|
233
|
+
expect{ @invalid_strategy.record_change(Object.new, 1) }.to raise_error(NotImplementedError)
|
219
234
|
end
|
220
235
|
|
221
236
|
it "should require cacheable? to be implemented" do
|
222
|
-
|
223
|
-
end
|
224
|
-
|
225
|
-
it "should require invalidate to be implemented" do
|
226
|
-
lambda { @invalid_strategy.invalidate(1) }.should raise_error(NotImplementedError)
|
237
|
+
expect{ @invalid_strategy.cacheable?(RecordCache::Query.new) }.to raise_error(NotImplementedError)
|
227
238
|
end
|
228
239
|
|
229
240
|
it "should fetch_records to be implemented" do
|
230
|
-
|
241
|
+
expect{ @invalid_strategy.fetch(RecordCache::Query.new) }.to raise_error(NotImplementedError)
|
231
242
|
end
|
232
243
|
end
|
233
244
|
end
|