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
@@ -0,0 +1,160 @@
1
+ # encoding: utf-8
2
+ #
3
+ require 'spec_helper'
4
+
5
+ describe Picky::Interfaces::LiveParameters::Unicorn do
6
+
7
+ before(:each) do
8
+ @parent = stub :parent
9
+ @child = stub :child
10
+ IO.stub! :pipe => [@child, @parent]
11
+ @parameters = described_class.new
12
+ @parameters.stub! :exclaim
13
+ end
14
+
15
+ describe Picky::Interfaces::LiveParameters::Unicorn::CouldNotUpdateConfigurationError do
16
+ before(:each) do
17
+ @error = Picky::Interfaces::LiveParameters::Unicorn::CouldNotUpdateConfigurationError.new :some_key, 'some message'
18
+ end
19
+ end
20
+
21
+ describe 'querying_removes_characters' do
22
+ it 'works' do
23
+ expect do
24
+ @parameters.querying_removes_characters
25
+ end.to_not raise_error
26
+ end
27
+ end
28
+ describe 'querying_stopwords' do
29
+ it 'works' do
30
+ expect do
31
+ @parameters.querying_stopwords
32
+ end.to_not raise_error
33
+ end
34
+ end
35
+ describe 'querying_splits_text_on' do
36
+ it 'works' do
37
+ expect do
38
+ @parameters.querying_splits_text_on
39
+ end.to_not raise_error
40
+ end
41
+ end
42
+
43
+ describe 'parameters' do
44
+ context 'all goes well' do
45
+ it 'does a few things in order' do
46
+ @parameters.should_receive(:close_child).once.with().ordered
47
+ @parameters.should_receive(:try_updating_configuration_with).once.with(:a => :b).ordered
48
+ @parameters.should_receive(:write_parent).once.with(:a => :b).ordered
49
+ @parameters.should_receive(:extract_configuration).once.with().ordered
50
+
51
+ @parameters.parameters :a => :b
52
+ end
53
+ end
54
+ context 'updating failed' do
55
+ before(:each) do
56
+ @parameters.should_receive(:try_updating_configuration_with).and_raise Picky::Interfaces::LiveParameters::Unicorn::CouldNotUpdateConfigurationError.new(:a, 'hello')
57
+ end
58
+ it 'kills itself and returns' do
59
+ @parameters.should_receive(:close_child).once.ordered
60
+ @parameters.should_receive(:harakiri).once.ordered
61
+
62
+ @parameters.parameters( :a => :b ).should == { :a => :ERROR }
63
+ end
64
+ end
65
+ end
66
+
67
+ describe 'harakiri' do
68
+ before(:each) do
69
+ Process.stub! :pid => :some_pid
70
+ end
71
+ it 'kills itself' do
72
+ Process.should_receive(:kill).once.with :QUIT, :some_pid
73
+
74
+ @parameters.harakiri
75
+ end
76
+ end
77
+
78
+ describe 'write_parent' do
79
+ before(:each) do
80
+ Process.stub! :pid => :some_pid
81
+ end
82
+ it 'calls the parent' do
83
+ @parent.should_receive(:write).once.with "[:some_pid, {:a=>:b}];;;"
84
+
85
+ @parameters.write_parent :a => :b
86
+ end
87
+ end
88
+
89
+ describe 'close_child' do
90
+ context 'child is closed' do
91
+ before(:each) do
92
+ @child.stub! :closed? => true
93
+ end
94
+ it 'does not receive close' do
95
+ @child.should_receive(:close).never
96
+
97
+ @parameters.close_child
98
+ end
99
+ end
100
+ context 'child not yet closed' do
101
+ before(:each) do
102
+ @child.stub! :closed? => false
103
+ end
104
+ it 'does receives close' do
105
+ @child.should_receive(:close).once.with()
106
+
107
+ @parameters.close_child
108
+ end
109
+ end
110
+ end
111
+
112
+ describe 'kill_worker' do
113
+ context 'all goes well' do
114
+ it 'uses Process.kill' do
115
+ Process.should_receive(:kill).once.with :some_signal, :some_pid
116
+
117
+ @parameters.kill_worker :some_signal, :some_pid
118
+ end
119
+ end
120
+ context 'there is no such process' do
121
+ it 'uses Process.kill' do
122
+ Process.should_receive(:kill).and_raise Errno::ESRCH.new
123
+
124
+ @parameters.should_receive(:remove_worker).once.with :some_pid
125
+
126
+ @parameters.kill_worker :some_signal, :some_pid
127
+ end
128
+ end
129
+ end
130
+
131
+ describe 'kill_each_worker_except' do
132
+ context 'worker pid in the worker pids' do
133
+ before(:each) do
134
+ @parameters.stub! :worker_pids => [1,2,3,4]
135
+ end
136
+ it 'kills each except the one' do
137
+ @parameters.should_receive(:kill_worker).once.with(:KILL, 1)
138
+ @parameters.should_receive(:kill_worker).once.with(:KILL, 2)
139
+
140
+ @parameters.should_receive(:kill_worker).once.with(:KILL, 4)
141
+
142
+ @parameters.kill_each_worker_except 3
143
+ end
144
+ end
145
+ context 'worker pid not in the worker pids (unrealistic, but...)' do
146
+ before(:each) do
147
+ @parameters.stub! :worker_pids => [1,2,3,4]
148
+ end
149
+ it 'kills each except the one' do
150
+ @parameters.should_receive(:kill_worker).once.with(:KILL, 1)
151
+ @parameters.should_receive(:kill_worker).once.with(:KILL, 2)
152
+ @parameters.should_receive(:kill_worker).once.with(:KILL, 3)
153
+ @parameters.should_receive(:kill_worker).once.with(:KILL, 4)
154
+
155
+ @parameters.kill_each_worker_except 5
156
+ end
157
+ end
158
+ end
159
+
160
+ end
@@ -3,62 +3,102 @@ require 'spec_helper'
3
3
  describe Picky::Loader do
