redtastic 0.2.1 → 0.2.2

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.
@@ -0,0 +1,776 @@
1
+ require 'spec_helper'
2
+
3
+ describe Redtastic::Model do
4
+
5
+ it 'validates type' do
6
+ expect do
7
+ class InvalidType < Redtastic::Model
8
+ type :foo
9
+ end
10
+ end.to raise_error(RuntimeError, 'foo is not a valid type')
11
+ end
12
+
13
+ it 'validates resolution' do
14
+ expect do
15
+ class InvalidResolution < Redtastic::Model
16
+ type :counter
17
+ resolution :foo
18
+ end
19
+ end.to raise_error(RuntimeError, 'foo is not a valid resolution')
20
+ end
21
+
22
+ context 'counter' do
23
+ before do
24
+ class Visits < Redtastic::Model
25
+ type :counter
26
+ resolution :days
27
+ end
28
+
29
+ class NoResolutions < Redtastic::Model
30
+ type :counter
31
+ end
32
+
33
+ @no_resolution_key = 'app1:no_resolutions:1'
34
+ @day_key = 'app1:visits:2014-01-05:1'
35
+ @week_key = 'app1:visits:2014-W1:1'
36
+ @month_key = 'app1:visits:2014-01:1'
37
+ @year_key = 'app1:visits:2014:1'
38
+ @id = 1001
39
+ @index = 1
40
+ @timestamp = '2014-01-05'
41
+ end
42
+
43
+ describe '#increment' do
44
+ context 'a model with a daily resolution' do
45
+ before do
46
+ Visits.increment(timestamp: @timestamp, id: @id)
47
+ end
48
+
49
+ it 'increments the daily key' do
50
+ expect(Redtastic::Connection.redis.hget(@day_key, @index)).to eq('1')
51
+ end
52
+
53
+ it 'increments the weekly key' do
54
+ expect(Redtastic::Connection.redis.hget(@week_key, @index)).to eq('1')
55
+ end
56
+
57
+ it 'increments the monthly key' do
58
+ expect(Redtastic::Connection.redis.hget(@month_key, @index)).to eq('1')
59
+ end
60
+
61
+ it 'increments the yearly key' do
62
+ expect(Redtastic::Connection.redis.hget(@year_key, @index)).to eq('1')
63
+ end
64
+ end
65
+
66
+ context 'a model with no resolution' do
67
+ it 'increments the key' do
68
+ NoResolutions.increment(id: @id)
69
+ expect(Redtastic::Connection.redis.hget(@no_resolution_key, @index)).to eq('1')
70
+ end
71
+ end
72
+
73
+ context 'multiple ids' do
74
+ before do
75
+ ids = [1001, 1002, 2003]
76
+ Visits.increment(timestamp: @timestamp, id: ids)
77
+ end
78
+
79
+ it 'increments the keys for each id' do
80
+ expect(Redtastic::Connection.redis.hget(@day_key, '1')).to eq('1')
81
+ expect(Redtastic::Connection.redis.hget(@day_key, '2')).to eq('1')
82
+ expect(Redtastic::Connection.redis.hget('app1:visits:2014-01-05:2', '3')).to eq('1')
83
+ end
84
+ end
85
+ end
86
+
87
+ describe '#decrement' do
88
+ before do
89
+ Redtastic::Connection.redis.hset(@day_key, @index, '1')
90
+ Visits.decrement(timestamp: @timestamp, id: @id)
91
+ end
92
+
93
+ context 'a model with a resolution' do
94
+ it 'decrements the key' do
95
+ expect(Redtastic::Connection.redis.hget(@day_key, @index)).to eq('0')
96
+ end
97
+ end
98
+
99
+ context 'a model with no resolution' do
100
+ before do
101
+ Redtastic::Connection.redis.hset(@no_resolution_key, @index, '1')
102
+ NoResolutions.decrement(id: @id)
103
+ end
104
+
105
+ it 'decrements the key' do
106
+ expect(Redtastic::Connection.redis.hget(@no_resolution_key, @index)).to eq('0')
107
+ end
108
+ end
109
+
110
+ context 'multiple ids' do
111
+ before do
112
+ ids = [1001, 1002, 2003]
113
+ Visits.decrement(timestamp: @timestamp, id: ids)
114
+ end
115
+
116
+ it 'decrements the keys for each id' do
117
+ expect(Redtastic::Connection.redis.hget(@day_key, '1')).to eq('-1')
118
+ expect(Redtastic::Connection.redis.hget(@day_key, '2')).to eq('-1')
119
+ expect(Redtastic::Connection.redis.hget('app1:visits:2014-01-05:2', '3')).to eq('-1')
120
+ end
121
+ end
122
+ end
123
+
124
+ describe '#find' do
125
+ context 'a model with a resolution' do
126
+ before do
127
+ Visits.increment(timestamp: @timestamp, id: @id)
128
+ Visits.increment(timestamp: '2014-01-02', id: @id)
129
+ end
130
+
131
+ it 'finds the value for a single day' do
132
+ expect(Visits.find(year: 2014, month: 1, day: 5, id: @id)).to eq(1)
133
+ end
134
+
135
+ it 'finds the value for a single week' do
136
+ expect(Visits.find(year: 2014, week: 1, id: @id)).to eq(2)
137
+ end
138
+
139
+ it 'finds the value for a single month' do
140
+ expect(Visits.find(year: 2014, month: 1, id: @id)).to eq(2)
141
+ end
142
+
143
+ it 'finds the value for a single year' do
144
+ expect(Visits.find(year: 2014, id: @id)).to eq(2)
145
+ end
146
+ end
147
+
148
+ context 'a model with no resolution' do
149
+ before do
150
+ 3.times { NoResolutions.increment(id: @id) }
151
+ end
152
+
153
+ it 'finds the value for the counter' do
154
+ expect(NoResolutions.find(id: @id)).to eq(3)
155
+ end
156
+ end
157
+
158
+ context 'mutiple ids' do
159
+ before do
160
+ 2.times { Visits.increment(timestamp: @timestamp, id: 1001) }
161
+ Visits.increment(timestamp: @timestamp, id: 2003)
162
+ end
163
+
164
+ it 'returns an array of the values for each id' do
165
+ expected_result = [2, 1]
166
+ expect(Visits.find(year: 2014, month: 1, day: 5, id: [1001, 2003])).to eq(expected_result)
167
+ end
168
+ end
169
+ end
170
+
171
+ describe '#aggregate' do
172
+ context 'when no interval specified' do
173
+ it 'returns the total over the date range' do
174
+ 9.times { |day| Redtastic::Connection.redis.hincrby("app1:visits:2014-01-0#{day + 1}:1", '1', 1) }
175
+ res = Visits.aggregate(start_date: '2014-01-01', end_date: '2014-01-09', id: @id)
176
+ expect(res).to eq(9)
177
+ end
178
+
179
+ it 'returns the correct total over the date range when resolution is weeks' do
180
+ class Foo < Redtastic::Model
181
+ type :counter
182
+ resolution :weeks
183
+ end
184
+ 3.times { |num| Redtastic::Connection.redis.hincrby("app1:foo:2014-W#{num}:1", '1', 1) }
185
+ res = Foo.aggregate(start_date: '2014-01-01', end_date: '2014-01-09', id: @id)
186
+ expect(res).to eq(2)
187
+ end
188
+
189
+ it 'returns the correct total over the date range when the resolution is months' do
190
+ class Foo < Redtastic::Model
191
+ type :counter
192
+ resolution :months
193
+ end
194
+ 3.times { Redtastic::Connection.redis.hincrby('app1:foo:2014-01:1', '1', 1) }
195
+ res = Foo.aggregate(start_date: '2014-01-01', end_date: '2014-01-09', id: @id)
196
+ expect(res).to eq(3)
197
+ end
198
+
199
+ it 'returns the correct total over the date range when resolution is yearly' do
200
+ class Foo < Redtastic::Model
201
+ type :counter
202
+ resolution :years
203
+ end
204
+ 3.times { Redtastic::Connection.redis.hincrby('app1:foo:2014:1', '1', 1) }
205
+ res = Foo.aggregate(start_date: '2014-01-01', end_date: '2014-01-09', id: @id)
206
+ expect(res).to eq(3)
207
+ end
208
+ end
209
+
210
+ context 'when interval is specified' do
211
+ before do
212
+ @params = { start_date: '2014-01-01', end_date: '2014-01-08', id: @id }
213
+ 8.times { |day| Visits.increment(timestamp: "2014-01-0#{day + 1}", id: @id) }
214
+ end
215
+
216
+ context 'and is days' do
217
+ before do
218
+ @params[:interval] = :days
219
+ @result = Visits.aggregate(@params)
220
+ end
221
+
222
+ it 'returns the total over the date range' do
223
+ expect(@result[:visits]).to eq(8)
224
+ end
225
+
226
+ it 'returns the proper amount of data points' do
227
+ expect(@result[:days].size).to eq(8)
228
+ end
229
+
230
+ it 'returns the correct data for each point in the interval' do
231
+ @result[:days].each do |day|
232
+ expect(day[:visits]).to eq(1)
233
+ end
234
+ end
235
+
236
+ it 'returns the correct dates for each point in the interval' do
237
+ current_date = Date.parse(@params[:start_date])
238
+ @result[:days].each do |day|
239
+ expect(day[:date]).to eq(current_date.strftime('%Y-%m-%d'))
240
+ current_date = current_date.advance(days: +1)
241
+ end
242
+ end
243
+ end
244
+
245
+ context 'and is weeks' do
246
+ before do
247
+ @params[:interval] = :weeks
248
+ @result = Visits.aggregate(@params)
249
+ end
250
+
251
+ it 'returns the total over the date range' do
252
+ expect(@result[:visits]).to eq(8)
253
+ end
254
+
255
+ it 'returns the proper amount of data points' do
256
+ expect(@result[:weeks].size).to eq(2)
257
+ end
258
+
259
+ it 'returns the correct data for each point in the interval' do
260
+ expect(@result[:weeks][0][:visits]).to eq(5)
261
+ expect(@result[:weeks][1][:visits]).to eq(3)
262
+ end
263
+
264
+ it 'returns the correct dates for each point in the interval' do
265
+ expect(@result[:weeks][0][:date]).to eq('2014-W1')
266
+ expect(@result[:weeks][1][:date]).to eq('2014-W2')
267
+ end
268
+ end
269
+
270
+ context 'and is months' do
271
+ before do
272
+ @params[:interval] = :months
273
+ @result = Visits.aggregate(@params)
274
+ end
275
+
276
+ it 'returns the total over the date range' do
277
+ expect(@result[:visits]).to eq(8)
278
+ end
279
+
280
+ it 'returns the proper amount of data points' do
281
+ expect(@result[:months].size).to eq(1)
282
+ end
283
+
284
+ it 'returns the correct data for each point in the interval' do
285
+ expect(@result[:months][0][:visits]).to eq(8)
286
+ end
287
+
288
+ it 'returns the correct dates for each point in the interval' do
289
+ expect(@result[:months][0][:date]).to eq('2014-01')
290
+ end
291
+ end
292
+
293
+ context 'and is years' do
294
+ before do
295
+ @params[:interval] = :years
296
+ @result = Visits.aggregate(@params)
297
+ end
298
+
299
+ it 'returns the total over the date range' do
300
+ expect(@result[:visits]).to eq(8)
301
+ end
302
+
303
+ it 'returns the proper amount of data points' do
304
+ expect(@result[:years].size).to eq(1)
305
+ end
306
+
307
+ it 'returns the correct data for each point in the interval' do
308
+ expect(@result[:years][0][:visits]).to eq(8)
309
+ end
310
+
311
+ it 'returns the correct dates for each point in the interval' do
312
+ expect(@result[:years][0][:date]).to eq('2014')
313
+ end
314
+ end
315
+ end
316
+
317
+ context 'mutiple ids' do
318
+ before do
319
+ 9.times { |day| Redtastic::Connection.redis.hincrby("app1:visits:2014-01-0#{day + 1}:1", '1', 1) }
320
+ 3.times { |day| Redtastic::Connection.redis.hincrby("app1:visits:2014-01-0#{day + 1}:2", '3', 1) }
321
+ @params = { start_date: '2014-01-01', end_date: '2014-01-09', id: [1001, 2003] }
322
+ end
323
+
324
+ context 'when no interval is specified' do
325
+ it 'returns the aggregate total for both ids combined' do
326
+ result = Visits.aggregate(@params)
327
+ expect(result).to eq(12)
328
+ end
329
+ end
330
+
331
+ context 'when an interval is specified' do
332
+ before do
333
+ @result = Visits.aggregate(@params.merge!(interval: :days))
334
+ end
335
+
336
+ it 'returns the total over the date range' do
337
+ expect(@result[:visits]).to eq(12)
338
+ end
339
+
340
+ it 'returns the proper amount of data points' do
341
+ expect(@result[:days].size).to eq(9)
342
+ end
343
+
344
+ it 'returns the correct data for each point in the interval' do
345
+ 3.times do |num|
346
+ expect(@result[:days][num][:visits]).to eq(2)
347
+ end
348
+ (3..8).each do |num|
349
+ expect(@result[:days][num][:visits]).to eq(1)
350
+ end
351
+ end
352
+ end
353
+ end
354
+ end
355
+ end
356
+
357
+ context 'unique counter' do
358
+ before do
359
+ class Customers < Redtastic::Model
360
+ type :unique
361
+ resolution :days
362
+ end
363
+ @id = 1001
364
+ @timestamp = '2014-01-05'
365
+ @user1 = 4321
366
+ @user2 = 8765
367
+ @day_key = 'app1:customers:2014-01-05:1001'
368
+ @week_key = 'app1:customers:2014-W1:1001'
369
+ @month_key = 'app1:customers:2014-01:1001'
370
+ @year_key = 'app1:customers:2014:1001'
371
+ end
372
+
373
+ describe '#increment' do
374
+ context 'single ids' do
375
+ before do
376
+ Customers.increment(id: @id, timestamp: @timestamp, unique_id: @user1)
377
+ Customers.increment(id: @id, timestamp: @timestamp, unique_id: @user2)
378
+ end
379
+
380
+ it 'adds user 1 to the set' do
381
+ expect(Redtastic::Connection.redis.sismember(@day_key, @user1)).to be true
382
+ end
383
+
384
+ it 'adds user 2 to the set' do
385
+ expect(Redtastic::Connection.redis.sismember(@day_key, @user2)).to be true
386
+ end
387
+
388
+ it 'adds user 1 to the weekly set' do
389
+ expect(Redtastic::Connection.redis.sismember(@week_key, @user1)).to be true
390
+ end
391
+
392
+ it 'adds user 1 to the monthly set' do
393
+ expect(Redtastic::Connection.redis.sismember(@month_key, @user1)).to be true
394
+ end
395
+
396
+ it 'adds user 1 to the yearly set' do
397
+ expect(Redtastic::Connection.redis.sismember(@year_key, @user1)).to be true
398
+ end
399
+ end
400
+
401
+ context 'multiple ids' do
402
+ before do
403
+ ids = [1001, 1002]
404
+ Customers.increment(id: ids, timestamp: @timestamp, unique_id: @user1)
405
+ end
406
+
407
+ it 'increments bits on both keys' do
408
+ expect(Redtastic::Connection.redis.sismember(@day_key, @user1)).to be true
409
+ expect(Redtastic::Connection.redis.sismember('app1:customers:2014-01-05:1002', @user1)).to be true
410
+ end
411
+ end
412
+ end
413
+
414
+ describe '#decrement' do
415
+ before do
416
+ # First add user 1
417
+ Redtastic::Connection.redis.sadd(@day_key, @user1)
418
+ end
419
+
420
+ it 'decrements user1 removing it from the set' do
421
+ # Make sure it was properly added first
422
+ expect(Redtastic::Connection.redis.sismember(@day_key, @user1)).to be true
423
+ Customers.decrement(id: @id, timestamp: @timestamp, unique_id: @user1)
424
+ expect(Redtastic::Connection.redis.sismember(@day_key, @user1)).to be false
425
+ end
426
+ end
427
+
428
+ describe '#find' do
429
+ context 'single ids' do
430
+ before do
431
+ Customers.increment(id: @id, timestamp: @timestamp, unique_id: @user1)
432
+ end
433
+
434
+ it 'finds the value for a unique id on a single day' do
435
+ expect(Customers.find(id: @id, year: 2014, month: 1, day: 5, unique_id: @user1)).to eq(1)
436
+ expect(Customers.find(id: @id, year: 2014, month: 1, day: 5, unique_id: 1)).to eq(0)
437
+ end
438
+
439
+ it 'finds the value for a unique id in a single week' do
440
+ expect(Customers.find(id: @id, year: 2014, week: 1, unique_id: @user1)).to eq(1)
441
+ expect(Customers.find(id: @id, year: 2014, week: 1, unique_id: 1)).to eq(0)
442
+ end
443
+
444
+ it 'finds the value for a unique id in a single month' do
445
+ expect(Customers.find(id: @id, year: 2014, month: 1, unique_id: @user1)).to eq(1)
446
+ expect(Customers.find(id: @id, year: 2014, month: 1, unique_id: 1)).to eq(0)
447
+ end
448
+
449
+ it 'finds the value for a unique id in a single year' do
450
+ expect(Customers.find(id: @id, year: 2014, unique_id: @user1)).to eq(1)
451
+ expect(Customers.find(id: @id, year: 2014, unique_id: 1)).to eq(0)
452
+ end
453
+ end
454
+
455
+ context 'mutiple ids' do
456
+ before do
457
+ 2.times { Customers.increment(id: 1001, timestamp: @timestamp, unique_id: @user1) }
458
+ Customers.increment(id: 1002, timestamp: @timestamp, unique_id: @user1)
459
+ end
460
+
461
+ it 'returns an array of the values for each id' do
462
+ expected_result = [1, 1, 0]
463
+ params = { id: [1001, 1002, 1003], year: 2014, month: 1, day: 5, unique_id: @user1 }
464
+ expect(Customers.find(params)).to eq(expected_result)
465
+ end
466
+ end
467
+ end
468
+
469
+ describe '#aggregate' do
470
+ context 'when no interval is specified' do
471
+ it 'returns the total over the date range' do
472
+ 9.times { |day| Redtastic::Connection.redis.sadd("app1:customers:2014-01-0#{day + 1}:#{@id}", @user1) }
473
+ 3.times { |day| Redtastic::Connection.redis.sadd("app1:customers:2014-01-0#{day + 1}:#{@id}", @user2) }
474
+ result = Customers.aggregate(start_date: '2014-01-01', end_date: '2014-01-09', id: @id)
475
+ expect(result).to eq(2)
476
+ end
477
+
478
+ it 'returns the correct total over the date range when the resolution is weeks' do
479
+ class Foo < Redtastic::Model
480
+ type :unique
481
+ resolution :weeks
482
+ end
483
+ 3.times { |num| Redtastic::Connection.redis.sadd("app1:foo:2014-W#{num}:#{@id}", @user1) }
484
+ 2.times { |num| Redtastic::Connection.redis.sadd("app1:foo:2014-W#{num}:#{@id}", @user2) }
485
+ result = Foo.aggregate(start_date: '2014-01-01', end_date: '2014-01-09', id: @id)
486
+ expect(result).to eq(2)
487
+ end
488
+
489
+ it 'returns the correct total over the date range when the resolution is months' do
490
+ class Foo < Redtastic::Model
491
+ type :unique
492
+ resolution :months
493
+ end
494
+ 3.times { |num| Redtastic::Connection.redis.sadd("app1:foo:2014-01:#{@id}", @user1) }
495
+ 2.times { |num| Redtastic::Connection.redis.sadd("app1:foo:2014-01:#{@id}", @user2) }
496
+ result = Foo.aggregate(start_date: '2014-01-01', end_date: '2014-01-09', id: @id)
497
+ expect(result).to eq(2)
498
+ end
499
+
500
+ it 'returns the correct total over the date range when the resolution is years' do
501
+ class Foo < Redtastic::Model
502
+ type :unique
503
+ resolution :years
504
+ end
505
+ 3.times { |num| Redtastic::Connection.redis.sadd("app1:foo:2014:#{@id}", @user1) }
506
+ 2.times { |num| Redtastic::Connection.redis.sadd("app1:foo:2014:#{@id}", @user2) }
507
+ result = Foo.aggregate(start_date: '2014-01-01', end_date: '2014-01-09', id: @id)
508
+ expect(result).to eq(2)
509
+ end
510
+ end
511
+
512
+ context 'when interval is specified' do
513
+ before do
514
+ @params = { start_date: '2014-01-01', end_date: '2014-01-09', id: @id }
515
+ 9.times { |day| Customers.increment(id: @id, timestamp: "2014-01-0#{day + 1}", unique_id: @user1) }
516
+ 3.times { |day| Customers.increment(id: @id, timestamp: "2014-01-0#{day + 1}", unique_id: @user2) }
517
+ end
518
+
519
+ context 'and is days' do
520
+ before do
521
+ @params[:interval] = :days
522
+ @result = Customers.aggregate(@params)
523
+ end
524
+
525
+ it 'returns the total over the date range' do
526
+ expect(@result[:customers]).to eq(2)
527
+ end
528
+
529
+ it 'returns the proper amount of data points' do
530
+ expect(@result[:days].size).to eq(9)
531
+ end
532
+
533
+ it 'returns the correct data for each point in the interval' do
534
+ 3.times { |num| expect(@result[:days][num][:customers]).to eq(2) }
535
+ 6.times { |num| expect(@result[:days][num + 3][:customers]).to eq(1) }
536
+ end
537
+
538
+ it 'returns the correct dates for each point in the interval' do
539
+ current_date = Date.parse(@params[:start_date])
540
+ @result[:days].each do |day|
541
+ expect(day[:date]).to eq(current_date.strftime('%Y-%m-%d'))
542
+ current_date = current_date.advance(days: +1)
543
+ end
544
+ end
545
+ end
546
+
547
+ context 'and is weeks' do
548
+ before do
549
+ @params[:interval] = :weeks
550
+ @result = Customers.aggregate(@params)
551
+ end
552
+
553
+ it 'returns the total over the date range' do
554
+ expect(@result[:customers]).to eq(2)
555
+ end
556
+
557
+ it 'returns the proper amount of data points' do
558
+ expect(@result[:weeks].size).to eq(2)
559
+ end
560
+
561
+ it 'returns the correct data for each point in the interval' do
562
+ expect(@result[:weeks][0][:customers]).to eq(2)
563
+ expect(@result[:weeks][1][:customers]).to eq(1)
564
+ end
565
+
566
+ it 'returns the correct dates for each point in the interval' do
567
+ expect(@result[:weeks][0][:date]).to eq('2014-W1')
568
+ expect(@result[:weeks][1][:date]).to eq('2014-W2')
569
+ end
570
+ end
571
+
572
+ context 'and is years' do
573
+ before do
574
+ @params[:interval] = :years
575
+ @result = Customers.aggregate(@params)
576
+ end
577
+
578
+ it 'returns the total over the date range' do
579
+ expect(@result[:customers]).to eq(2)
580
+ end
581
+
582
+ it 'returns the proper amount of data points' do
583
+ expect(@result[:years].size).to eq(1)
584
+ end
585
+
586
+ it 'returns the correct data for each point in the interval' do
587
+ expect(@result[:years][0][:customers]).to eq(2)
588
+ end
589
+
590
+ it 'returns the correct dates for each point in the interval' do
591
+ expect(@result[:years][0][:date]).to eq('2014')
592
+ end
593
+ end
594
+ end
595
+
596
+ context 'multiple ids' do
597
+ before do
598
+ 9.times do |day|
599
+ Customers.increment(id: 1001, timestamp: "2014-01-0#{day + 1}", unique_id: @user1)
600
+ Customers.increment(id: 1002, timestamp: "2014-01-0#{day + 1}", unique_id: @user1)
601
+ end
602
+ 3.times { |day| Customers.increment(id: 1001, timestamp: "2014-01-0#{day + 1}", unique_id: @user2) }
603
+ @params = { start_date: '2014-01-01', end_date: '2014-01-09', id: [1001, 2003] }
604
+ end
605
+
606
+ context 'when no interval is specified' do
607
+ it 'returns the aggregate total for both ids combined' do
608
+ result = Customers.aggregate(@params)
609
+ expect(result).to eq(2)
610
+ end
611
+ end
612
+
613
+ context 'when an interval is specified' do
614
+ before do
615
+ @result = Customers.aggregate(@params.merge!(interval: :days))
616
+ end
617
+
618
+ it 'returns the total over the date range' do
619
+ expect(@result[:customers]).to eq(2)
620
+ end
621
+
622
+ it 'returns the proper amount of data points' do
623
+ expect(@result[:days].size).to eq(9)
624
+ end
625
+
626
+ it 'returns the correct data for each point in the interval' do
627
+ 3.times { |num| expect(@result[:days][num][:customers]).to eq(2) }
628
+ (3..8).each { |num| expect(@result[:days][num][:customers]).to eq(1) }
629
+ end
630
+ end
631
+ end
632
+ end
633
+ end
634
+
635
+ context 'attributes' do
636
+ before do
637
+ class Customers < Redtastic::Model
638
+ type :unique
639
+ resolution :days
640
+ end
641
+ class Males < Redtastic::Model
642
+ type :unique
643
+ end
644
+ class Mobile < Redtastic::Model
645
+ type :unique
646
+ end
647
+ @user1 = 1111
648
+ @user2 = 2222
649
+ @user3 = 3333
650
+ @attribute_key = 'app1:males'
651
+ end
652
+
653
+ describe '#increment' do
654
+ before do
655
+ Males.increment(unique_id: @user1)
656
+ Males.increment(unique_id: @user2)
657
+ end
658
+
659
+ it 'adds user1 to the set' do
660
+ result = Redtastic::Connection.redis.sismember(@attribute_key, @user1)
661
+ expect(result).to be true
662
+ end
663
+
664
+ it 'adds user2 to the set' do
665
+ result = Redtastic::Connection.redis.sismember(@attribute_key, @user2)
666
+ expect(result).to be true
667
+ end
668
+ end
669
+
670
+ describe '#decrement' do
671
+ before do
672
+ Males.increment(unique_id: @user1)
673
+ end
674
+
675
+ it 'adds user1 to the set' do
676
+ Males.decrement(unique_id: @user1)
677
+ result = Redtastic::Connection.redis.sismember(@attribute_key, @user1)
678
+ expect(result).to be false
679
+ end
680
+ end
681
+
682
+ describe '#find' do
683
+ before do
684
+ Males.increment(unique_id: @user1)
685
+ end
686
+
687
+ it 'returns 1 for a unique_id that is in the attribute set' do
688
+ expect(Males.find(unique_id: @user1)).to eq(1)
689
+ end
690
+
691
+ it 'returns 0 for a unique_id that is not in the attribute set' do
692
+ expect(Males.find(unique_id: @user2)).to eq(0)
693
+ end
694
+ end
695
+
696
+ describe '#aggregate' do
697
+ before do
698
+ Males.increment(unique_id: @user1)
699
+ Males.increment(unique_id: @user2)
700
+ Mobile.increment(unique_id: @user2)
701
+ 9.times{ |day| Redtastic::Connection.redis.sadd("app1:customers:2014-01-0#{day + 1}:#{2222}", @user1) }
702
+ 3.times{ |day| Redtastic::Connection.redis.sadd("app1:customers:2014-01-0#{day + 1}:#{1111}", @user2) }
703
+ 3.times{ |day| Redtastic::Connection.redis.sadd("app1:customers:2014-01-0#{day + 1}:#{1111}", @user3) }
704
+ @params = { id: [1111, 2222], start_date: '2014-01-01', end_date: '2014-01-09' }
705
+ @attributes = []
706
+ end
707
+
708
+ context 'when no interval is specified' do
709
+ context 'and single attribute is specified' do
710
+ it 'returns the total over the date range' do
711
+ @attributes << :males
712
+ result = Customers.aggregate(@params.merge!(attributes: @attributes))
713
+ expect(result).to eq(2)
714
+ end
715
+
716
+ it 'does not require use of an array if specifying only one attribute' do
717
+ result = Customers.aggregate(@params.merge!(attributes: :males))
718
+ expect(result).to eq(2)
719
+ end
720
+ end
721
+
722
+ context 'and multiple attributes are specified' do
723
+ it 'returns the total over the date range' do
724
+ @attributes << :males
725
+ @attributes << :mobile
726
+ result = Customers.aggregate(@params.merge!(attributes: @attributes))
727
+ expect(result).to eq(1)
728
+ end
729
+ end
730
+ end
731
+
732
+ context 'when interval is specified' do
733
+ context 'and single attribute is specified' do
734
+ before do
735
+ @attributes << :males
736
+ @result = Customers.aggregate(@params.merge!(attributes: @attributes, interval: :days))
737
+ end
738
+
739
+ it 'returns the total over the date range' do
740
+ expect(@result[:customers]).to eq(2)
741
+ end
742
+
743
+ it 'returns the proper amount of data points' do
744
+ expect(@result[:days].size).to eq(9)
745
+ end
746
+
747
+ it 'returns the correct data for each point in the interval' do
748
+ 3.times { |num| expect(@result[:days][num][:customers]).to eq(2) }
749
+ 6.times { |num| expect(@result[:days][num + 3][:customers]).to eq(1) }
750
+ end
751
+ end
752
+
753
+ context 'and multiple attributes are specified' do
754
+ before do
755
+ @attributes << :males
756
+ @attributes << :mobile
757
+ @result = Customers.aggregate(@params.merge!(attributes: @attributes, interval: :days))
758
+ end
759
+
760
+ it 'returns the total over the date range' do
761
+ expect(@result[:customers]).to eq(1)
762
+ end
763
+
764
+ it 'returns the proper amount of data points' do
765
+ expect(@result[:days].size).to eq(9)
766
+ end
767
+
768
+ it 'returns the correct data for each point in the interval' do
769
+ 3.times { |num| expect(@result[:days][num][:customers]).to eq(1) }
770
+ 6.times { |num| expect(@result[:days][num + 3][:customers]).to eq(0) }
771
+ end
772
+ end
773
+ end
774
+ end
775
+ end
776
+ end