active_record_tweaks 0.2.0 → 0.2.1
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 +4 -4
- data/.gitignore +7 -1
- data/.rubocop.yml +803 -0
- data/.travis.yml +17 -7
- data/Appraisals +26 -12
- data/Gemfile +1 -1
- data/README.md +36 -20
- data/Rakefile +5 -2
- data/active_record_tweaks.gemspec +11 -7
- data/gemfiles/rails_3_2.gemfile +10 -0
- data/gemfiles/rails_4_0.gemfile +10 -0
- data/gemfiles/rails_4_1.gemfile +10 -0
- data/gemfiles/rails_4_2.gemfile +10 -0
- data/lib/active_record_tweaks.rb +9 -7
- data/lib/active_record_tweaks/integration.rb +68 -53
- data/lib/active_record_tweaks/version.rb +5 -1
- data/spec/active_record_tweaks_spec.rb +228 -143
- data/spec/spec_helper.rb +14 -16
- metadata +69 -59
- data/gemfiles/rails3_2.gemfile +0 -8
- data/gemfiles/rails4_0.gemfile +0 -8
- data/gemfiles/rails4_1.gemfile +0 -8
@@ -1,76 +1,60 @@
|
|
1
|
-
require
|
1
|
+
require "spec_helper"
|
2
2
|
|
3
3
|
describe Parent do
|
4
|
-
describe
|
5
|
-
|
6
|
-
described_class.ancestors.
|
4
|
+
describe "included modules" do
|
5
|
+
specify do
|
6
|
+
expect(described_class.ancestors).to include(ActiveRecordTweaks)
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
|
-
describe
|
11
|
-
describe
|
10
|
+
describe "::Integration" do
|
11
|
+
describe "#cache_key_without_timestamp" do
|
12
12
|
subject { record.cache_key_without_timestamp }
|
13
13
|
|
14
|
-
|
15
|
-
context 'when record is a new record' do
|
14
|
+
context "when record is a new record" do
|
16
15
|
let(:record) { Parent.new }
|
17
16
|
|
18
|
-
it
|
17
|
+
it "works like #cache_key" do
|
19
18
|
should eq "#{record.class.model_name.cache_key}/new"
|
20
19
|
end
|
21
20
|
end
|
22
21
|
|
23
|
-
context
|
22
|
+
context "when record is an existing record" do
|
24
23
|
let(:record) { Parent.create! }
|
25
24
|
|
26
|
-
|
27
|
-
context 'and update_at is nil' do
|
25
|
+
context "and update_at is nil" do
|
28
26
|
before { record.update_attributes!(updated_at: nil) }
|
29
27
|
|
30
|
-
it
|
28
|
+
it "works like #cache_key" do
|
31
29
|
should eq "#{record.class.model_name.cache_key}/#{record.id}"
|
32
30
|
end
|
33
31
|
end
|
34
32
|
|
35
|
-
context
|
36
|
-
it
|
33
|
+
context "and update_at is present" do
|
34
|
+
it "works like #cache_key when updated_at is nil" do
|
37
35
|
should eq "#{record.class.model_name.cache_key}/#{record.id}"
|
38
36
|
end
|
39
37
|
end
|
40
38
|
end
|
41
39
|
|
42
|
-
context
|
40
|
+
context "when record has no update_at column" do
|
43
41
|
let!(:record) { Stone.create }
|
44
42
|
|
45
|
-
it
|
43
|
+
it "works like #cache_key when updated_at is nil" do
|
46
44
|
should eq "#{record.class.model_name.cache_key}/#{record.id}"
|
47
45
|
end
|
48
46
|
end
|
49
47
|
end
|
50
48
|
|
51
|
-
describe
|
49
|
+
describe "#cache_key_from_attribute" do
|
52
50
|
before { Timecop.freeze }
|
53
51
|
after { Timecop.return }
|
54
52
|
|
55
53
|
let!(:record) { Parent.create! }
|
56
54
|
|
57
55
|
before do
|
58
|
-
record.
|
59
|
-
|
60
|
-
1.day.from_now
|
61
|
-
end
|
62
|
-
|
63
|
-
def virtual_update_at_2
|
64
|
-
1.week.from_now
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
after do
|
69
|
-
record.class.class_eval do
|
70
|
-
remove_method :virtual_update_at_1
|
71
|
-
|
72
|
-
remove_method :virtual_update_at_2
|
73
|
-
end
|
56
|
+
allow(record).to receive(:virtual_update_at_1) { 1.day.from_now }
|
57
|
+
allow(record).to receive(:virtual_update_at_2) { 1.week.from_now }
|
74
58
|
end
|
75
59
|
|
76
60
|
let(:virtual_update_at_1) { record.virtual_update_at_1 }
|
@@ -80,121 +64,177 @@ describe Parent do
|
|
80
64
|
|
81
65
|
subject { record.cache_key_from_attribute(*arguments) }
|
82
66
|
|
83
|
-
context
|
67
|
+
context "when called with no argument" do
|
84
68
|
let(:arguments) { [] }
|
85
69
|
|
86
|
-
specify { expect{subject}.to raise_error(ArgumentError) }
|
70
|
+
specify { expect { subject }.to raise_error(ArgumentError) }
|
87
71
|
end
|
88
|
-
context
|
72
|
+
context "when called with 1 attribute name" do
|
89
73
|
let(:arguments) { [:virtual_update_at_1] }
|
90
74
|
|
91
|
-
it
|
75
|
+
context "when and it's present" do
|
76
|
+
it do
|
77
|
+
should match %r|
|
78
|
+
#{described_class.model_name.cache_key}
|
79
|
+
\/
|
80
|
+
#{record.id}
|
81
|
+
\-
|
82
|
+
#{virtual_update_at_1_in_cache_key}
|
83
|
+
|x
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context "when and it's nil" do
|
88
|
+
before do
|
89
|
+
allow(record).to receive(:virtual_update_at_1) { nil }
|
90
|
+
end
|
91
|
+
|
92
|
+
it do
|
93
|
+
should match %r|
|
94
|
+
#{described_class.model_name.cache_key}
|
95
|
+
\/
|
96
|
+
#{record.id}
|
97
|
+
|x
|
98
|
+
end
|
99
|
+
end
|
92
100
|
end
|
93
|
-
context
|
101
|
+
context "when called with 2 attribute names" do
|
94
102
|
let(:arguments) { [:virtual_update_at_1, :virtual_update_at_2] }
|
95
103
|
|
96
|
-
context
|
104
|
+
context "and #virtual_update_at_1 < #virtual_update_at_2" do
|
97
105
|
before do
|
98
|
-
record.
|
99
|
-
def virtual_update_at_2
|
100
|
-
virtual_update_at_1 + 1.day
|
101
|
-
end
|
102
|
-
end
|
106
|
+
allow(record).to receive(:virtual_update_at_2) { virtual_update_at_1 + 1.day }
|
103
107
|
end
|
104
108
|
|
105
|
-
it
|
109
|
+
it do
|
110
|
+
should match %r|
|
111
|
+
#{described_class.model_name.cache_key}
|
112
|
+
\/
|
113
|
+
#{record.id}
|
114
|
+
\-
|
115
|
+
#{virtual_update_at_2_in_cache_key}
|
116
|
+
|x
|
117
|
+
end
|
106
118
|
end
|
107
119
|
|
108
|
-
context
|
120
|
+
context "and #virtual_update_at_1 > #virtual_update_at_2" do
|
109
121
|
before do
|
110
|
-
record.
|
111
|
-
def virtual_update_at_2
|
112
|
-
virtual_update_at_1 - 1.day
|
113
|
-
end
|
114
|
-
end
|
122
|
+
allow(record).to receive(:virtual_update_at_2) { virtual_update_at_1 - 1.day }
|
115
123
|
end
|
116
124
|
|
117
|
-
it
|
125
|
+
it do
|
126
|
+
should match %r|
|
127
|
+
#{described_class.model_name.cache_key}
|
128
|
+
\/
|
129
|
+
#{record.id}
|
130
|
+
\-
|
131
|
+
#{virtual_update_at_1_in_cache_key}
|
132
|
+
|x
|
133
|
+
end
|
118
134
|
end
|
119
135
|
|
120
|
-
context
|
136
|
+
context "and #virtual_update_at_1 is nil" do
|
121
137
|
before do
|
122
|
-
record.
|
123
|
-
def virtual_update_at_1
|
124
|
-
nil
|
125
|
-
end
|
126
|
-
end
|
138
|
+
allow(record).to receive(:virtual_update_at_1) { nil }
|
127
139
|
end
|
128
140
|
|
129
|
-
it
|
141
|
+
it do
|
142
|
+
should match %r|
|
143
|
+
#{described_class.model_name.cache_key}
|
144
|
+
\/
|
145
|
+
#{record.id}
|
146
|
+
\-
|
147
|
+
#{virtual_update_at_2_in_cache_key}
|
148
|
+
|x
|
149
|
+
end
|
130
150
|
end
|
131
|
-
context
|
151
|
+
context "and #virtual_update_at_2 is nil" do
|
132
152
|
before do
|
133
|
-
record.
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
153
|
+
allow(record).to receive(:virtual_update_at_2) { nil }
|
154
|
+
end
|
155
|
+
|
156
|
+
it do
|
157
|
+
should match %r|
|
158
|
+
#{described_class.model_name.cache_key}
|
159
|
+
\/
|
160
|
+
#{record.id}
|
161
|
+
\-
|
162
|
+
#{virtual_update_at_1_in_cache_key}
|
163
|
+
|x
|
164
|
+
end
|
165
|
+
end
|
166
|
+
context "and both are nil" do
|
167
|
+
before do
|
168
|
+
allow(record).to receive(:virtual_update_at_1) { nil }
|
169
|
+
allow(record).to receive(:virtual_update_at_2) { nil }
|
138
170
|
end
|
139
171
|
|
140
|
-
it
|
172
|
+
it do
|
173
|
+
should match %r|
|
174
|
+
#{described_class.model_name.cache_key}
|
175
|
+
\/
|
176
|
+
#{record.id}
|
177
|
+
|x
|
178
|
+
end
|
141
179
|
end
|
142
180
|
end
|
143
181
|
end
|
144
182
|
|
145
|
-
|
146
|
-
describe '.cache_key' do
|
183
|
+
describe ".cache_key" do
|
147
184
|
subject { klass.cache_key }
|
148
185
|
|
149
|
-
context
|
186
|
+
context "when a class has no update_at column" do
|
150
187
|
let(:klass) { Stone }
|
151
188
|
|
152
|
-
context
|
153
|
-
before { klass.count.
|
189
|
+
context "and has no record" do
|
190
|
+
before { expect(klass.count).to eq 0 }
|
154
191
|
|
155
|
-
it { should match
|
192
|
+
it { should match %r|\/#{klass.count}$| }
|
156
193
|
end
|
157
|
-
context
|
194
|
+
context "and has a record" do
|
158
195
|
before { klass.create! }
|
159
196
|
|
160
|
-
it { should match
|
197
|
+
it { should match %r|\/#{klass.count}$| }
|
161
198
|
end
|
162
199
|
end
|
163
200
|
|
164
|
-
context
|
201
|
+
context "when a class has updated_at column" do
|
165
202
|
let(:klass) { Parent }
|
166
203
|
|
167
|
-
context
|
168
|
-
before { klass.count.
|
204
|
+
context "and has no record" do
|
205
|
+
before { expect(klass.count).to eq 0 }
|
169
206
|
|
170
|
-
it { should match
|
207
|
+
it { should match %r|\/#{klass.count}$| }
|
171
208
|
end
|
172
209
|
|
173
|
-
context
|
210
|
+
context "and has a record" do
|
174
211
|
let!(:parent) { klass.create! }
|
175
212
|
|
176
|
-
it
|
213
|
+
it do
|
214
|
+
should eq "parents/all/"\
|
215
|
+
"#{klass.count}-#{klass.maximum(:updated_at).utc.to_s(:nsec)}"
|
216
|
+
end
|
177
217
|
|
178
|
-
context
|
218
|
+
context "when record all has nil updated timestamps" do
|
179
219
|
before { klass.update_all(updated_at: nil) }
|
180
220
|
|
181
|
-
it { should match
|
221
|
+
it { should match %r|\/#{klass.count}$| }
|
182
222
|
end
|
183
223
|
|
184
|
-
describe
|
224
|
+
describe "precision" do
|
185
225
|
let!(:child) { Child.create!(parent: parent) }
|
186
226
|
let!(:old_cache_key) { klass.cache_key }
|
187
227
|
let(:new_cache_key) { klass.cache_key }
|
188
228
|
|
189
229
|
subject { new_cache_key }
|
190
230
|
|
191
|
-
context
|
231
|
+
context "when self touched" do
|
192
232
|
before { parent.touch }
|
193
233
|
|
194
234
|
it { should_not eq old_cache_key }
|
195
235
|
end
|
196
236
|
|
197
|
-
context
|
237
|
+
context "when child touched" do
|
198
238
|
before { child.touch }
|
199
239
|
|
200
240
|
it { should_not eq old_cache_key }
|
@@ -203,90 +243,132 @@ describe Parent do
|
|
203
243
|
end
|
204
244
|
end
|
205
245
|
|
206
|
-
context
|
246
|
+
context "when a class has updated_at AND updated_on column" do
|
207
247
|
let(:klass) { Person }
|
208
248
|
|
209
|
-
context
|
249
|
+
context "when getting cache_key using update_on column" do
|
210
250
|
subject { klass.cache_key(:updated_on) }
|
211
251
|
|
212
|
-
context
|
213
|
-
before { klass.count.
|
252
|
+
context "and has no record" do
|
253
|
+
before { expect(klass.count).to eq 0 }
|
214
254
|
|
215
|
-
it { should match
|
255
|
+
it { should match %r|\/#{klass.count}$| }
|
216
256
|
end
|
217
|
-
context
|
257
|
+
context "and has a record" do
|
218
258
|
let!(:person) { klass.create! }
|
219
259
|
|
220
|
-
context
|
260
|
+
context "and it has updated_at value only" do
|
221
261
|
before { person.update_attributes!(updated_at: Time.now, updated_on: nil) }
|
222
262
|
|
223
263
|
it { should eq "people/all/#{klass.count}" }
|
224
264
|
end
|
225
265
|
|
226
|
-
context
|
266
|
+
context "and it has updated_on value only" do
|
227
267
|
before { person.update_attributes!(updated_at: nil, updated_on: Time.now) }
|
228
268
|
|
229
|
-
it
|
269
|
+
it do
|
270
|
+
should eq "people/all/"\
|
271
|
+
"#{klass.count}-#{klass.maximum(:updated_on).utc.to_s(:nsec)}"
|
272
|
+
end
|
230
273
|
end
|
231
274
|
end
|
232
275
|
end
|
233
276
|
|
234
|
-
context
|
277
|
+
context "when getting cache_key using both columns" do
|
235
278
|
subject { klass.cache_key(:updated_at, :updated_on) }
|
236
279
|
|
237
|
-
context
|
238
|
-
before { klass.count.
|
280
|
+
context "and has no record" do
|
281
|
+
before { expect(klass.count).to eq 0 }
|
239
282
|
|
240
|
-
it { should match
|
283
|
+
it { should match %r|\/#{klass.count}$| }
|
241
284
|
end
|
242
|
-
context
|
285
|
+
context "and has a record" do
|
243
286
|
let!(:person) { klass.create! }
|
244
287
|
|
245
|
-
context
|
246
|
-
before
|
288
|
+
context "and it has updated_on value only" do
|
289
|
+
before do
|
290
|
+
person.update_attributes!(
|
291
|
+
updated_at: nil,
|
292
|
+
updated_on: Time.now,
|
293
|
+
)
|
294
|
+
end
|
247
295
|
|
248
|
-
it
|
296
|
+
it do
|
297
|
+
should eq "people/all/"\
|
298
|
+
"#{klass.count}-#{klass.maximum(:updated_on).utc.to_s(:nsec)}"
|
299
|
+
end
|
249
300
|
end
|
250
301
|
|
251
|
-
context
|
252
|
-
before
|
302
|
+
context "and it has newer updated_at" do
|
303
|
+
before do
|
304
|
+
person.update_attributes!(
|
305
|
+
updated_at: Time.now + 3600,
|
306
|
+
updated_on: Time.now,
|
307
|
+
)
|
308
|
+
end
|
253
309
|
|
254
|
-
it
|
310
|
+
it do
|
311
|
+
should eq "people/all/"\
|
312
|
+
"#{klass.count}-#{klass.maximum(:updated_at).utc.to_s(:nsec)}"
|
313
|
+
end
|
255
314
|
end
|
256
315
|
|
257
|
-
context
|
258
|
-
before
|
316
|
+
context "and it has newer updated_on" do
|
317
|
+
before do
|
318
|
+
person.update_attributes!(
|
319
|
+
updated_at: Time.now,
|
320
|
+
updated_on: Time.now + 3600,
|
321
|
+
)
|
322
|
+
end
|
259
323
|
|
260
|
-
it
|
324
|
+
it do
|
325
|
+
should eq "people/all/"\
|
326
|
+
"#{klass.count}-#{klass.maximum(:updated_on).utc.to_s(:nsec)}"
|
327
|
+
end
|
261
328
|
end
|
262
329
|
end
|
263
330
|
end
|
264
331
|
|
265
|
-
context
|
332
|
+
context "when getting cache_key with nil" do
|
266
333
|
subject { klass.cache_key(nil) }
|
267
334
|
|
268
|
-
context
|
269
|
-
before { klass.count.
|
335
|
+
context "and has no record" do
|
336
|
+
before { expect(klass.count).to eq 0 }
|
270
337
|
|
271
|
-
it { should match
|
338
|
+
it { should match %r|\/#{klass.count}$| }
|
272
339
|
end
|
273
|
-
context
|
340
|
+
context "and has a record" do
|
274
341
|
let!(:person) { klass.create! }
|
275
342
|
|
276
|
-
context
|
277
|
-
before
|
343
|
+
context "and it has updated_on value only" do
|
344
|
+
before do
|
345
|
+
person.update_attributes!(
|
346
|
+
updated_at: nil,
|
347
|
+
updated_on: Time.now,
|
348
|
+
)
|
349
|
+
end
|
278
350
|
|
279
351
|
it { should eq "people/all/#{klass.count}" }
|
280
352
|
end
|
281
353
|
|
282
|
-
context
|
283
|
-
before
|
354
|
+
context "and it has newer updated_at" do
|
355
|
+
before do
|
356
|
+
person.update_attributes!(
|
357
|
+
updated_at: Time.now + 3600,
|
358
|
+
updated_on: Time.now,
|
359
|
+
)
|
360
|
+
end
|
284
361
|
|
285
362
|
it { should eq "people/all/#{klass.count}" }
|
286
363
|
end
|
287
364
|
|
288
|
-
context
|
289
|
-
before
|
365
|
+
context "and it has newer updated_on" do
|
366
|
+
before do
|
367
|
+
person.update_attributes!(
|
368
|
+
updated_at: Time.now,
|
369
|
+
updated_on: Time.now + 3600,
|
370
|
+
)
|
371
|
+
end
|
290
372
|
|
291
373
|
it { should eq "people/all/#{klass.count}" }
|
292
374
|
end
|
@@ -294,72 +376,75 @@ describe Parent do
|
|
294
376
|
end
|
295
377
|
end
|
296
378
|
|
297
|
-
context
|
379
|
+
context "when a class has custom timestamp format" do
|
298
380
|
let(:klass) { Animal }
|
299
381
|
let!(:record) { klass.create! }
|
300
382
|
|
301
|
-
it
|
383
|
+
it do
|
384
|
+
should eq "animals/all/"\
|
385
|
+
"#{klass.count}-#{klass.maximum(:updated_at).utc.to_s(:number)}"
|
386
|
+
end
|
302
387
|
end
|
303
388
|
end
|
304
389
|
|
305
|
-
describe
|
390
|
+
describe ".cache_key_without_timestamp" do
|
306
391
|
subject { klass.cache_key_without_timestamp }
|
307
392
|
|
308
|
-
context
|
393
|
+
context "when a class has no update_at column" do
|
309
394
|
let(:klass) { Stone }
|
310
395
|
|
311
|
-
context
|
312
|
-
before { klass.count.
|
396
|
+
context "and has no record" do
|
397
|
+
before { expect(klass.count).to eq 0 }
|
313
398
|
|
314
|
-
it { should match
|
399
|
+
it { should match %r|\/#{klass.count}$| }
|
315
400
|
end
|
316
|
-
context
|
401
|
+
context "and has a record" do
|
317
402
|
before { klass.create! }
|
318
403
|
|
319
|
-
it { should match
|
404
|
+
it { should match %r|\/#{klass.count}$| }
|
320
405
|
end
|
321
406
|
end
|
322
407
|
|
323
|
-
context
|
408
|
+
context "when a class has updated_at column" do
|
324
409
|
let(:klass) { Parent }
|
325
410
|
|
326
|
-
context
|
327
|
-
before { klass.count.
|
411
|
+
context "and has no record" do
|
412
|
+
before { expect(klass.count).to eq 0 }
|
328
413
|
|
329
|
-
it { should match
|
414
|
+
it { should match %r|\/#{klass.count}$| }
|
330
415
|
end
|
331
416
|
|
332
|
-
context
|
417
|
+
context "and has a record" do
|
333
418
|
let!(:parent) { klass.create! }
|
334
419
|
|
335
420
|
it { should eq "parents/all/#{klass.count}" }
|
336
421
|
|
337
|
-
context
|
422
|
+
context "when record all has nil updated timestamps" do
|
338
423
|
before { klass.update_all(updated_at: nil) }
|
339
424
|
|
340
|
-
it { should match
|
425
|
+
it { should match %r|\/#{klass.count}$| }
|
341
426
|
end
|
342
427
|
end
|
343
428
|
end
|
344
429
|
|
345
|
-
context
|
430
|
+
context "when a class has updated_at AND updated_on column" do
|
346
431
|
let(:klass) { Person }
|
347
432
|
|
348
|
-
context
|
349
|
-
before { klass.count.
|
433
|
+
context "and has no record" do
|
434
|
+
before { expect(klass.count).to eq 0 }
|
350
435
|
|
351
|
-
it { should match
|
436
|
+
it { should match %r|\/#{klass.count}$| }
|
352
437
|
end
|
353
|
-
context
|
438
|
+
context "and has a record" do
|
354
439
|
let!(:person) { klass.create! }
|
355
440
|
|
356
|
-
context
|
441
|
+
context "and it has updated_at value only" do
|
357
442
|
before { person.update_attributes!(updated_at: Time.now, updated_on: nil) }
|
358
443
|
|
359
444
|
it { should eq "people/all/#{klass.count}" }
|
360
445
|
end
|
361
446
|
|
362
|
-
context
|
447
|
+
context "and it has updated_on value only" do
|
363
448
|
before { person.update_attributes!(updated_at: nil, updated_on: Time.now) }
|
364
449
|
|
365
450
|
it { should eq "people/all/#{klass.count}" }
|