4
4
 
5
5
  before(:each) do
6
+ described_class.stub! :exclaim
6
7
  @loader_path = File.absolute_path("#{File.dirname(__FILE__)}/../../lib/picky/loader.rb")
7
8
  end
8
-
9
+
10
+ describe 'load self and framework' do
11
+ it 'it is quick' do
12
+ performance_of do
13
+ described_class.load_self
14
+ described_class.load_framework
15
+ end.should < 0.025
16
+ end
17
+ end
18
+
9
19
  describe 'load_application' do
10
- before(:each) do
11
- Picky::Application.stub! :reload
20
+ it 'does ok' do
21
+ Kernel.should_receive(:load).once.with 'spec/test_directory/app.rb'
22
+
23
+ lambda { described_class.load_application }.should_not raise_error
12
24
  end
13
- it "does ok" do
14
- lambda { Picky::Loader.load_application }.should_not raise_error
25
+ it 'loads correctly' do
26
+ described_class.should_receive(:load_user).once.with 'app'
27
+
28
+ described_class.load_application
29
+ end
30
+ it 'loads correctly' do
31
+ described_class.should_receive(:load_user).once.with 'special_app'
32
+
33
+ described_class.load_application 'special_app'
15
34
  end
16
35
  end
17
-
36
+
18
37
  describe 'load_framework' do
19
38
  before(:each) do
20
- Picky::Loader.stub! :load_relative
39
+ described_class.stub! :load_relative
21
40
  end
22
- it "does ok" do
23
- lambda { Picky::Loader.load_framework }.should_not raise_error
41
+ it 'does ok' do
42
+ lambda { described_class.load_framework }.should_not raise_error
24
43
  end
25
44
  end
26
-
45
+
27
46
  describe 'load_self' do
28
47
  before(:each) do
29
- Picky::Loader.stub! :load
30
- Picky::Loader.stub! :exclaim
48
+ described_class.stub! :load
31
49
  end
32
50
  after(:each) do
33
- Picky::Loader.load_self
51
+ described_class.load_self
34
52
  end
35
53
  it 'should load __SELF__' do
36
- Picky::Loader.should_receive(:load).once.with @loader_path
54
+ Kernel.should_receive(:load).once.with @loader_path
37
55
  end
38
56
  end
39
57
 
40
58
  describe 'reload' do
41
59
  before(:each) do
42
60
  load @loader_path
