picky 4.0.0pre1 → 4.0.0pre2

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.
Files changed (112) hide show
  1. data/aux/picky/cli.rb +6 -2
  2. data/lib/picky.rb +10 -8
  3. data/lib/picky/backends/backend.rb +37 -0
  4. data/lib/picky/backends/file.rb +0 -20
  5. data/lib/picky/backends/memory.rb +0 -29
  6. data/lib/picky/backends/redis.rb +74 -15
  7. data/lib/picky/backends/redis/list.rb +1 -1
  8. data/lib/picky/backends/sqlite.rb +0 -27
  9. data/lib/picky/bundle.rb +2 -2
  10. data/lib/picky/bundle_indexed.rb +1 -1
  11. data/lib/picky/bundle_indexing.rb +1 -1
  12. data/lib/picky/categories_indexed.rb +1 -11
  13. data/lib/picky/category.rb +4 -4
  14. data/lib/picky/category/location.rb +25 -0
  15. data/lib/picky/category_realtime.rb +4 -3
  16. data/lib/picky/console.rb +1 -1
  17. data/lib/picky/constants.rb +1 -1
  18. data/lib/picky/ext/maybe_compile.rb +2 -2
  19. data/lib/picky/extensions/object.rb +3 -2
  20. data/lib/picky/generators/aliases.rb +7 -2
  21. data/lib/picky/generators/partial/default.rb +1 -0
  22. data/lib/picky/generators/similarity/default.rb +1 -0
  23. data/lib/picky/generators/similarity/phonetic.rb +13 -2
  24. data/lib/picky/generators/strategy.rb +0 -2
  25. data/lib/picky/generators/weights/constant.rb +1 -2
  26. data/lib/picky/generators/weights/default.rb +1 -0
  27. data/lib/picky/generators/weights/dynamic.rb +1 -1
  28. data/lib/picky/generators/weights/logarithmic.rb +1 -1
  29. data/lib/picky/generators/weights/{runtime.rb → stub.rb} +1 -3
  30. data/lib/picky/index.rb +3 -3
  31. data/lib/picky/index_indexing.rb +0 -2
  32. data/lib/picky/index_realtime.rb +1 -1
  33. data/lib/picky/indexers/base.rb +7 -0
  34. data/lib/picky/indexers/parallel.rb +2 -4
  35. data/lib/picky/indexers/serial.rb +2 -0
  36. data/lib/picky/indexes_indexing.rb +1 -1
  37. data/lib/picky/interfaces/live_parameters/master_child.rb +175 -0
  38. data/lib/picky/interfaces/live_parameters/unicorn.rb +37 -0
  39. data/lib/picky/loader.rb +238 -259
  40. data/lib/picky/query/allocation.rb +19 -10
  41. data/lib/picky/query/combination.rb +7 -1
  42. data/lib/picky/query/combinations.rb +1 -6
  43. data/lib/picky/query/token.rb +26 -36
  44. data/lib/picky/results.rb +18 -17
  45. data/lib/picky/scheduler.rb +2 -1
  46. data/lib/picky/search.rb +1 -1
  47. data/lib/picky/sinatra.rb +6 -6
  48. data/lib/picky/statistics.rb +2 -0
  49. data/lib/picky/tokenizer.rb +8 -8
  50. data/lib/picky/wrappers/bundle/calculation.rb +4 -4
  51. data/lib/picky/wrappers/bundle/location.rb +1 -2
  52. data/lib/tasks/framework.rake +1 -1
  53. data/lib/tasks/statistics.rake +1 -1
  54. data/lib/tasks/try.rake +1 -1
  55. data/lib/tasks/try.rb +1 -1
  56. data/spec/aux/picky/cli_spec.rb +12 -12
  57. data/spec/ext/performant_spec.rb +16 -16
  58. data/spec/functional/backends/file_spec.rb +78 -7
  59. data/spec/functional/backends/memory_spec.rb +78 -7
  60. data/spec/functional/backends/redis_spec.rb +73 -13
  61. data/spec/functional/dynamic_weights_spec.rb +3 -4
  62. data/spec/functional/realtime_spec.rb +2 -2
  63. data/spec/functional/speed_spec.rb +2 -2
  64. data/spec/functional/terminate_early_spec.rb +3 -3
  65. data/spec/lib/analytics_spec.rb +1 -1
  66. data/spec/lib/analyzer_spec.rb +5 -3
  67. data/spec/lib/categories_indexed_spec.rb +38 -20
  68. data/spec/lib/category/location_spec.rb +30 -0
  69. data/spec/lib/character_substituters/west_european_spec.rb +1 -0
  70. data/spec/lib/extensions/hash_spec.rb +6 -5
  71. data/spec/lib/extensions/module_spec.rb +6 -6
  72. data/spec/lib/extensions/object_spec.rb +9 -8
  73. data/spec/lib/extensions/string_spec.rb +1 -1
  74. data/spec/lib/generators/similarity/phonetic_spec.rb +11 -0
  75. data/spec/lib/index_realtime_spec.rb +5 -5
  76. data/spec/lib/interfaces/{live_parameters_spec.rb → live_parameters/master_child_spec.rb} +26 -26
  77. data/spec/lib/interfaces/live_parameters/unicorn_spec.rb +160 -0
  78. data/spec/lib/loader_spec.rb +65 -25
  79. data/spec/lib/query/allocation_spec.rb +25 -22
  80. data/spec/lib/query/combinations_spec.rb +13 -36
  81. data/spec/lib/query/token_spec.rb +144 -131
  82. data/spec/lib/query/tokens_spec.rb +14 -0
  83. data/spec/lib/results_spec.rb +14 -8
  84. data/spec/lib/search_spec.rb +1 -1
  85. data/spec/lib/sinatra_spec.rb +8 -8
  86. metadata +28 -91
  87. data/lib/picky/adapters/rack.rb +0 -34
  88. data/lib/picky/adapters/rack/base.rb +0 -27
  89. data/lib/picky/adapters/rack/live_parameters.rb +0 -37
  90. data/lib/picky/adapters/rack/search.rb +0 -67
  91. data/lib/picky/application.rb +0 -268
  92. data/lib/picky/frontend_adapters/rack.rb +0 -161
  93. data/lib/picky/interfaces/live_parameters.rb +0 -187
  94. data/lib/picky/sources/base.rb +0 -92
  95. data/lib/picky/sources/couch.rb +0 -76
  96. data/lib/picky/sources/csv.rb +0 -83
  97. data/lib/picky/sources/db.rb +0 -189
  98. data/lib/picky/sources/delicious.rb +0 -63
  99. data/lib/picky/sources/mongo.rb +0 -80
  100. data/lib/picky/wrappers/category/location.rb +0 -38
  101. data/lib/tasks/routes.rake +0 -8
  102. data/spec/lib/adapters/rack/base_spec.rb +0 -24
  103. data/spec/lib/adapters/rack/live_parameters_spec.rb +0 -26
  104. data/spec/lib/adapters/rack/query_spec.rb +0 -39
  105. data/spec/lib/application_spec.rb +0 -155
  106. data/spec/lib/frontend_adapters/rack_spec.rb +0 -294
  107. data/spec/lib/sources/base_spec.rb +0 -53
  108. data/spec/lib/sources/couch_spec.rb +0 -114
  109. data/spec/lib/sources/csv_spec.rb +0 -89
  110. data/spec/lib/sources/db_spec.rb +0 -125
  111. data/spec/lib/sources/delicious_spec.rb +0 -94
  112. data/spec/lib/sources/mongo_spec.rb +0 -50
