inferx 0.2.3 → 0.2.4
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.
- data/lib/inferx.rb +2 -4
- data/lib/inferx/categories.rb +173 -18
- data/lib/inferx/category.rb +40 -76
- data/lib/inferx/category/complementary.rb +48 -0
- data/lib/inferx/version.rb +1 -1
- data/spec/inferx/categories_spec.rb +325 -59
- data/spec/inferx/category/complementary_spec.rb +76 -0
- data/spec/inferx/category_spec.rb +60 -119
- data/spec/inferx_spec.rb +1 -9
- data/spec/spec_helper.rb +7 -0
- metadata +5 -11
- data/lib/inferx/adapter.rb +0 -64
- data/lib/inferx/complementary/categories.rb +0 -14
- data/lib/inferx/complementary/category.rb +0 -108
- data/spec/inferx/adapter_spec.rb +0 -92
- data/spec/inferx/complementary/categories_spec.rb +0 -25
- data/spec/inferx/complementary/category_spec.rb +0 -139
data/lib/inferx/version.rb
CHANGED
@@ -8,74 +8,179 @@ describe Inferx::Categories do
|
|
8
8
|
end
|
9
9
|
|
10
10
|
describe Inferx::Categories, '#initialize' do
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
categories.should
|
11
|
+
before do
|
12
|
+
@categories = described_class.new(redis_stub)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'sets "inferx:categories" to key attribute by default' do
|
16
|
+
@categories.key.should == 'inferx:categories'
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'is not manual save by default' do
|
20
|
+
@categories.should_not be_manual
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'with :namespace option' do
|
24
|
+
it 'considers the value to key attribute' do
|
25
|
+
categories = described_class.new(redis_stub, :namespace => 'example')
|
26
|
+
categories.key.should == 'inferx:example:categories'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'with :manual option' do
|
31
|
+
it 'is manual save if the value is true' do
|
32
|
+
categories = described_class.new(redis_stub, :manual => true)
|
33
|
+
categories.should be_manual
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'is not manual save if the value is false' do
|
37
|
+
categories = described_class.new(redis_stub, :manual => false)
|
38
|
+
categories.should_not be_manual
|
39
|
+
end
|
17
40
|
end
|
18
41
|
end
|
19
42
|
|
20
|
-
describe Inferx::Categories, '#
|
21
|
-
|
43
|
+
describe Inferx::Categories, '#filter' do
|
44
|
+
before do
|
22
45
|
redis = redis_stub do |s|
|
23
|
-
s.
|
46
|
+
s.stub!(:hkeys => %w(red green blue))
|
24
47
|
end
|
25
48
|
|
26
|
-
categories = described_class.new(redis)
|
27
|
-
categories.all
|
49
|
+
@categories = described_class.new(redis)
|
28
50
|
end
|
29
51
|
|
30
|
-
it
|
52
|
+
it "returns an instance of #{described_class}" do
|
53
|
+
categories = @categories.filter('red', 'green')
|
54
|
+
categories.should be_an(described_class)
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'returns an instance that is different from their own' do
|
58
|
+
categories = @categories.filter('red', 'green')
|
59
|
+
categories.object_id.should_not == @categories.object_id
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'returns categories filtered by the category names' do
|
63
|
+
categories = @categories.filter('red', 'green')
|
64
|
+
categories.all.should == %w(red green)
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'when calling many times' do
|
68
|
+
it 'returns categories filtered by the collective category names' do
|
69
|
+
categories = @categories.filter('red', 'green').filter('green')
|
70
|
+
categories.all.should == %w(green)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe Inferx::Categories, '#except' do
|
76
|
+
before do
|
31
77
|
redis = redis_stub do |s|
|
32
|
-
s.stub!(:hkeys =>
|
78
|
+
s.stub!(:hkeys => %w(red green blue))
|
33
79
|
end
|
34
80
|
|
35
|
-
categories = described_class.new(redis)
|
36
|
-
|
81
|
+
@categories = described_class.new(redis)
|
82
|
+
end
|
83
|
+
|
84
|
+
it "returns an instance of #{described_class}" do
|
85
|
+
categories = @categories.except('red')
|
86
|
+
categories.should be_an(described_class)
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'returns an instance that is different from their own' do
|
90
|
+
categories = @categories.except('red')
|
91
|
+
categories.object_id.should_not == @categories.object_id
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'returns categories filtered by the category names' do
|
95
|
+
categories = @categories.except('red')
|
96
|
+
categories.all.should == %w(green blue)
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'when calling many times' do
|
100
|
+
it 'returns categories filtered by the successive category names' do
|
101
|
+
categories = @categories.except('red').except('green')
|
102
|
+
categories.all.should == %w(blue)
|
103
|
+
end
|
37
104
|
end
|
38
105
|
end
|
39
106
|
|
40
|
-
describe Inferx::Categories, '#
|
41
|
-
|
42
|
-
redis = redis_stub do |s|
|
43
|
-
s.
|
107
|
+
describe Inferx::Categories, '#all' do
|
108
|
+
before do
|
109
|
+
@redis = redis_stub do |s|
|
110
|
+
s.stub!(:hkeys => %w(red green blue))
|
44
111
|
end
|
45
112
|
|
46
|
-
categories = described_class.new(redis)
|
47
|
-
categories.get('red')
|
113
|
+
@categories = described_class.new(@redis)
|
48
114
|
end
|
49
115
|
|
50
|
-
it '
|
51
|
-
redis
|
52
|
-
|
116
|
+
it 'calls Redis#hkeys' do
|
117
|
+
@redis.should_receive(:hkeys).with('inferx:categories')
|
118
|
+
@categories.all
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'returns an instance of Array' do
|
122
|
+
@categories.all.should be_an(Array)
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'returns an empty array if the key is missing' do
|
126
|
+
@redis.stub!(:hkeys => nil)
|
127
|
+
@categories.all.should be_empty
|
128
|
+
end
|
129
|
+
|
130
|
+
context 'when filtered' do
|
131
|
+
it 'returns filtered category names' do
|
132
|
+
categories = @categories.filter('red', 'green').except('red')
|
133
|
+
categories.all.should == %w(green)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe Inferx::Categories, '#get' do
|
139
|
+
before do
|
140
|
+
@redis = redis_stub do |s|
|
141
|
+
s.stub!(:hget => '2', :hkeys => %w(red green blue))
|
53
142
|
end
|
143
|
+
end
|
54
144
|
|
55
|
-
|
56
|
-
|
145
|
+
it 'calls Redis#hget' do
|
146
|
+
@redis.should_receive(:hget).with('inferx:categories', 'red').and_return('2')
|
147
|
+
categories = described_class.new(@redis)
|
57
148
|
categories.get('red')
|
58
149
|
end
|
59
150
|
|
60
|
-
it '
|
61
|
-
|
62
|
-
|
63
|
-
|
151
|
+
it 'calles Inferx::Category.new with the instance of Redis, the categories, the category name and total of scores' do
|
152
|
+
categories = described_class.new(@redis)
|
153
|
+
Inferx::Category.should_receive(:new).with(@redis, categories, 'red', 2)
|
154
|
+
categories.get('red')
|
155
|
+
end
|
64
156
|
|
65
|
-
|
157
|
+
it 'returns an instance of Inferx::Category' do
|
158
|
+
categories = described_class.new(@redis)
|
66
159
|
categories.get('red').should be_an(Inferx::Category)
|
67
160
|
end
|
68
161
|
|
69
162
|
context 'with a missing category' do
|
70
163
|
it 'raises ArgumentError' do
|
71
|
-
redis
|
72
|
-
|
73
|
-
end
|
74
|
-
|
75
|
-
categories = described_class.new(redis)
|
164
|
+
@redis.stub!(:hget => nil)
|
165
|
+
categories = described_class.new(@redis)
|
76
166
|
lambda { categories.get('red') }.should raise_error(ArgumentError, /"red" is missing/)
|
77
167
|
end
|
78
168
|
end
|
169
|
+
|
170
|
+
context 'when filtered' do
|
171
|
+
it 'raises ArgumentError if the category is not defined in filtered categories' do
|
172
|
+
categories = described_class.new(@redis)
|
173
|
+
categories = categories.filter('red', 'green').except('red')
|
174
|
+
lambda { categories.get('red') }.should raise_error(ArgumentError, '"red" does not exist in filtered categories')
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
context 'when construct with :complementary option' do
|
179
|
+
it 'returns an instance of Inferx::Category::Complementary' do
|
180
|
+
categories = described_class.new(@redis, :complementary => true)
|
181
|
+
categories.get('red').should be_an(Inferx::Category::Complementary)
|
182
|
+
end
|
183
|
+
end
|
79
184
|
end
|
80
185
|
|
81
186
|
describe Inferx::Categories, '#add' do
|
@@ -152,38 +257,39 @@ describe Inferx::Categories, '#remove' do
|
|
152
257
|
end
|
153
258
|
|
154
259
|
describe Inferx::Categories, '#exists?' do
|
155
|
-
|
260
|
+
before do
|
156
261
|
redis = redis_stub.tap do |s|
|
157
|
-
s.
|
262
|
+
s.stub!(:hkeys => %w(red green blue))
|
158
263
|
end
|
159
264
|
|
160
|
-
categories = described_class.new(redis)
|
161
|
-
categories.exists?('red')
|
265
|
+
@categories = described_class.new(redis)
|
162
266
|
end
|
163
267
|
|
164
268
|
it 'returns true if the category is defined' do
|
165
|
-
|
166
|
-
s.stub!(:hexists => true)
|
167
|
-
end
|
168
|
-
|
169
|
-
categories = described_class.new(redis)
|
170
|
-
categories.should be_exists('red')
|
269
|
+
@categories.should be_exists('red')
|
171
270
|
end
|
172
271
|
|
173
272
|
it 'returns false if the category is not defined' do
|
174
|
-
|
175
|
-
|
273
|
+
@categories.should_not be_exists('cyan')
|
274
|
+
end
|
275
|
+
|
276
|
+
context 'when filtered' do
|
277
|
+
it 'returns true if the category is defined in filtered categories' do
|
278
|
+
categories = @categories.filter('red', 'green').except('red')
|
279
|
+
categories.should be_exists('green')
|
176
280
|
end
|
177
281
|
|
178
|
-
categories
|
179
|
-
|
282
|
+
it 'returns false if the category is not defined in filtered categories' do
|
283
|
+
categories = @categories.filter('red', 'green').except('red')
|
284
|
+
categories.should_not be_exists('red')
|
285
|
+
end
|
180
286
|
end
|
181
287
|
end
|
182
288
|
|
183
289
|
describe Inferx::Categories, '#each' do
|
184
290
|
before do
|
185
291
|
@redis = redis_stub do |s|
|
186
|
-
s.stub!(:hgetall => {
|
292
|
+
s.stub!(:hkeys => %w(red green blue), :hgetall => {
|
187
293
|
'red' => 2,
|
188
294
|
'green' => 3,
|
189
295
|
'blue' => 1
|
@@ -202,21 +308,181 @@ describe Inferx::Categories, '#each' do
|
|
202
308
|
categories.each { |category| n += 1 }
|
203
309
|
n.should == 3
|
204
310
|
end
|
311
|
+
|
312
|
+
context 'when filtered' do
|
313
|
+
it 'passes an instance of Inferx::Category in filtered categories to the block' do
|
314
|
+
categories = described_class.new(@redis)
|
315
|
+
categories = categories.filter('red', 'green').except('red')
|
316
|
+
category_names = []
|
317
|
+
categories.each { |category| category_names << category.name }
|
318
|
+
category_names.should == %w(green)
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
context 'when construct with :complementary option' do
|
323
|
+
it 'passes an instance of Inferx::Category::Complementary to the block' do
|
324
|
+
categories = described_class.new(@redis, :complementary => true)
|
325
|
+
categories.each { |category| category.should be_an(Inferx::Category::Complementary) }
|
326
|
+
end
|
327
|
+
end
|
205
328
|
end
|
206
329
|
|
207
|
-
describe Inferx::Categories, '#
|
330
|
+
describe Inferx::Categories, '#inject' do
|
208
331
|
before do
|
209
|
-
@
|
210
|
-
s.stub!(:
|
332
|
+
@redis = redis_stub do |s|
|
333
|
+
s.stub!(:hkeys => %w(red green blue))
|
334
|
+
s.stub!(:zincrby)
|
335
|
+
s.stub!(:hincrby)
|
336
|
+
end
|
337
|
+
|
338
|
+
@categories = described_class.new(@redis).filter('red', 'green')
|
339
|
+
end
|
340
|
+
|
341
|
+
it 'calls Redis#zincrby and Redis#hincrby for the categories' do
|
342
|
+
@redis.tap do |s|
|
343
|
+
s.should_receive(:zincrby).with('inferx:categories:red', 2, 'apple')
|
344
|
+
s.should_receive(:zincrby).with('inferx:categories:red', 3, 'strawberry')
|
345
|
+
s.should_receive(:hincrby).with('inferx:categories', 'red', 5)
|
346
|
+
|
347
|
+
s.should_receive(:zincrby).with('inferx:categories:green', 2, 'apple')
|
348
|
+
s.should_receive(:zincrby).with('inferx:categories:green', 3, 'strawberry')
|
349
|
+
s.should_receive(:hincrby).with('inferx:categories', 'green', 5)
|
350
|
+
|
351
|
+
s.should_not_receive(:zincrby).with('inferx:categories:blue', 2, 'apple')
|
352
|
+
s.should_not_receive(:zincrby).with('inferx:categories:blue', 3, 'strawberry')
|
353
|
+
s.should_not_receive(:hincrby).with('inferx:categories', 'blue', 5)
|
354
|
+
|
355
|
+
s.should_receive(:save)
|
211
356
|
end
|
357
|
+
|
358
|
+
@categories.inject(%w(apple strawberry apple strawberry strawberry))
|
212
359
|
end
|
213
360
|
|
214
|
-
it '
|
215
|
-
@categories.
|
216
|
-
|
361
|
+
it 'returns an instance of Hash' do
|
362
|
+
increases = @categories.inject(%w(apple strawberry apple strawberry strawberry))
|
363
|
+
increases.should be_a(Hash)
|
364
|
+
end
|
365
|
+
|
366
|
+
it 'returns increase for each category' do
|
367
|
+
increases = @categories.inject(%w(apple strawberry apple strawberry strawberry))
|
368
|
+
increases.should == {'red' => 5, 'green' => 5}
|
369
|
+
end
|
370
|
+
|
371
|
+
context 'with empty categories' do
|
372
|
+
it 'returns an empty hash' do
|
373
|
+
categories = @categories.except('red', 'green')
|
374
|
+
increases = categories.inject(%w(apple strawberry apple strawberry strawberry))
|
375
|
+
increases.should be_empty
|
376
|
+
end
|
217
377
|
end
|
218
378
|
|
219
|
-
|
220
|
-
|
379
|
+
context 'with empty words' do
|
380
|
+
it 'returns zero fluctuation' do
|
381
|
+
increases = @categories.inject([])
|
382
|
+
increases.should == {'red' => 0, 'green' => 0}
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
context 'with manual save' do
|
387
|
+
it 'does not call Redis#save' do
|
388
|
+
@redis.tap do |s|
|
389
|
+
s.should_not_receive(:save)
|
390
|
+
end
|
391
|
+
|
392
|
+
categories = described_class.new(@redis, :manual => true)
|
393
|
+
categories.inject(%w(apple strawberry apple strawberry strawberry))
|
394
|
+
end
|
395
|
+
end
|
396
|
+
end
|
397
|
+
|
398
|
+
describe Inferx::Categories, '#eject' do
|
399
|
+
before do
|
400
|
+
@redis = redis_stub do |s|
|
401
|
+
s.stub!(:hkeys => %w(red green blue))
|
402
|
+
|
403
|
+
s.stub!(:pipelined).and_return do |&block|
|
404
|
+
block.call
|
405
|
+
%w(3 2 0) + %w(3 2 0)
|
406
|
+
end
|
407
|
+
|
408
|
+
s.stub!(:zincrby)
|
409
|
+
s.stub!(:zremrangebyscore)
|
410
|
+
s.stub!(:hincrby)
|
411
|
+
end
|
412
|
+
|
413
|
+
@categories = described_class.new(@redis).filter('red', 'green')
|
414
|
+
end
|
415
|
+
|
416
|
+
it 'calls Redis#zincrby, Redis#zremrangebyscore and Redis#hincrby for the categories' do
|
417
|
+
@redis.tap do |s|
|
418
|
+
s.should_receive(:zincrby).with('inferx:categories:red', -2, 'apple')
|
419
|
+
s.should_receive(:zincrby).with('inferx:categories:red', -3, 'strawberry')
|
420
|
+
s.should_receive(:zremrangebyscore).with('inferx:categories:red', '-inf', 0)
|
421
|
+
s.should_receive(:hincrby).with('inferx:categories', 'red', -5)
|
422
|
+
|
423
|
+
s.should_receive(:zincrby).with('inferx:categories:green', -2, 'apple')
|
424
|
+
s.should_receive(:zincrby).with('inferx:categories:green', -3, 'strawberry')
|
425
|
+
s.should_receive(:zremrangebyscore).with('inferx:categories:green', '-inf', 0)
|
426
|
+
s.should_receive(:hincrby).with('inferx:categories', 'green', -5)
|
427
|
+
|
428
|
+
s.should_not_receive(:zincrby).with('inferx:categories:blue', 2, 'apple')
|
429
|
+
s.should_not_receive(:zincrby).with('inferx:categories:blue', 3, 'strawberry')
|
430
|
+
s.should_not_receive(:zremrangebyscore).with('inferx:categories:blue', '-inf', 0)
|
431
|
+
s.should_not_receive(:hincrby).with('inferx:categories', 'blue', 5)
|
432
|
+
|
433
|
+
s.should_receive(:save)
|
434
|
+
end
|
435
|
+
|
436
|
+
@categories.eject(%w(apple strawberry apple strawberry strawberry))
|
437
|
+
end
|
438
|
+
|
439
|
+
it 'returns an instance of Hash' do
|
440
|
+
decreases = @categories.eject(%w(apple strawberry apple strawberry strawberry))
|
441
|
+
decreases.should be_a(Hash)
|
442
|
+
end
|
443
|
+
|
444
|
+
it 'returns decrease for each category' do
|
445
|
+
decreases = @categories.eject(%w(apple strawberry apple strawberry strawberry))
|
446
|
+
decreases.should == {'red' => 5, 'green' => 5}
|
447
|
+
end
|
448
|
+
|
449
|
+
it 'adjusts decrease' do
|
450
|
+
@redis.tap do |s|
|
451
|
+
s.stub!(:pipelined).and_return do |&block|
|
452
|
+
block.call
|
453
|
+
%w(3 2 0) + %w(-1 -2 2)
|
454
|
+
end
|
455
|
+
|
456
|
+
s.should_receive(:hincrby).with('inferx:categories', 'green', -2)
|
457
|
+
end
|
458
|
+
|
459
|
+
decreases = @categories.eject(%w(apple strawberry apple strawberry strawberry))
|
460
|
+
decreases.should == {'red' => 5, 'green' => 2}
|
461
|
+
end
|
462
|
+
|
463
|
+
context 'with empty categories' do
|
464
|
+
it 'returns an empty hash' do
|
465
|
+
categories = @categories.except('red', 'green')
|
466
|
+
decreases = categories.eject(%w(apple strawberry apple strawberry strawberry))
|
467
|
+
decreases.should be_empty
|
468
|
+
end
|
469
|
+
end
|
470
|
+
|
471
|
+
context 'with empty words' do
|
472
|
+
it 'returns zero fluctuation' do
|
473
|
+
decreases = @categories.eject([])
|
474
|
+
decreases.should == {'red' => 0, 'green' => 0}
|
475
|
+
end
|
476
|
+
end
|
477
|
+
|
478
|
+
context 'with manual save' do
|
479
|
+
it 'does not call Redis#save' do
|
480
|
+
@redis.tap do |s|
|
481
|
+
s.should_not_receive(:save)
|
482
|
+
end
|
483
|
+
|
484
|
+
categories = described_class.new(@redis, :manual => true)
|
485
|
+
categories.eject(%w(apple strawberry apple strawberry strawberry))
|
486
|
+
end
|
221
487
|
end
|
222
488
|
end
|