43
- Picky::Loader.stub! :exclaim
44
- Picky::Loader.stub! :load_framework
45
- Picky::Loader.stub! :load_application
61
+ described_class.stub! :load_framework
62
+ described_class.stub! :load_application
63
+ Dir.stub! :chdir
64
+ end
65
+ it 'should call the right methods in order' do
66
+ described_class.should_receive(:load_self).ordered
67
+ described_class.should_receive(:load_framework).ordered
68
+ described_class.should_receive(:load_application).ordered
69
+
70
+ described_class.reload
71
+ end
72
+ it 'should load itself only once' do
73
+ described_class.should_receive(:load_self).once
74
+
75
+ described_class.reload
76
+ end
77
+ # it 'can load a specific app' do
78
+ # described_class.should_receive(:load_application).once.with 'special_app'
79
+ #
80
+ # described_class.reload 'special_app'
81
+ # end
82
+ end
83
+
84
+ describe 'load' do
85
+ before(:each) do
86
+ load @loader_path
87
+ described_class.stub! :load_framework
88
+ described_class.stub! :load_application
46
89
  Dir.stub! :chdir
47
90
  end
48
91
  after(:each) do
49
- Picky::Loader.reload
92
+ described_class.load
50
93
  end
51
94
  it 'should call the right methods in order' do
52
- Picky::Loader.should_receive(:load_self).ordered
53
- Picky::Loader.should_receive(:load_framework).ordered
54
- Picky::Loader.should_receive(:load_application).ordered
95
+ described_class.should_receive(:load_self).ordered
96
+ described_class.should_receive(:load_framework).ordered
97
+ described_class.should_receive(:load_application).ordered
55
98
  end
56
99
  it 'should load itself only once' do
57
- Picky::Loader.should_receive(:load_self).once
100
+ described_class.should_receive(:load_self).once
58
101
  end
59
- # it 'should load the app only once' do
60
- # Loader.should_receive(:load_framework).once
61
- # end
62
102
  end
63
103
 
64
104
  end
@@ -1,30 +1,22 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Picky::Query::Allocation do
4
-
4
+
5
5
  before(:each) do
6
6
  @backend = stub :backend
7
7
  @index = stub :index, :result_identifier => :some_result_identifier, :backend => @backend
8
8
  @combinations = stub :combinations, :empty? => false
9
9
  @allocation = described_class.new @index, @combinations
10
10
  end
11
-
12
- describe "eql?" do
13
- # TODO This works, but is not acceptable.
14
- #
15
- it "returns true" do
16
- @allocation.eql?(:anything).should == true
17
- end
18
- end
19
-
11
+
20
12
  describe "hash" do
21
13
  it "delegates to the combinations" do
22
14
  @combinations.should_receive(:hash).once.with
23
-
15
+
24
16
  @allocation.hash
25
17
  end
26
18
  end
27
-
19
+
28
20
  describe "to_s" do
29
21
  before(:each) do
30
22
  @combinations.stub! :to_result => 'combinations_result'
@@ -40,15 +32,15 @@ describe Picky::Query::Allocation do
40
32
  end
41
33
  end
42
34
  end
43
-
35
+
44
36
  describe 'remove' do
45
37
  it 'should delegate to the combinations' do
46
38
  @combinations.should_receive(:remove).once.with [:some_categories]
47
-
39
+
48
40
  @allocation.remove [:some_categories]
49
41
  end
50
42
  end
51
-
43
+
52
44
  describe 'process!' do
53
45
  context 'no ids' do
54
46
  before(:each) do
@@ -130,7 +122,7 @@ describe Picky::Query::Allocation do
130
122
  context 'with ids' do
131
123
  it 'should output an array of information' do
132
124
  @backend.stub! :ids => [1,2,3]
133
-
125
+
134
126
  @allocation.process! 20, 0
135
127
 
136
128
  @allocation.to_result.should == [:some_result_identifier, :some_score, 3, [:some_result], [1, 2, 3]]
@@ -148,7 +140,7 @@ describe Picky::Query::Allocation do
148
140
  context 'with ids' do
149
141
  it 'should output an array of information' do
150
142
  @backend.stub! :ids => [1,2,3]
151
-
143
+
152
144
  @allocation.process! 20, 0
153
145
 
154
146
  @allocation.to_result.should == [:some_result_identifier, :some_score, 3, [:some_result1, :some_result2], [1, 2, 3]]
@@ -162,7 +154,7 @@ describe Picky::Query::Allocation do
162
154
  end
163
155
  it 'should return nil' do
164
156
  @backend.stub! :ids => []
165
-
157
+
166
158
  @allocation.process! 20, 0
167
159
 
168
160
  @allocation.to_result.should == nil