@@ -12,105 +12,40 @@ describe Picky::Query::Token do
12
12
  end
13
13
  end
14
14
 
15
- describe 'next_similar_token' do
16
- before(:each) do
17
- @bundle = stub :bundle, :similar => [:array, :of, :similar]
18
- @category = stub :category, :bundle_for => @bundle
19
-
20
- @token = described_class.processed 'similar~', 'Similar~'
21
- end
22
- it 'returns the right next tokens' do
23
- next_token = @token.next_similar_token @category
24
- next_token.text.should == :array
25
- next_token = next_token.next_similar_token @category
26
- next_token.text.should == :of
27
- next_token = next_token.next_similar_token @category
28
- next_token.text.should == :similar
29
- next_token = next_token.next_similar_token @category
30
- next_token.should == nil
31
- end
32
- end
33
-
34
- describe 'next_similar' do
35
- before(:each) do
36
- @bundle = stub :bundle
37
- end
38
- describe 'original' do
39
- context 'with stub' do
40
- before(:each) do
41
- @bundle.stub! :similar => [:array, :of, :similar]
42
-
43
- @token = described_class.processed 'similar~', 'Similar'
44
- end
45
- it 'should have a certain original text' do
46
- @token.next_similar @bundle
47
-
48
- @token.original.should == :array
49
- end
15
+ describe 'similar_tokens_for' do
16
+ let(:token) { described_class.processed 'similar~', 'Similar~' }
17
+ context 'with similar' do
18
+ before(:each) do
19
+ @bundle = stub :bundle, :similar => ['array', 'of', 'similar']
20
+ @category = stub :category, :bundle_for => @bundle
50
21
  end
