low_card_tables 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.travis.yml +59 -0
- data/Gemfile +17 -0
- data/LICENSE +21 -0
- data/README.md +75 -0
- data/Rakefile +6 -0
- data/lib/low_card_tables.rb +72 -0
- data/lib/low_card_tables/active_record/base.rb +55 -0
- data/lib/low_card_tables/active_record/migrations.rb +223 -0
- data/lib/low_card_tables/active_record/relation.rb +35 -0
- data/lib/low_card_tables/active_record/scoping.rb +87 -0
- data/lib/low_card_tables/errors.rb +74 -0
- data/lib/low_card_tables/has_low_card_table/base.rb +114 -0
- data/lib/low_card_tables/has_low_card_table/low_card_association.rb +273 -0
- data/lib/low_card_tables/has_low_card_table/low_card_associations_manager.rb +143 -0
- data/lib/low_card_tables/has_low_card_table/low_card_dynamic_method_manager.rb +224 -0
- data/lib/low_card_tables/has_low_card_table/low_card_objects_manager.rb +80 -0
- data/lib/low_card_tables/low_card_table/base.rb +184 -0
- data/lib/low_card_tables/low_card_table/cache.rb +214 -0
- data/lib/low_card_tables/low_card_table/cache_expiration/exponential_cache_expiration_policy.rb +151 -0
- data/lib/low_card_tables/low_card_table/cache_expiration/fixed_cache_expiration_policy.rb +23 -0
- data/lib/low_card_tables/low_card_table/cache_expiration/has_cache_expiration.rb +100 -0
- data/lib/low_card_tables/low_card_table/cache_expiration/no_caching_expiration_policy.rb +13 -0
- data/lib/low_card_tables/low_card_table/cache_expiration/unlimited_cache_expiration_policy.rb +13 -0
- data/lib/low_card_tables/low_card_table/row_collapser.rb +175 -0
- data/lib/low_card_tables/low_card_table/row_manager.rb +681 -0
- data/lib/low_card_tables/low_card_table/table_unique_index.rb +134 -0
- data/lib/low_card_tables/version.rb +4 -0
- data/lib/low_card_tables/version_support.rb +52 -0
- data/low_card_tables.gemspec +69 -0
- data/spec/low_card_tables/helpers/database_helper.rb +148 -0
- data/spec/low_card_tables/helpers/query_spy_helper.rb +47 -0
- data/spec/low_card_tables/helpers/system_helpers.rb +63 -0
- data/spec/low_card_tables/system/basic_system_spec.rb +254 -0
- data/spec/low_card_tables/system/bulk_system_spec.rb +334 -0
- data/spec/low_card_tables/system/caching_system_spec.rb +531 -0
- data/spec/low_card_tables/system/migrations_system_spec.rb +747 -0
- data/spec/low_card_tables/system/options_system_spec.rb +581 -0
- data/spec/low_card_tables/system/queries_system_spec.rb +142 -0
- data/spec/low_card_tables/system/validations_system_spec.rb +88 -0
- data/spec/low_card_tables/unit/active_record/base_spec.rb +53 -0
- data/spec/low_card_tables/unit/active_record/migrations_spec.rb +207 -0
- data/spec/low_card_tables/unit/active_record/relation_spec.rb +47 -0
- data/spec/low_card_tables/unit/active_record/scoping_spec.rb +101 -0
- data/spec/low_card_tables/unit/has_low_card_table/base_spec.rb +79 -0
- data/spec/low_card_tables/unit/has_low_card_table/low_card_association_spec.rb +287 -0
- data/spec/low_card_tables/unit/has_low_card_table/low_card_associations_manager_spec.rb +190 -0
- data/spec/low_card_tables/unit/has_low_card_table/low_card_dynamic_method_manager_spec.rb +234 -0
- data/spec/low_card_tables/unit/has_low_card_table/low_card_objects_manager_spec.rb +70 -0
- data/spec/low_card_tables/unit/low_card_table/base_spec.rb +207 -0
- data/spec/low_card_tables/unit/low_card_table/cache_expiration/exponential_cache_expiration_policy_spec.rb +128 -0
- data/spec/low_card_tables/unit/low_card_table/cache_expiration/fixed_cache_expiration_policy_spec.rb +25 -0
- data/spec/low_card_tables/unit/low_card_table/cache_expiration/has_cache_expiration_policy_spec.rb +100 -0
- data/spec/low_card_tables/unit/low_card_table/cache_expiration/no_caching_expiration_policy_spec.rb +14 -0
- data/spec/low_card_tables/unit/low_card_table/cache_expiration/unlimited_cache_expiration_policy_spec.rb +14 -0
- data/spec/low_card_tables/unit/low_card_table/cache_spec.rb +282 -0
- data/spec/low_card_tables/unit/low_card_table/row_collapser_spec.rb +109 -0
- data/spec/low_card_tables/unit/low_card_table/row_manager_spec.rb +918 -0
- data/spec/low_card_tables/unit/low_card_table/table_unique_index_spec.rb +117 -0
- metadata +206 -0
@@ -0,0 +1,207 @@
|
|
1
|
+
require 'low_card_tables'
|
2
|
+
|
3
|
+
describe LowCardTables::LowCardTable::Base do
|
4
|
+
before :each do
|
5
|
+
@test_class = Class.new
|
6
|
+
@test_class.send(:include, LowCardTables::LowCardTable::Base)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should make its recipient inherit the low-card policy from LowCardTables" do
|
10
|
+
LowCardTables.low_card_cache_expiration 20
|
11
|
+
@test_class.low_card_cache_expiration.should == 20
|
12
|
+
|
13
|
+
LowCardTables.low_card_cache_expiration 45
|
14
|
+
@test_class.low_card_cache_expiration.should == 45
|
15
|
+
end
|
16
|
+
|
17
|
+
context "with an instance" do
|
18
|
+
before :each do
|
19
|
+
@instance = @test_class.new
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "row-matching" do
|
23
|
+
it "should match columns by hash-indexing, by default" do
|
24
|
+
expect(@instance).to receive(:[]).with('foo').twice.and_return(:bar)
|
25
|
+
|
26
|
+
@instance._low_card_column_matches?(:foo, :bar).should be
|
27
|
+
@instance._low_card_column_matches?(:foo, :baz).should_not be
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should match a hash one-by-one, by calling through to _low_card_column_matches?" do
|
31
|
+
expect(@instance).to receive(:_low_card_column_matches?).with(:foo, :bar).and_return(true)
|
32
|
+
expect(@instance).to receive(:_low_card_column_matches?).with(:baz, :quux).and_return(true)
|
33
|
+
|
34
|
+
@instance._low_card_row_matches_hash?(:foo => :bar, :baz => :quux).should be
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should not match a different hash, by calling through to _low_card_column_matches?" do
|
38
|
+
expect(@instance).to receive(:_low_card_column_matches?).with(:foo, :bar).and_return(false)
|
39
|
+
|
40
|
+
@instance._low_card_row_matches_hash?(:foo => :bar).should_not be
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should always match if the hash contains nothing" do
|
44
|
+
@instance._low_card_row_matches_hash?({ }).should be
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should match a set of hashes, by looking for one that matches, by calling through to _low_card_row_matches_hash?" do
|
48
|
+
h1 = { :foo => :bar, :bar => :baz }
|
49
|
+
h2 = { :a => :b, 'c' => 12345 }
|
50
|
+
|
51
|
+
expect(@instance).to receive(:_low_card_row_matches_hash?).with(h1).and_return(false)
|
52
|
+
expect(@instance).to receive(:_low_card_row_matches_hash?).with(h2).and_return(true)
|
53
|
+
|
54
|
+
@instance._low_card_row_matches_any_hash?([ h1, h2 ]).should be
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should fail to match a set of hashes, by looking for one that matches, by calling through to _low_card_row_matches_hash?" do
|
58
|
+
h1 = { :foo => :bar, :bar => :baz }
|
59
|
+
h2 = { :a => :b, 'c' => 12345 }
|
60
|
+
|
61
|
+
expect(@instance).to receive(:_low_card_row_matches_hash?).with(h1).and_return(false)
|
62
|
+
expect(@instance).to receive(:_low_card_row_matches_hash?).with(h2).and_return(false)
|
63
|
+
|
64
|
+
@instance._low_card_row_matches_any_hash?([ h1, h2 ]).should_not be
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should match blocks by calling them" do
|
68
|
+
block = double("block")
|
69
|
+
|
70
|
+
expect(block).to receive(:call).once.with(@instance).and_return(true)
|
71
|
+
@instance._low_card_row_matches_block?(block).should be
|
72
|
+
|
73
|
+
expect(block).to receive(:call).once.with(@instance).and_return(false)
|
74
|
+
@instance._low_card_row_matches_block?(block).should_not be
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should save and return options properly" do
|
80
|
+
@test_class.is_low_card_table(:foo => :bar, :baz => :quux)
|
81
|
+
@test_class.low_card_options.should == { :foo => :bar, :baz => :quux }
|
82
|
+
|
83
|
+
@test_class.low_card_options = { :a => :b, :c => :d }
|
84
|
+
@test_class.low_card_options.should == { :a => :b, :c => :d }
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should declare that it's a low-card table" do
|
88
|
+
@test_class.is_low_card_table?.should be
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "row manager" do
|
92
|
+
it "should create a row manager of the right class, by default" do
|
93
|
+
rm = @test_class._low_card_row_manager
|
94
|
+
@test_class._low_card_row_manager.should be(rm)
|
95
|
+
|
96
|
+
rm.class.should == LowCardTables::LowCardTable::RowManager
|
97
|
+
rm.low_card_model.should be(@test_class)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should call through to the row manager on #reset_column_information" do
|
101
|
+
mod = Module.new
|
102
|
+
mod.module_eval do
|
103
|
+
def reset_column_information
|
104
|
+
@_reset_column_information_calls ||= 0
|
105
|
+
@_reset_column_information_calls += 1
|
106
|
+
:reset_column_information_return_value
|
107
|
+
end
|
108
|
+
|
109
|
+
def reset_column_information_calls
|
110
|
+
@_reset_column_information_calls
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
test_class = Class.new
|
115
|
+
test_class.send(:extend, mod)
|
116
|
+
test_class.send(:include, LowCardTables::LowCardTable::Base)
|
117
|
+
|
118
|
+
rm = double("row_manager")
|
119
|
+
allow(test_class).to receive(:_low_card_row_manager).and_return(rm)
|
120
|
+
|
121
|
+
expect(rm).to receive(:column_information_reset!).once
|
122
|
+
|
123
|
+
test_class.reset_column_information.should == :reset_column_information_return_value
|
124
|
+
test_class.reset_column_information_calls.should == 1
|
125
|
+
end
|
126
|
+
|
127
|
+
context "with a mock row manager" do
|
128
|
+
before :each do
|
129
|
+
@rm = double("row_manager")
|
130
|
+
allow(@test_class).to receive(:_low_card_row_manager).and_return(@rm)
|
131
|
+
end
|
132
|
+
|
133
|
+
%w{all_rows row_for_id rows_for_ids rows_matching ids_matching find_ids_for find_or_create_ids_for
|
134
|
+
find_rows_for find_or_create_rows_for flush_cache! referring_models collapse_rows_and_update_referrers!
|
135
|
+
value_column_names referred_to_by
|
136
|
+
ensure_has_unique_index! remove_unique_index!}.each do |method_name|
|
137
|
+
it "should delegate to the row manager for #{method_name}" do
|
138
|
+
expect(@rm).to receive(method_name).once.with(:foo, :bar).and_return(:baz)
|
139
|
+
@test_class.send("low_card_#{method_name}", :foo, :bar).should == :baz
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
context "saving" do
|
146
|
+
before :each do
|
147
|
+
@save_mod = Module.new
|
148
|
+
@save_mod.module_eval do
|
149
|
+
def save(*args)
|
150
|
+
_saves_called << [ :save, args ]
|
151
|
+
:save_return_value
|
152
|
+
end
|
153
|
+
|
154
|
+
def save!(*args)
|
155
|
+
_saves_called << [ :save!, args ]
|
156
|
+
:save_return_value!
|
157
|
+
end
|
158
|
+
|
159
|
+
def _saves_called
|
160
|
+
@_saves_called ||= [ ]
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
# We need a new class -- because we need to make sure our module gets in there first
|
165
|
+
@test_class = Class.new
|
166
|
+
@test_class.send(:include, @save_mod)
|
167
|
+
@test_class.send(:include, LowCardTables::LowCardTable::Base)
|
168
|
+
|
169
|
+
@test_class.is_low_card_table
|
170
|
+
@test_class.is_low_card_table # ensure that calling it twice doesn't mess anything up
|
171
|
+
|
172
|
+
@instance = @test_class.new
|
173
|
+
end
|
174
|
+
|
175
|
+
it "should refuse to save, by default" do
|
176
|
+
lambda { @instance.save }.should raise_error(LowCardTables::Errors::LowCardCannotSaveAssociatedLowCardObjectsError)
|
177
|
+
@instance._saves_called.length.should == 0
|
178
|
+
|
179
|
+
lambda { @instance.save! }.should raise_error(LowCardTables::Errors::LowCardCannotSaveAssociatedLowCardObjectsError)
|
180
|
+
@instance._saves_called.length.should == 0
|
181
|
+
end
|
182
|
+
|
183
|
+
it "should save, if invoked via #save_low_card_row" do
|
184
|
+
@instance.save_low_card_row(:foo, :bar).should == :save_return_value
|
185
|
+
@instance._saves_called.should == [ [ :save, [ :foo, :bar ] ] ]
|
186
|
+
end
|
187
|
+
|
188
|
+
it "should save, if invoked via #save_low_card_row!" do
|
189
|
+
@instance.save_low_card_row!(:foo, :bar).should == :save_return_value!
|
190
|
+
@instance._saves_called.should == [ [ :save!, [ :foo, :bar ] ] ]
|
191
|
+
end
|
192
|
+
|
193
|
+
it "should not accidentally continue allowing saves if save! blows up" do
|
194
|
+
@save_mod.module_eval do
|
195
|
+
def save!(*args)
|
196
|
+
_saves_called << [ :save!, args ]
|
197
|
+
raise "kaboom"
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
lambda { @instance.save_low_card_row!(:foo, :bar) }.should raise_error(/kaboom/i)
|
202
|
+
@instance._saves_called.should == [ [ :save!, [ :foo, :bar ] ] ]
|
203
|
+
|
204
|
+
lambda { @instance.save! }.should raise_error(LowCardTables::Errors::LowCardCannotSaveAssociatedLowCardObjectsError)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'low_card_tables'
|
2
|
+
require 'active_support/time'
|
3
|
+
|
4
|
+
describe LowCardTables::LowCardTable::CacheExpiration::ExponentialCacheExpirationPolicy do
|
5
|
+
def klass
|
6
|
+
LowCardTables::LowCardTable::CacheExpiration::ExponentialCacheExpirationPolicy
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should create itself with default values" do
|
10
|
+
instance = klass.new({ :start_time => Time.now })
|
11
|
+
|
12
|
+
instance.zero_floor.should == 3.minutes
|
13
|
+
instance.min_time.should == 10.seconds
|
14
|
+
instance.exponent.should == 2.0
|
15
|
+
instance.max_time.should == 1.hour
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should prevent specifying invalid values" do
|
19
|
+
lambda { klass.new(:start_time => Time.now, :zero_floor_time => 'foo') }.should raise_error(ArgumentError, /zero_floor_time/i)
|
20
|
+
lambda { klass.new(:start_time => Time.now, :zero_floor_time => -1.0) }.should raise_error(ArgumentError, /zero_floor_time/i)
|
21
|
+
|
22
|
+
lambda { klass.new(:start_time => Time.now, :min_time => 'foo') }.should raise_error(ArgumentError, /min_time/i)
|
23
|
+
lambda { klass.new(:start_time => Time.now, :min_time => -1.0) }.should raise_error(ArgumentError, /min_time/i)
|
24
|
+
lambda { klass.new(:start_time => Time.now, :min_time => 0.0) }.should raise_error(ArgumentError, /min_time/i)
|
25
|
+
lambda { klass.new(:start_time => Time.now, :min_time => 1.0) }.should raise_error(ArgumentError, /min_time/i)
|
26
|
+
|
27
|
+
lambda { klass.new(:start_time => Time.now, :exponent => 'foo') }.should raise_error(ArgumentError, /exponent/i)
|
28
|
+
lambda { klass.new(:start_time => Time.now, :exponent => -1.0) }.should raise_error(ArgumentError, /exponent/i)
|
29
|
+
lambda { klass.new(:start_time => Time.now, :exponent => 0.0) }.should raise_error(ArgumentError, /exponent/i)
|
30
|
+
lambda { klass.new(:start_time => Time.now, :exponent => 1.0) }.should raise_error(ArgumentError, /exponent/i)
|
31
|
+
|
32
|
+
lambda { klass.new(:start_time => Time.now, :max_time => 'foo') }.should raise_error(ArgumentError, /max_time/i)
|
33
|
+
lambda { klass.new(:start_time => Time.now, :max_time => 0.0) }.should raise_error(ArgumentError, /max_time/i)
|
34
|
+
lambda { klass.new(:start_time => Time.now, :max_time => -1.0) }.should raise_error(ArgumentError, /max_time/i)
|
35
|
+
lambda { klass.new(:start_time => Time.now, :min_time => 3.0, :max_time => 2.0) }.should raise_error(ArgumentError, /max_time/i)
|
36
|
+
end
|
37
|
+
|
38
|
+
def with_instance(options = { })
|
39
|
+
@start_time = Time.now
|
40
|
+
@cache_read_at = @start_time
|
41
|
+
@instance = klass.new(options.merge(:start_time => @start_time))
|
42
|
+
|
43
|
+
yield
|
44
|
+
end
|
45
|
+
|
46
|
+
def refill!(time)
|
47
|
+
@cache_read_at = @start_time + time
|
48
|
+
end
|
49
|
+
|
50
|
+
def should_be_stale!(time)
|
51
|
+
@instance.stale?(@cache_read_at, @start_time + time).should be
|
52
|
+
end
|
53
|
+
|
54
|
+
def should_not_be_stale!(time)
|
55
|
+
@instance.stale?(@cache_read_at, @start_time + time).should_not be
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should have a zero floor that's adjustable" do
|
59
|
+
with_instance(:zero_floor_time => 1.0) do
|
60
|
+
should_be_stale!(0.0)
|
61
|
+
should_be_stale!(0.5)
|
62
|
+
should_be_stale!(0.9)
|
63
|
+
|
64
|
+
refill!(1.0)
|
65
|
+
should_not_be_stale!(1.1)
|
66
|
+
end
|
67
|
+
|
68
|
+
with_instance(:zero_floor_time => 0.0) do
|
69
|
+
should_not_be_stale!(0.0)
|
70
|
+
|
71
|
+
refill!(0.5)
|
72
|
+
should_not_be_stale!(0.6)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should start an initial period of min_time seconds" do
|
77
|
+
with_instance(:zero_floor_time => 1.0, :min_time => 3.0) do
|
78
|
+
should_be_stale!(1.0)
|
79
|
+
refill!(1.0)
|
80
|
+
|
81
|
+
should_not_be_stale!(1.5)
|
82
|
+
should_not_be_stale!(3.0)
|
83
|
+
should_not_be_stale!(3.9)
|
84
|
+
should_be_stale!(4.1)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should exponentially increase according to the exponent" do
|
89
|
+
with_instance(:zero_floor_time => 1.0, :min_time => 3.0, :exponent => 1.5) do
|
90
|
+
# period 1: 1.0 - 4.0 seconds (3.0 duration)
|
91
|
+
refill!(1.0)
|
92
|
+
should_not_be_stale!(3.9)
|
93
|
+
|
94
|
+
# period 2: 4.0 - 8.5 seconds (4.5 duration)
|
95
|
+
refill!(4.0)
|
96
|
+
should_not_be_stale!(4.0)
|
97
|
+
should_not_be_stale!(7.0)
|
98
|
+
should_not_be_stale!(8.4)
|
99
|
+
should_be_stale!(8.5)
|
100
|
+
|
101
|
+
# period 3: 8.5 - 15.25 seconds (6.75 duration)
|
102
|
+
refill!(8.5)
|
103
|
+
should_not_be_stale!(8.5)
|
104
|
+
should_not_be_stale!(12.0)
|
105
|
+
should_not_be_stale!(15.0)
|
106
|
+
should_be_stale!(15.25)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should cap out at the max_time" do
|
111
|
+
with_instance(:zero_floor_time => 1.0, :min_time => 5.0, :exponent => 100.0, :max_time => 10.0) do
|
112
|
+
# zero floor: 0.0-1.0
|
113
|
+
# period 1: 1.0-6.0
|
114
|
+
# period 2: 6.0-16.0
|
115
|
+
refill!(6.0)
|
116
|
+
|
117
|
+
should_not_be_stale!(6.0)
|
118
|
+
should_not_be_stale!(15.9)
|
119
|
+
should_be_stale!(16.0)
|
120
|
+
|
121
|
+
# period 3: 16.0-26.0
|
122
|
+
refill!(16.0)
|
123
|
+
should_not_be_stale!(16.0)
|
124
|
+
should_not_be_stale!(25.9)
|
125
|
+
should_be_stale!(26.0)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
data/spec/low_card_tables/unit/low_card_table/cache_expiration/fixed_cache_expiration_policy_spec.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'low_card_tables'
|
2
|
+
|
3
|
+
describe LowCardTables::LowCardTable::CacheExpiration::FixedCacheExpirationPolicy do
|
4
|
+
def klass
|
5
|
+
LowCardTables::LowCardTable::CacheExpiration::FixedCacheExpirationPolicy
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should require a non-negative expiration time" do
|
9
|
+
lambda { klass.new("foo") }.should raise_error(ArgumentError)
|
10
|
+
lambda { klass.new(-1.0) }.should raise_error(ArgumentError)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should expire at that time" do
|
14
|
+
i = klass.new(1.0)
|
15
|
+
|
16
|
+
i.expiration_time.should == 1.0
|
17
|
+
|
18
|
+
the_time = Time.now - rand(100_000)
|
19
|
+
i.stale?(the_time, the_time).should_not be
|
20
|
+
i.stale?(the_time, the_time + 0.5).should_not be
|
21
|
+
i.stale?(the_time, the_time + 0.99).should_not be
|
22
|
+
i.stale?(the_time, the_time + 1.0).should be
|
23
|
+
i.stale?(the_time, the_time + 15.0).should be
|
24
|
+
end
|
25
|
+
end
|
data/spec/low_card_tables/unit/low_card_table/cache_expiration/has_cache_expiration_policy_spec.rb
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'low_card_tables'
|
2
|
+
require 'active_support/time'
|
3
|
+
|
4
|
+
describe LowCardTables::LowCardTable::CacheExpiration::HasCacheExpiration do
|
5
|
+
before :each do
|
6
|
+
@test_class = Class.new
|
7
|
+
@test_class.send(:include, LowCardTables::LowCardTable::CacheExpiration::HasCacheExpiration)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should default to no policy" do
|
11
|
+
@test_class.low_card_cache_expiration.should be_nil
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should allow setting to a no-caching policy" do
|
15
|
+
@test_class.low_card_cache_expiration 0
|
16
|
+
@test_class.low_card_cache_expiration.should == 0
|
17
|
+
@test_class.low_card_cache_expiration_policy_object.class.should == LowCardTables::LowCardTable::CacheExpiration::NoCachingExpirationPolicy
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should allow setting to a fixed policy" do
|
21
|
+
@test_class.low_card_cache_expiration 15
|
22
|
+
@test_class.low_card_cache_expiration.should == 15
|
23
|
+
@test_class.low_card_cache_expiration_policy_object.class.should == LowCardTables::LowCardTable::CacheExpiration::FixedCacheExpirationPolicy
|
24
|
+
@test_class.low_card_cache_expiration_policy_object.expiration_time.should == 15
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should allow setting to an unlimited policy" do
|
28
|
+
@test_class.low_card_cache_expiration :unlimited
|
29
|
+
@test_class.low_card_cache_expiration.should == :unlimited
|
30
|
+
@test_class.low_card_cache_expiration_policy_object.class.should == LowCardTables::LowCardTable::CacheExpiration::UnlimitedCacheExpirationPolicy
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should allow setting to an exponential policy, with defaults" do
|
34
|
+
@test_class.low_card_cache_expiration :exponential
|
35
|
+
@test_class.low_card_cache_expiration.should == :exponential
|
36
|
+
@test_class.low_card_cache_expiration_policy_object.class.should == LowCardTables::LowCardTable::CacheExpiration::ExponentialCacheExpirationPolicy
|
37
|
+
@test_class.low_card_cache_expiration_policy_object.zero_floor.should == 3.minutes
|
38
|
+
@test_class.low_card_cache_expiration_policy_object.min_time.should == 10.seconds
|
39
|
+
@test_class.low_card_cache_expiration_policy_object.exponent.should == 2.0
|
40
|
+
@test_class.low_card_cache_expiration_policy_object.max_time.should == 1.hour
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should allow setting to an exponential policy, with overrides" do
|
44
|
+
@test_class.low_card_cache_expiration :exponential, :zero_floor_time => 2.0, :min_time => 3.0, :exponent => 4.0, :max_time => 5.0
|
45
|
+
@test_class.low_card_cache_expiration.should == [ :exponential, { :zero_floor_time => 2.0, :min_time => 3.0, :exponent => 4.0, :max_time => 5.0 } ]
|
46
|
+
@test_class.low_card_cache_expiration_policy_object.class.should == LowCardTables::LowCardTable::CacheExpiration::ExponentialCacheExpirationPolicy
|
47
|
+
@test_class.low_card_cache_expiration_policy_object.zero_floor.should == 2.0
|
48
|
+
@test_class.low_card_cache_expiration_policy_object.min_time.should == 3.0
|
49
|
+
@test_class.low_card_cache_expiration_policy_object.exponent.should == 4.0
|
50
|
+
@test_class.low_card_cache_expiration_policy_object.max_time.should == 5.0
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should allow changing the policy" do
|
54
|
+
@test_class.low_card_cache_expiration 15
|
55
|
+
@test_class.low_card_cache_expiration.should == 15
|
56
|
+
@test_class.low_card_cache_expiration :unlimited
|
57
|
+
@test_class.low_card_cache_expiration.should == :unlimited
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should not change the policy if there's an exception" do
|
61
|
+
@test_class.low_card_cache_expiration 15
|
62
|
+
@test_class.low_card_cache_expiration.should == 15
|
63
|
+
|
64
|
+
lambda { @test_class.low_card_cache_expiration :exponential, :zero_floor_time => -10.0 }.should raise_error(ArgumentError)
|
65
|
+
|
66
|
+
@test_class.low_card_cache_expiration.should == 15
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should fall back to the inherited class, if there is one" do
|
70
|
+
@parent_class = Class.new
|
71
|
+
@parent_class.send(:include, LowCardTables::LowCardTable::CacheExpiration::HasCacheExpiration)
|
72
|
+
|
73
|
+
@test_class.low_card_cache_policy_inherits_from(@parent_class)
|
74
|
+
|
75
|
+
@test_class.low_card_cache_expiration.should be_nil
|
76
|
+
@test_class.low_card_cache_expiration_policy_object.should be_nil
|
77
|
+
|
78
|
+
@parent_class.low_card_cache_expiration 15
|
79
|
+
@parent_class.low_card_cache_expiration.should == 15
|
80
|
+
@parent_class.low_card_cache_expiration_policy_object.class.should == LowCardTables::LowCardTable::CacheExpiration::FixedCacheExpirationPolicy
|
81
|
+
@parent_class.low_card_cache_expiration_policy_object.expiration_time.should == 15
|
82
|
+
@test_class.low_card_cache_expiration.should == 15
|
83
|
+
@test_class.low_card_cache_expiration_policy_object.class.should == LowCardTables::LowCardTable::CacheExpiration::FixedCacheExpirationPolicy
|
84
|
+
@test_class.low_card_cache_expiration_policy_object.expiration_time.should == 15
|
85
|
+
|
86
|
+
@parent_class.low_card_cache_expiration :exponential
|
87
|
+
@test_class.low_card_cache_expiration.should == :exponential
|
88
|
+
@test_class.low_card_cache_expiration_policy_object.class.should == LowCardTables::LowCardTable::CacheExpiration::ExponentialCacheExpirationPolicy
|
89
|
+
|
90
|
+
@test_class.low_card_cache_expiration 27
|
91
|
+
@test_class.low_card_cache_expiration.should == 27
|
92
|
+
@test_class.low_card_cache_expiration_policy_object.class.should == LowCardTables::LowCardTable::CacheExpiration::FixedCacheExpirationPolicy
|
93
|
+
@test_class.low_card_cache_expiration_policy_object.expiration_time.should == 27
|
94
|
+
|
95
|
+
@parent_class.low_card_cache_expiration 105
|
96
|
+
@test_class.low_card_cache_expiration.should == 27
|
97
|
+
@test_class.low_card_cache_expiration_policy_object.class.should == LowCardTables::LowCardTable::CacheExpiration::FixedCacheExpirationPolicy
|
98
|
+
@test_class.low_card_cache_expiration_policy_object.expiration_time.should == 27
|
99
|
+
end
|
100
|
+
end
|