@@ -177,7 +169,7 @@ describe Picky::Query::Allocation do
177
169
  end
178
170
  it 'should output the correct json string' do
179
171
  @backend.stub! :ids => [1,2,3,4,5,6,7]
180
-
172
+
181
173
  @allocation.process! 20, 0
182
174
 
183
175
  @allocation.to_json.should == '["some_result_identifier","some_score",7,["some_result1","some_result2"],[1,2,3,4,5,6,7]]'
@@ -185,10 +177,21 @@ describe Picky::Query::Allocation do
185
177
  end
186
178
 
187
179
  describe "calculate_score" do
188
- it 'should delegate to the combinations' do
189
- @combinations.should_receive(:calculate_score).once.with :some_weights
180
+ context 'non-empty combinations' do
181
+ it 'should delegate to backend and combinations' do
182
+ @backend.should_receive(:weight).once.with(@combinations).and_return 1
183
+ @combinations.should_receive(:weighted_score).once.with(:some_weights).and_return 2
190
184
 
191
- @allocation.calculate_score :some_weights
185
+ @allocation.calculate_score(:some_weights).should == 3
186
+ end
187
+ end
188
+ context 'empty combinations' do
189
+ before(:each) do
190
+ @combinations.stub! :empty? => true
191
+ end
192
+ it 'should just be zero' do
193
+ @allocation.calculate_score(:some_weights).should == 0
194
+ end
192
195
  end
193
196
  end
194
197
 
@@ -6,78 +6,55 @@ describe Picky::Query::Combinations do
6
6
 
7
7
  before(:each) do
8
8
  @combinations_ary = stub :combinations_ary
9
-
9
+
10
10
  @combinations = described_class.new @combinations_ary
11
11
  end
12
-
12
+
13
13
  describe "to_result" do
14
14
  before(:each) do
15
15
  @combination1 = stub :combination1, :to_result => :result1
16
16
  @combination2 = stub :combination2, :to_result => :result2
17
-
17
+
18
18
  @combinations_ary = [@combination1, @combination2]
19
-
19
+
20
20
  @combinations = described_class.new @combinations_ary
21
21
  end
22
22
  it "resultifies the combinations" do
23
23
  @combinations.to_result.should == [:result1, :result2]
24
24
  end
25
25
  end
26
-
26
+
27
27
  describe "weighted_score" do
28
28
  it "uses the weights' score method" do
29
29
  weights = stub :weights
30
30
  weights.should_receive(:score_for).once.with @combinations_ary
31
-
31
+
32
32
  @combinations.weighted_score weights
33
33
  end
34
34
  end
35
-
35
+
36
36
  describe "total_score" do
37
37
  before(:each) do
38
38
  @combination1 = stub :combination1, :weight => 3.14
39
39
  @combination2 = stub :combination2, :weight => 2.76
40
-
40
+
41
41
  @combinations_ary = [@combination1, @combination2]
42
-
42
+
43
43
  @combinations = described_class.new @combinations_ary
44
44
  end
45
45
  it "sums the scores" do
46
- @combinations.total_score.should == 5.90
46
+ @combinations.score.should == 5.90
47
47
  end
48
48
  end
49
-
50
- describe "calculate_score" do
51
- before(:each) do
52
- @combinations.stub! :total_score => 0
53
- @combinations.stub! :weighted_score => 0
54
- end
55
- it "first sums, then weighs" do
56
- @combinations.should_receive(:total_score).once.ordered.and_return 0
57
- @combinations.should_receive(:weighted_score).once.ordered.and_return 0
58
-
59
- @combinations.calculate_score :anything
60
- end
61
- it "calls sum_score" do
62
- @combinations.should_receive(:total_score).once.with.and_return 0
63
-
64
- @combinations.calculate_score :anything
65
- end
66
- it "calls sum_score" do
67
- @combinations.should_receive(:weighted_score).once.with(:weights).and_return 0
68
-
69
- @combinations.calculate_score :weights
70
- end
71
- end
72
-
49
+
73
50
  describe 'hash' do
74
51
  it "delegates to the combinations array" do
75
52
  @combinations_ary.should_receive(:hash).once.with
76
-
53
+
77
54
  @combinations.hash
78
55
  end
79
56
  end
80
-
57
+
81
58
  describe 'remove' do
82
59
  before(:each) do
83
60
  @combination1 = stub :combination1, :category => :other