51
- end
52
- context 'similar' do
53
- context 'with stub' do
54
- before(:each) do
55
- @bundle.stub! :similar => [:array, :of, :similar]
56
-
57
- @token = described_class.processed 'similar~', 'Similar'
58
- end
59
- it 'generates all similar' do
60
- @token.next_similar(@bundle).should == :array
61
- @token.next_similar(@bundle).should == :of
62
- @token.next_similar(@bundle).should == :similar
63
- @token.next_similar(@bundle).should == nil
64
- end
65
- it 'should have a certain text' do
66
- @token.next_similar @bundle
67
- @token.next_similar @bundle
68
- @token.next_similar @bundle
69
- @token.next_similar @bundle
70
-
71
- @token.text.should == :similar
22
+ it 'returns a list of tokens' do
23
+ token.similar_tokens_for(@category).each do |token|
24
+ token.should be_kind_of(described_class)
72
25
  end
73
26
  end
74
- end
75
- context 'non-similar' do
76
- context 'with stub' do
77
- before(:each) do
78
- @bundle.stub! :similar => [:array, :of, :similar]
79
-
80
- @token = described_class.processed 'nonsimilar', 'Nonsimilar'
81
- end
82
- it 'generates all similar' do
83
- @token.next_similar(@bundle).should == nil
84
- end
85
- it 'should have a certain text' do
86
- @token.next_similar @bundle
87
-
88
- @token.text.should == 'nonsimilar'
27
+ it 'returns all non-similar tokens' do
28
+ token.similar_tokens_for(@category).each do |token|
29
+ token.should_not be_similar
89
30
  end
90
31
  end
91
- end
92
- end
93
-
94
- describe "generate_similarity_for" do
95
- before(:each) do
96
- @bundle = stub :bundle
97
-
98
- @token = described_class.processed 'flarb~', 'FLARB~'
99
- end
100
- context "with similar" do
101
- before(:each) do
102
- @bundle.stub! :similar => [:array, :of, :similar]
32
+ it 'returns a list of tokens with the right text' do
33
+ token.similar_tokens_for(@category).map(&:text).should == ['array', 'of', 'similar']
34
+ end
35
+ it 'returns a list of tokens with the right original' do
36
+ token.similar_tokens_for(@category).map(&:original).should == ['array', 'of', 'similar']
103
37
  end
104
- it "returns an array of the right size" do
105
- @token.generate_similarity_for(@bundle).size.should == 3
38
+ it 'returns a list of tokens with the right categorization' do
39
+ token.similar_tokens_for(@category).map(&:user_defined_categories).should == [[@category], [@category], [@category]]
106
40
  end
