picky 4.0.0pre1 → 4.0.0pre2

Sign up to get free protection for your applications and to get access to all the features.
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