107
41
  end
108
- context "without similar" do
42
+ context 'without similar' do
109
43
  before(:each) do
110
- @bundle.stub! :similar => []
44
+ @bundle = stub :bundle, :similar => []
45
+ @category = stub :category, :bundle_for => @bundle
111
46
  end
112
- it "returns an array of the right size" do
113
- @token.generate_similarity_for(@bundle).size.should == 0
47
+ it 'returns an empty list' do
48
+ token.similar_tokens_for(@category).should == []
114
49
  end
115
50
  end
116
51
  end
@@ -167,12 +102,24 @@ describe Picky::Query::Token do
167
102
  it_should_qualify 'a,b,c:d', [['a','b','c'], 'd']
168
103
  it_should_qualify ':', [nil, '']
169
104
  it_should_qualify 'vorname:qualifier', [['vorname'], 'qualifier']
170
- it_should_qualify 'with:qualifier', [['with'], 'qualifier']
171
- it_should_qualify 'without qualifier', [nil, 'without qualifier']
172
- it_should_qualify 'name:', [nil, 'name']
173
- it_should_qualify ':broken qualifier', [[], 'broken qualifier']
174
- it_should_qualify '', [nil, '']
175
- it_should_qualify 'fn:text', [['fn'], 'text']
105
+ end
106
+
107
+ describe 'qualifier' do
108
+ it 'returns the right thing' do
109
+ token = described_class.processed 'b'
110
+
111
+ token.qualifiers.should == []
112
+ end
113
+ it 'returns the right thing' do
114
+ token = described_class.processed 'a:b'
115
+
116
+ token.qualifiers.should == ['a']
117
+ end
118
+ it 'returns the right thing' do
119
+ token = described_class.processed 'a,b:c'
120
+
121
+ token.qualifiers.should == ['a', 'b']
122
+ end
176
123
  end
177
124
 
178
125
  describe 'processed' do
@@ -199,6 +146,76 @@ describe Picky::Query::Token do
199
146
  end
200
147
  end
201
148
 
149
+ describe 'partialize' do
150
+ context 'token explicitly partial' do
151
+ let(:token) { described_class.new 'a*' }
152
+ it 'is afterwards partial' do
153
+ token.partialize
154
+
155
+ token.should be_partial
156
+ end
157
+ end
158
+ context 'token explicitly nonpartial' do
159
+ let(:token) { described_class.new 'a"' }
160
+ it 'is afterwards not partial' do
161
+ token.partialize
162
+
163
+ token.should_not be_partial
164
+ end
165
+ end
166
+ context 'token nonpartial' do
167
+ let(:token) { described_class.new 'a' }
168
+ it 'is afterwards not partial' do
169
+ token.partialize
170
+
171
+ token.should_not be_partial
172
+ end
173
+ end
174
+ context 'special case' do
175
+ let(:token) { described_class.new 'a*"' }
176
+ it 'is afterwards not partial - last one wins' do
177
+ token.partialize
178
+
179
+ token.should_not be_partial
180
+ end
181
+ end
182
+ context 'special case' do
183
+ let(:token) { described_class.new 'a"*' }
184
+ it 'is afterwards partial - last one wins' do
185
+ token.partialize
186
+
187
+ token.should be_partial
188
+ end
189
+ end
190
+ end
191
+
192
+ describe 'similarize' do
193
+ context 'token explicitly similar' do
194
+ let(:token) { described_class.new 'a~' }
195
+ it 'is afterwards similar' do
196
+ token.similarize
197
+
198
+ token.should be_similar
199
+ end
200
+ end
201
+ context 'token explicitly nonsimilar' do
202
+ let(:token) { described_class.new 'a"' }
203
+ it 'is afterwards not similar' do
204
+ token.similarize
205
+
206
+ token.should_not be_similar
207
+ end
208
+ end
209
+ context 'token nonsimilar' do
210
+ let(:token) { described_class.new 'a' }
211
+ it 'is afterwards not similar' do
212
+ token.similarize
213
+
214
+ token.should_not be_similar
215
+ end
216
+ end
217
+ end
218
+
202
219
  describe 'symbolize!' do
203
220
  before(:each) do
204
221
  @token = described_class.processed 'string', 'String'
@@ -323,70 +340,66 @@ describe Picky::Query::Token do
323
340
 
324
341
  describe 'qualifiers' do
325
342
  context 'with qualifier' do
326
- before(:each) do
327
- @token = described_class.processed('sp:qualifier')
328
- end
343
+ let(:token) { described_class.processed 'sp:qualifier' }
329
344
  it 'should return the qualifier' do
330
- @token.qualifiers.should == ['sp']
345
+ token.qualifiers.should == ['sp']
331
346
  end
332
347
  end
333
348
  context 'with incorrect qualifier' do
334
- before(:each) do
335
- @token = described_class.processed('specific:qualifier')
336
- end
349
+ let(:token) { described_class.processed 'specific:qualifier' }
337
350
  it 'should return the qualifier' do
338
- @token.qualifiers.should == ['specific']
351
+ token.qualifiers.should == ['specific']
339
352
  end
340
353
  end
341
354
  context 'with multiple qualifiers' do
342
- before(:each) do
343
- @token = described_class.processed('sp,spec:qualifier')
344
- end
355
+ let(:token) { described_class.processed 'sp,spec:qualifier' }
345
356
  it 'should return the qualifier' do
346
- @token.qualifiers.should == ['sp', 'spec']
357
+ token.qualifiers.should == ['sp', 'spec']
347
358
  end
348
359
  end
349
360
  context 'without qualifier' do
350
- before(:each) do
351
- @token = described_class.processed('noqualifier')
352
- end
353
- it 'should return nil' do
354
- @token.qualifiers.should == nil
361
+ let(:token) { described_class.processed 'noqualifier' }
362
+ it 'is correct' do
363
+ token.qualifiers.should == []
355
364
  end
356
365
  end
357
366
  end
358
367
 
359
368
  describe 'partial=' do
360
369
  context 'partial nil' do
361
- before(:each) do
362
- @token = described_class.new 'text'
363
- end
370
+ let(:token) { described_class.new 'text' }
364
371
  it 'should set partial' do
365
- @token.partial = true
372
+ token.partial = true
366
373
 
367
- @token.instance_variable_get(:@partial).should be_true
374
+ token.should be_partial
368
375
  end
369
376
  it 'should set partial' do
370
- @token.partial = false
377
+ token.partial = false
371
378
 
372
- @token.instance_variable_get(:@partial).should be_false
379
+ token.should_not be_partial
373
380
  end
374
381
  end
375
382
  context 'partial not nil' do
376
- before(:each) do
377
- @token = described_class.processed 'text*'
383
+ let(:token) { described_class.processed 'text"' }
384
+ it 'should not set partial' do
385
+ token.partial = true
386
+
387
+ token.should_not be_partial
378
388
  end
389
+ end
390
+ context 'partial not nil' do
391
+ let(:token) { described_class.processed 'text*' }
379
392
  it 'should not set partial' do
380
- @token.instance_variable_set :@partial, false
393
+ token.instance_variable_set :@partial, false
381
394
 
382
- @token.partial = true
395
+ token.partial = true
383
396
 
384
- @token.instance_variable_get(:@partial).should be_false
397
+ token.should_not be_partial
385
398
  end
386
399
  it 'should not set partial' do
387
- @token.partial = false
400
+ token.partial = false
388
401
 
389
- @token.instance_variable_get(:@partial).should be_true
402
+ token.should be_partial
390
403
  end
391
404
  end
392
405
  end
@@ -395,27 +408,27 @@ describe Picky::Query::Token do
395
408
  it 'should not partialize a token if the text ends with "' do
396
409
  token = described_class.processed 'text"'
397
410
 
398
- token.instance_variable_get(:@partial).should be_false
411
+ token.should_not be_partial
399
412
  end
400
413
  it 'should partialize a token if the text ends with *' do
401
414
  token = described_class.processed 'text*'
402
415
 
403
- token.instance_variable_get(:@partial).should be_true
416
+ token.should be_partial
404
417
  end
405
418
  it 'should not partialize a token if the text ends with ~' do
406
419
  token = described_class.processed 'text~'
407
420
 
408
- token.instance_variable_get(:@partial).should be_nil
421
+ token.should_not be_partial
409
422
  end
410
423
  it 'lets the last one win' do
411
424
  token = described_class.processed 'text"*'
412
425
 
413
- token.partial?.should == true
426
+ token.should be_partial
414
427
  end
415
428
  it 'lets the last one win' do
416
429
  token = described_class.processed 'text*"'
417
430
 
418
- token.partial?.should == false
431
+ token.should_not be_partial
419
432
  end
420
433
  end
421
434
 
@@ -106,6 +106,20 @@ describe Picky::Query::Tokens do
106
106
  @token.should be_partial
107
107
  end
108
108
  end
109
+ context 'special case' do
110
+ before(:each) do
111
+ @token = Picky::Query::Token.processed 'a"'
112
+ @tokens = described_class.new [@token]
113
+ end
114
+ it 'should not have a last partialized token' do
115
+ @token.should_not be_partial
116
+ end
117
+ it 'should not partialize the last token' do
118
+ @tokens.partialize_last
119
+
120
+ @token.should_not be_partial
121
+ end
122
+ end
109
123
  context 'one token' do
110
124
  before(:each) do
111
125
  @token = Picky::Query::Token.processed 'Token'
@@ -1,19 +1,19 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Picky::Results do
4
-
4
+
5
5
  describe "from" do
6
6
  before(:each) do
7
7
  @results = stub :results
8
8
  described_class.stub! :new => @results
9
-
9
+
10
10
  @results.stub! :prepare!
11
11
  end
12
12
  it "should generate a result" do
13
13
  described_class.from("some query", 20, 0, @allocations).should == @results
14
14
  end
15
15
  end
16
-
16
+
17
17
  describe "ids" do
18
18
  before(:each) do
19
19
  @allocations = stub :allocations
@@ -21,14 +21,20 @@ describe Picky::Results do
21
21
  end
22
22
  it "delegates" do
23
23
  @allocations.should_receive(:ids).once.with :anything
24
-
24
+
25
25
  @results.ids :anything
26
26
  end
27
27
  end
28
-
28
+
29
+ describe 'to_s time format' do
30
+ it 'is in the right format' do
31
+ described_class.new("some_query").to_s.should match(/\d{2}\-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/)
32
+ end
33
+ end
34
+
29
35
  describe 'to_s' do
30
36
  before(:each) do
31
- time = stub :time, :to_s => '0-08-16 10:07:33'
37
+ time = stub :time, :strftime => '2011-08-16 10:07:33'
32
38
  Time.stub! :now => time
33
39
  end
34
40
  context 'without results' do
@@ -36,7 +42,7 @@ describe Picky::Results do
36
42
  @results = described_class.new "some_query"
37
43
  end
38
44
  it 'should output a default log' do
39
- @results.to_s.should == '.|0-08-16 10:07:33|0.000000|some_query | 0| 0| 0|'
45
+ @results.to_s.should == '.|2011-08-16 10:07:33|0.000000|some_query | 0| 0| 0|'
40
46
  end
41
47
  end
42
48
  context 'with results' do
@@ -50,7 +56,7 @@ describe Picky::Results do
50
56
  :total => 12345678
51
57
  end
52
58
  it 'should output a specific log' do
53
- @results.to_s.should == '>|0-08-16 10:07:33|0.123457|some_query |12345678|1234|12|'
59
+ @results.to_s.should == '>|2011-08-16 10:07:33|0.123457|some_query |12345678|1234|12|'
54
60
  end
55
61
  end
56
62
  end