picky 0.0.0 → 0.0.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.
Files changed (161) hide show
  1. data/bin/picky +14 -0
  2. data/lib/bundling.rb +10 -0
  3. data/lib/constants.rb +9 -0
  4. data/lib/deployment.rb +212 -0
  5. data/lib/picky/application.rb +40 -0
  6. data/lib/picky/cacher/convenience.rb +3 -0
  7. data/lib/picky/cacher/generator.rb +17 -0
  8. data/lib/picky/cacher/partial/default.rb +7 -0
  9. data/lib/picky/cacher/partial/none.rb +19 -0
  10. data/lib/picky/cacher/partial/strategy.rb +7 -0
  11. data/lib/picky/cacher/partial/subtoken.rb +91 -0
  12. data/lib/picky/cacher/partial_generator.rb +15 -0
  13. data/lib/picky/cacher/similarity/default.rb +7 -0
  14. data/lib/picky/cacher/similarity/double_levenshtone.rb +73 -0
  15. data/lib/picky/cacher/similarity/none.rb +25 -0
  16. data/lib/picky/cacher/similarity/strategy.rb +7 -0
  17. data/lib/picky/cacher/similarity_generator.rb +15 -0
  18. data/lib/picky/cacher/weights/default.rb +7 -0
  19. data/lib/picky/cacher/weights/logarithmic.rb +39 -0
  20. data/lib/picky/cacher/weights/strategy.rb +7 -0
  21. data/lib/picky/cacher/weights_generator.rb +15 -0
  22. data/lib/picky/configuration/configuration.rb +13 -0
  23. data/lib/picky/configuration/field.rb +68 -0
  24. data/lib/picky/configuration/indexes.rb +60 -0
  25. data/lib/picky/configuration/queries.rb +32 -0
  26. data/lib/picky/configuration/type.rb +52 -0
  27. data/lib/picky/cores.rb +101 -0
  28. data/lib/picky/db/configuration.rb +23 -0
  29. data/lib/picky/ext/ruby19/extconf.rb +7 -0
  30. data/lib/picky/ext/ruby19/performant.c +339 -0
  31. data/lib/picky/extensions/array.rb +45 -0
  32. data/lib/picky/extensions/hash.rb +11 -0
  33. data/lib/picky/extensions/module.rb +15 -0
  34. data/lib/picky/extensions/symbol.rb +18 -0
  35. data/lib/picky/generator.rb +156 -0
  36. data/lib/picky/helpers/cache.rb +23 -0
  37. data/lib/picky/helpers/gc.rb +11 -0
  38. data/lib/picky/helpers/measuring.rb +45 -0
  39. data/lib/picky/helpers/search.rb +27 -0
  40. data/lib/picky/index/bundle.rb +328 -0
  41. data/lib/picky/index/category.rb +109 -0
  42. data/lib/picky/index/combined.rb +38 -0
  43. data/lib/picky/index/type.rb +30 -0
  44. data/lib/picky/indexers/base.rb +77 -0
  45. data/lib/picky/indexers/default.rb +3 -0
  46. data/lib/picky/indexers/field.rb +13 -0
  47. data/lib/picky/indexers/no_source_specified_error.rb +5 -0
  48. data/lib/picky/indexers/solr.rb +60 -0
  49. data/lib/picky/indexes.rb +180 -0
  50. data/lib/picky/initializers/ext.rb +6 -0
  51. data/lib/picky/initializers/mysql.rb +22 -0
  52. data/lib/picky/loader.rb +287 -0
  53. data/lib/picky/loggers/search.rb +19 -0
  54. data/lib/picky/performant/array.rb +23 -0
  55. data/lib/picky/query/allocation.rb +82 -0
  56. data/lib/picky/query/allocations.rb +131 -0
  57. data/lib/picky/query/base.rb +124 -0
  58. data/lib/picky/query/combination.rb +69 -0
  59. data/lib/picky/query/combinations.rb +106 -0
  60. data/lib/picky/query/combinator.rb +92 -0
  61. data/lib/picky/query/full.rb +15 -0
  62. data/lib/picky/query/live.rb +22 -0
  63. data/lib/picky/query/qualifiers.rb +73 -0
  64. data/lib/picky/query/solr.rb +77 -0
  65. data/lib/picky/query/token.rb +215 -0
  66. data/lib/picky/query/tokens.rb +102 -0
  67. data/lib/picky/query/weigher.rb +159 -0
  68. data/lib/picky/query/weights.rb +55 -0
  69. data/lib/picky/rack/harakiri.rb +37 -0
  70. data/lib/picky/results/base.rb +103 -0
  71. data/lib/picky/results/full.rb +19 -0
  72. data/lib/picky/results/live.rb +19 -0
  73. data/lib/picky/routing.rb +165 -0
  74. data/lib/picky/signals.rb +11 -0
  75. data/lib/picky/solr/schema_generator.rb +73 -0
  76. data/lib/picky/sources/base.rb +19 -0
  77. data/lib/picky/sources/csv.rb +30 -0
  78. data/lib/picky/sources/db.rb +77 -0
  79. data/lib/picky/tokenizers/base.rb +130 -0
  80. data/lib/picky/tokenizers/default.rb +3 -0
  81. data/lib/picky/tokenizers/index.rb +73 -0
  82. data/lib/picky/tokenizers/query.rb +70 -0
  83. data/lib/picky/umlaut_substituter.rb +21 -0
  84. data/lib/picky-tasks.rb +6 -0
  85. data/lib/picky.rb +18 -0
  86. data/lib/tasks/application.rake +5 -0
  87. data/lib/tasks/cache.rake +53 -0
  88. data/lib/tasks/framework.rake +4 -0
  89. data/lib/tasks/index.rake +29 -0
  90. data/lib/tasks/server.rake +48 -0
  91. data/lib/tasks/shortcuts.rake +13 -0
  92. data/lib/tasks/solr.rake +36 -0
  93. data/lib/tasks/spec.rake +11 -0
  94. data/lib/tasks/statistics.rake +13 -0
  95. data/lib/tasks/try.rake +29 -0
  96. data/prototype_project/Gemfile +23 -0
  97. data/prototype_project/Rakefile +1 -0
  98. data/prototype_project/app/README +6 -0
  99. data/prototype_project/app/application.rb +50 -0
  100. data/prototype_project/app/application.ru +29 -0
  101. data/prototype_project/app/db.yml +10 -0
  102. data/prototype_project/app/logging.rb +20 -0
  103. data/prototype_project/app/unicorn.ru +10 -0
  104. data/prototype_project/log/README +1 -0
  105. data/prototype_project/script/console +34 -0
  106. data/prototype_project/tmp/README +0 -0
  107. data/prototype_project/tmp/pids/README +0 -0
  108. data/spec/ext/performant_spec.rb +64 -0
  109. data/spec/lib/application_spec.rb +61 -0
  110. data/spec/lib/cacher/partial/subtoken_spec.rb +89 -0
  111. data/spec/lib/cacher/partial_generator_spec.rb +35 -0
  112. data/spec/lib/cacher/similarity/double_levenshtone_spec.rb +60 -0
  113. data/spec/lib/cacher/similarity/none_spec.rb +23 -0
  114. data/spec/lib/cacher/similarity_generator_spec.rb +22 -0
  115. data/spec/lib/cacher/weights/logarithmic_spec.rb +30 -0
  116. data/spec/lib/cacher/weights_generator_spec.rb +21 -0
  117. data/spec/lib/configuration/configuration_spec.rb +38 -0
  118. data/spec/lib/configuration/type_spec.rb +49 -0
  119. data/spec/lib/configuration_spec.rb +8 -0
  120. data/spec/lib/cores_spec.rb +65 -0
  121. data/spec/lib/extensions/array_spec.rb +37 -0
  122. data/spec/lib/extensions/hash_spec.rb +11 -0
  123. data/spec/lib/extensions/module_spec.rb +27 -0
  124. data/spec/lib/extensions/symbol_spec.rb +85 -0
  125. data/spec/lib/generator_spec.rb +135 -0
  126. data/spec/lib/helpers/cache_spec.rb +35 -0
  127. data/spec/lib/helpers/gc_spec.rb +71 -0
  128. data/spec/lib/helpers/measuring_spec.rb +18 -0
  129. data/spec/lib/helpers/search_spec.rb +50 -0
  130. data/spec/lib/index/bundle_partial_generation_speed_spec.rb +47 -0
  131. data/spec/lib/index/bundle_spec.rb +260 -0
  132. data/spec/lib/index/category_spec.rb +203 -0
  133. data/spec/lib/indexers/base_spec.rb +73 -0
  134. data/spec/lib/indexers/field_spec.rb +20 -0
  135. data/spec/lib/loader_spec.rb +48 -0
  136. data/spec/lib/loggers/search_spec.rb +19 -0
  137. data/spec/lib/performant/array_spec.rb +13 -0
  138. data/spec/lib/query/allocation_spec.rb +194 -0
  139. data/spec/lib/query/allocations_spec.rb +336 -0
  140. data/spec/lib/query/base_spec.rb +104 -0
  141. data/spec/lib/query/combination_spec.rb +90 -0
  142. data/spec/lib/query/combinations_spec.rb +83 -0
  143. data/spec/lib/query/combinator_spec.rb +112 -0
  144. data/spec/lib/query/full_spec.rb +22 -0
  145. data/spec/lib/query/live_spec.rb +61 -0
  146. data/spec/lib/query/qualifiers_spec.rb +31 -0
  147. data/spec/lib/query/solr_spec.rb +51 -0
  148. data/spec/lib/query/token_spec.rb +297 -0
  149. data/spec/lib/query/tokens_spec.rb +189 -0
  150. data/spec/lib/query/weights_spec.rb +47 -0
  151. data/spec/lib/results/base_spec.rb +233 -0
  152. data/spec/lib/routing_spec.rb +318 -0
  153. data/spec/lib/solr/schema_generator_spec.rb +42 -0
  154. data/spec/lib/sources/db_spec.rb +91 -0
  155. data/spec/lib/tokenizers/base_spec.rb +61 -0
  156. data/spec/lib/tokenizers/index_spec.rb +51 -0
  157. data/spec/lib/tokenizers/query_spec.rb +105 -0
  158. data/spec/lib/umlaut_substituter_spec.rb +84 -0
  159. data/spec/specific/speed_spec.rb +55 -0
  160. metadata +371 -15
  161. data/README.textile +0 -9
@@ -0,0 +1,233 @@
1
+ require 'spec_helper'
2
+
3
+ describe Results do
4
+
5
+ describe 'to_log' do
6
+ before(:each) do
7
+ time = stub :time, :to_s => '0-08-16 10:07:33'
8
+ Time.stub! :now => time
9
+ end
10
+ context 'without results' do
11
+ before(:each) do
12
+ @results = Results::Base.new
13
+ end
14
+ it 'should output a default log' do
15
+ @results.to_log('some_query').should == '|0-08-16 10:07:33|0.000000|some_query | 0| 0| 0|'
16
+ end
17
+ end
18
+ context 'with results' do
19
+ before(:each) do
20
+ @allocations = stub :allocations,
21
+ :process! => nil, :size => 12
22
+
23
+ @results = Results::Base.new @allocations
24
+ @results.stub! :duration => 0.1234567890,
25
+ :total => 12345678,
26
+ :offset => 1234
27
+ end
28
+ it 'should output a specific log' do
29
+ @results.to_log('some_query').should == '|0-08-16 10:07:33|0.123457|some_query |12345678|1234|12|'
30
+ end
31
+ end
32
+ end
33
+
34
+ describe 'to_marshal' do
35
+ before(:each) do
36
+ @results = Results::Base.new
37
+ end
38
+ it 'should do it correctly' do
39
+ @results.stub! :serialize => :serialized
40
+
41
+ @results.to_marshal.should == "\x04\b:\x0Fserialized"
42
+ end
43
+ end
44
+
45
+ describe 'to_json' do
46
+ before(:each) do
47
+ @results = Results::Base.new
48
+ end
49
+ it 'should do it correctly' do
50
+ @results.stub! :serialize => :serialized
51
+
52
+ @results.to_json.should == '"serialized"'
53
+ end
54
+ end
55
+
56
+ describe 'serialize' do
57
+ before(:each) do
58
+ @allocations = stub :allocations, :process! => nil, :to_result => :allocations, :total => :some_total
59
+
60
+ @results = Results::Base.new @allocations
61
+ @results.duration = :some_duration
62
+ end
63
+ it 'should do it correctly' do
64
+ @results.prepare! :some_offset
65
+
66
+ @results.serialize.should == { :allocations => :allocations, :offset => :some_offset, :duration => :some_duration, :total => :some_total }
67
+ end
68
+ end
69
+
70
+ describe 'prepare!' do
71
+ describe 'Full' do
72
+ before(:each) do
73
+ @results = Results::Full.new
74
+ @allocations = stub :allocations
75
+ @results.stub! :allocations => @allocations
76
+ end
77
+ it 'should first offset (TODO), then truncate' do
78
+ @allocations.should_receive(:process!).once.with(20, 0).ordered
79
+
80
+ @results.prepare!
81
+ end
82
+ end
83
+ describe 'Live' do
84
+ before(:each) do
85
+ @results = Results::Live.new
86
+ @allocations = stub :allocations
87
+ @results.stub! :allocations => @allocations
88
+ end
89
+ it 'should generate truncate the ids fully' do
90
+ @allocations.should_receive(:process!).once.with(0, 0).ordered
91
+
92
+ @results.prepare!
93
+ end
94
+ end
95
+ end
96
+
97
+ describe "class accessors" do
98
+ describe 'Full' do
99
+ it "should have accessors for max_results" do
100
+ max_results = stub :max_results
101
+ old_results = Results::Full.max_results
102
+ Results::Full.max_results = max_results
103
+
104
+ Results::Full.max_results.should == max_results
105
+
106
+ Results::Full.max_results = old_results
107
+ end
108
+ end
109
+ describe 'Live' do
110
+ it "should have accessors for max_results" do
111
+ max_results = stub :max_results
112
+ old_results = Results::Live.max_results
113
+ Results::Live.max_results = max_results
114
+
115
+ Results::Live.max_results.should == max_results
116
+
117
+ Results::Live.max_results = old_results
118
+ end
119
+ end
120
+ end
121
+
122
+ describe 'initialize' do
123
+ context 'without allocations' do
124
+ describe 'Full' do
125
+ it 'should not fail' do
126
+ lambda {
127
+ Results::Full.new
128
+ }.should_not raise_error
129
+ end
130
+ it 'should set the allocations to allocations that are empty' do
131
+ Results::Full.new.instance_variable_get(:@allocations).should be_empty
132
+ end
133
+ end
134
+ describe 'Live' do
135
+ it 'should not fail' do
136
+ lambda {
137
+ Results::Live.new
138
+ }.should_not raise_error
139
+ end
140
+ it 'should set the allocations to allocations that are empty' do
141
+ Results::Live.new.instance_variable_get(:@allocations).should be_empty
142
+ end
143
+ end
144
+ end
145
+ context 'with allocations' do
146
+ describe 'Full' do
147
+ it 'should not fail' do
148
+ lambda {
149
+ Results::Full.new :some_allocations
150
+ }.should_not raise_error
151
+ end
152
+ it 'should set the allocations to an empty array' do
153
+ Results::Full.new(:some_allocations).instance_variable_get(:@allocations).should == :some_allocations
154
+ end
155
+ end
156
+ describe 'Live' do
157
+ it 'should not fail' do
158
+ lambda {
159
+ Results::Live.new :some_allocations
160
+ }.should_not raise_error
161
+ end
162
+ it 'should set the allocations to an empty array' do
163
+ Results::Live.new(:some_allocations).instance_variable_get(:@allocations).should == :some_allocations
164
+ end
165
+ end
166
+ end
167
+ end
168
+
169
+ describe 'duration' do
170
+ describe 'Full' do
171
+ before(:each) do
172
+ @results = Results::Full.new
173
+ end
174
+ it 'should return the set duration' do
175
+ @results.duration = :some_duration
176
+
177
+ @results.duration.should == :some_duration
178
+ end
179
+ it 'should return 0 as a default' do
180
+ @results.duration.should == 0
181
+ end
182
+ end
183
+ describe 'Live' do
184
+ before(:each) do
185
+ @results = Results::Live.new
186
+ end
187
+ it 'should return the set duration' do
188
+ @results.duration = :some_duration
189
+
190
+ @results.duration.should == :some_duration
191
+ end
192
+ it 'should return 0 as a default' do
193
+ @results.duration.should == 0
194
+ end
195
+ end
196
+ end
197
+
198
+ describe 'total' do
199
+ describe 'Full' do
200
+ it 'should delegate to allocations.total' do
201
+ allocations = stub :allocations
202
+ results = Results::Full.new allocations
203
+
204
+ allocations.should_receive(:total).once
205
+
206
+ results.total
207
+ end
208
+ end
209
+ describe 'Live' do
210
+ it 'should delegate to allocations.total' do
211
+ allocations = stub :allocations
212
+ results = Results::Live.new allocations
213
+
214
+ allocations.should_receive(:total).once
215
+
216
+ results.total
217
+ end
218
+ end
219
+
220
+ end
221
+
222
+ describe "accessors" do
223
+ before(:each) do
224
+ @results = Results::Base.new :anything
225
+ @some_stub = stub(:some)
226
+ end
227
+ it "should have accessors for duration" do
228
+ @results.duration = @some_stub
229
+ @results.duration.should == @some_stub
230
+ end
231
+ end
232
+
233
+ end
@@ -0,0 +1,318 @@
1
+ # encoding: utf-8
2
+ #
3
+ require 'spec_helper'
4
+
5
+ describe Routing do
6
+
7
+ before(:each) do
8
+ @routing = Routing.new
9
+ end
10
+
11
+ def rack_defaults_for url
12
+ url, query_string = url.split ??
13
+
14
+ { "GATEWAY_INTERFACE"=>"CGI/1.1",
15
+ "PATH_INFO"=>"#{url}",
16
+ "QUERY_STRING"=>"#{query_string}",
17
+ "REMOTE_ADDR"=>"127.0.0.1",
18
+ "REMOTE_HOST"=>"localhost",
19
+ "REQUEST_METHOD"=>"GET",
20
+ "REQUEST_URI"=>"http://localhost:3001#{url}",
21
+ "SCRIPT_NAME"=>"",
22
+ "SERVER_NAME"=>"localhost",
23
+ "SERVER_PORT"=>"3001",
24
+ "SERVER_PROTOCOL"=>"HTTP/1.1",
25
+ "SERVER_SOFTWARE"=>"WEBrick/1.3.1 (Ruby/1.9.2/2010-07-11)",
26
+ "HTTP_HOST"=>"localhost:3001",
27
+ "HTTP_USER_AGENT"=>"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; en-us) AppleWebKit/533.16 (KHTML like Gecko) Version/5.0 Safari/533.16",
28
+ "HTTP_ACCEPT"=>"application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5",
29
+ "HTTP_CACHE_CONTROL"=>"max-age=0",
30
+ "HTTP_ACCEPT_LANGUAGE"=>"en-us",
31
+ "HTTP_ACCEPT_ENCODING"=>"gzip,
32
+ deflate",
33
+ "HTTP_COOKIE"=>"__utma=111872281.1536032598.1255697925.1255697925.1255697925.1; _jsuid=8971917605087477351; locale=de",
34
+ "HTTP_CONNECTION"=>"keep-alive",
35
+ "rack.input"=>'' }
36
+ end
37
+
38
+ context 'real routes' do
39
+ before(:each) do
40
+ @routing.reset_routes
41
+ PickyLog.stub! :log
42
+ end
43
+ it 'should route correctly' do
44
+ env = {}
45
+
46
+ @routing.routes.freeze
47
+ @routing.call(env).should == [404, {"Content-Type" => "text/html", "X-Cascade" => "pass"}, ["Not Found"]]
48
+ end
49
+ it 'should route correctly' do
50
+ env = rack_defaults_for '/'
51
+
52
+ @routing.root 200
53
+
54
+ @routing.routes.freeze
55
+ @routing.call(env).should == [200, {"Content-Type"=>"text/html", "Content-Length"=>"0"}, ['']]
56
+ end
57
+ it 'should route correctly' do
58
+ env = rack_defaults_for '/blarf'
59
+
60
+ @routing.default 200
61
+
62
+ @routing.routes.freeze
63
+ @routing.call(env).should == [200, {"Content-Type"=>"text/html", "Content-Length"=>"0"}, ['']]
64
+ end
65
+ it 'should route correctly' do
66
+ env = rack_defaults_for '/gurk'
67
+
68
+ @routing.answer %r{/gurk}, lambda { |env| [333, {}, ['this is gurk']] }
69
+
70
+ @routing.routes.freeze
71
+ @routing.call(env).should == [333, {}, ['this is gurk']]
72
+ end
73
+ it 'should route correctly' do
74
+ env = rack_defaults_for '/gurk'
75
+
76
+ @routing.answer '/gurk', lambda { |env| [333, {}, ['this is gurk']] }
77
+
78
+ @routing.routes.freeze
79
+ @routing.call(env).should == [333, {}, ['this is gurk']]
80
+ end
81
+ it 'should route correctly' do
82
+ env = rack_defaults_for '/searches/live.json?query=some_query'
83
+
84
+ live = stub :live
85
+ live.should_receive(:search_with_text).once.with(anything, 0).and_return(Results::Live.new)
86
+ Query::Live.stub! :new => live
87
+
88
+ @routing.live %r{/searches/live}, :some_index
89
+
90
+ @routing.routes.freeze
91
+ @routing.call(env).should == [200, {"Content-Type"=>"application/octet-stream", "Content-Length"=>"52"}, ["{\"allocations\":[],\"offset\":0,\"duration\":0,\"total\":0}"]]
92
+ end
93
+ it 'should route correctly' do
94
+ env = rack_defaults_for '/searches/live.json?query=some_query'
95
+
96
+ live = stub :live
97
+ live.should_receive(:search_with_text).once.with(anything, 0).and_return(Results::Live.new)
98
+ Query::Live.stub! :new => live
99
+
100
+ @routing.live '/searches/live', :some_index
101
+
102
+ @routing.routes.freeze
103
+ @routing.call(env).should == [200, {"Content-Type"=>"application/octet-stream", "Content-Length"=>"52"}, ["{\"allocations\":[],\"offset\":0,\"duration\":0,\"total\":0}"]]
104
+ end
105
+ it 'should route correctly' do
106
+ env = rack_defaults_for '/searches/full?query=some_query'
107
+
108
+ full = stub :full
109
+ full.should_receive(:search_with_text).once.with(anything, 0).and_return(Results::Full.new)
110
+ Query::Full.stub! :new => full
111
+
112
+ @routing.full %r{/searches/full}, :some_index
113
+
114
+ @routing.routes.freeze
115
+ @routing.call(env).should == [200, {"Content-Type"=>"application/octet-stream", "Content-Length"=>"50"}, ["\x04\b{\t:\x10allocations[\x00:\voffseti\x00:\rdurationi\x00:\ntotali\x00"]]
116
+ end
117
+ it 'should route correctly' do
118
+ env = rack_defaults_for '/searches/full?query=some_query'
119
+
120
+ full = stub :full
121
+ full.should_receive(:search_with_text).once.with(anything, 0).and_return(Results::Full.new)
122
+ Query::Full.stub! :new => full
123
+
124
+ @routing.full '/searches/full', :some_index
125
+
126
+ @routing.routes.freeze
127
+ @routing.call(env).should == [200, {"Content-Type"=>"application/octet-stream", "Content-Length"=>"50"}, ["\x04\b{\t:\x10allocations[\x00:\voffseti\x00:\rdurationi\x00:\ntotali\x00"]]
128
+ end
129
+ it 'should route correctly' do
130
+ env = rack_defaults_for '/searches/some_route?query=some_query'
131
+
132
+ full = stub :full
133
+ full.should_receive(:search_with_text).once.with(anything, 0).and_return(Results::Full.new)
134
+ Query::Full.stub! :new => full
135
+
136
+ @routing.route '/searches/some_route', Query::Full.new(:some_index, :some_other_index)
137
+
138
+ @routing.routes.freeze
139
+ @routing.call(env).should == [200, {"Content-Type"=>"application/octet-stream", "Content-Length"=>"50"}, ["\x04\b{\t:\x10allocations[\x00:\voffseti\x00:\rdurationi\x00:\ntotali\x00"]]
140
+ end
141
+ it 'should route correctly' do
142
+ env = rack_defaults_for '/searches/some_route?query=some_query&type=some_type'
143
+
144
+ full = stub :full
145
+ full.should_receive(:search_with_text).once.with(anything, 0).and_return(Results::Full.new)
146
+ Query::Full.stub! :new => full
147
+
148
+ @routing.route '/searches/some_route', Query::Full.new(:some_index, :some_other_index), :query => { :type => :some_type }
149
+
150
+ @routing.routes.freeze
151
+ @routing.call(env).should == [200, {"Content-Type"=>"application/octet-stream", "Content-Length"=>"50"}, ["\x04\b{\t:\x10allocations[\x00:\voffseti\x00:\rdurationi\x00:\ntotali\x00"]]
152
+ end
153
+ it 'should route correctly' do
154
+ env = rack_defaults_for '/searches/some_wrong_route?query=some_query'
155
+
156
+ full = stub :full
157
+ full.should_receive(:search_with_text).never
158
+ Query::Full.stub! :new => full
159
+
160
+ @routing.route '/searches/some_route', Query::Full.new(:some_index, :some_other_index)
161
+
162
+ @routing.routes.freeze
163
+ @routing.call(env).should == [404, {"Content-Type"=>"text/html", "X-Cascade"=>"pass"}, ["Not Found"]]
164
+ end
165
+ end
166
+
167
+ context 'stubbed routes' do
168
+ before(:each) do
169
+ @routes = stub :routes
170
+ @routing.stub! :routes => @routes
171
+ end
172
+ describe 'call' do
173
+ it 'should description' do
174
+
175
+ end
176
+ end
177
+
178
+ describe 'generate_query_string' do
179
+ it 'should not allow an empty query condition' do
180
+ lambda {
181
+ @routing.generate_query_string({}).should == 'this=must_be'
182
+ }.should raise_error "At least one query string condition is needed."
183
+ end
184
+ it 'should handle a single condition' do
185
+ @routing.generate_query_string(:this => :must_be).should == 'this=must_be'
186
+ end
187
+ it 'should not allow multiple query strings' do
188
+ lambda {
189
+ @routing.generate_query_string(:this => :must_be, :that => :should_be).should == 'this=must_be|that=should_be'
190
+ }.should raise_error "Too many query param conditions (only 1 allowed): {:this=>:must_be, :that=>:should_be}"
191
+ end
192
+ it 'should be sanity checked' do
193
+ '/searches/some_route?query=some_query&type=some_type'.should match(%r{#{"type=some_type"}})
194
+ end
195
+ end
196
+
197
+ describe 'route' do
198
+ before(:each) do
199
+ @some_query_app = stub :some_query_app
200
+ @routing.stub! :generate_app => @some_query_app
201
+ end
202
+ it 'should add the right route' do
203
+ @routes.should_receive(:add_route).once.with @some_query_app, { :request_method => "GET", :path_info => /some_url/ }
204
+
205
+ @routing.route %r{some_url}, :some_query, {}
206
+ end
207
+ it 'should add the right route' do
208
+ @routes.should_receive(:add_route).once.with @some_query_app, { :request_method => "GET", :path_info => /some_url/ }
209
+
210
+ @routing.route 'some_url', :some_query, {}
211
+ end
212
+ it 'should add the right route' do
213
+ @routes.should_receive(:add_route).once.with @some_query_app, { :request_method => "GET", :glarf => :blarf, :path_info => /some_url/ }
214
+
215
+ @routing.route 'some_url', :some_query, { :glarf => :blarf }
216
+ end
217
+ end
218
+
219
+ describe 'default' do
220
+ it 'should call answer' do
221
+ @routing.should_receive(:answer).once.with nil, Routing::STATUSES[200]
222
+
223
+ @routing.default 200
224
+ end
225
+ end
226
+
227
+ describe 'root' do
228
+ it 'should call answer' do
229
+ @routing.should_receive(:answer).once.with %r{^/$}, Routing::STATUSES[200]
230
+
231
+ @routing.root 200
232
+ end
233
+ end
234
+
235
+ #
236
+ describe 'live' do
237
+ describe 'instance creation' do
238
+ before(:each) do
239
+ @routing.stub :route
240
+ end
241
+ context 'with options' do
242
+ it 'should call route correctly' do
243
+ Query::Live.should_receive(:new).once.with :some_index, :some_other_index
244
+
245
+ @routing.live :url, :some_index, :some_other_index, { :query => { :param => :value } }
246
+ end
247
+ end
248
+ context 'without options' do
249
+ it 'should call route correctly' do
250
+ Query::Live.should_receive(:new).once.with :some_index, :some_other_index
251
+
252
+ @routing.live :url, :some_index, :some_other_index
253
+ end
254
+ end
255
+ end
256
+ describe 'delegation' do
257
+ context 'with options' do
258
+ it 'should call route correctly' do
259
+ Query::Live.stub! :new => :live
260
+
261
+ @routing.should_receive(:route).once.with :url, :live, { :query => { :param => :value } }
262
+
263
+ @routing.live :url, :some_index, { :query => { :param => :value } }
264
+ end
265
+ end
266
+ context 'without options' do
267
+ it 'should call route correctly' do
268
+ Query::Live.stub! :new => :live
269
+
270
+ @routing.should_receive(:route).once.with :url, :live, {}
271
+
272
+ @routing.live :url, :some_index
273
+ end
274
+ end
275
+ end
276
+ end
277
+
278
+ describe 'answer' do
279
+ context 'with app' do
280
+ before(:each) do
281
+ @app = stub :app
282
+ end
283
+ context 'with url' do
284
+ it 'should use the app with default_options from the url' do
285
+ @routes.should_receive(:add_route).once.with @app, { :request_method => "GET", :path_info => /some_url/ }
286
+
287
+ @routing.answer 'some_url', @app
288
+ end
289
+ end
290
+ context 'without url' do
291
+ it 'should use the app with default_options' do
292
+ @routes.should_receive(:add_route).once.with @app, { :request_method => "GET" }
293
+
294
+ @routing.answer nil, @app
295
+ end
296
+ end
297
+ end
298
+ context 'without app' do
299
+ context 'with url' do
300
+ it 'should use the 404 with default_options from the url' do
301
+ @routes.should_receive(:add_route).once.with Routing::STATUSES[200], { :request_method => "GET", :path_info => /some_url/ }
302
+
303
+ @routing.answer 'some_url'
304
+ end
305
+ end
306
+ context 'without url' do
307
+ it 'should use the 404 with default_options' do
308
+ @routes.should_receive(:add_route).once.with Routing::STATUSES[200], { :request_method => "GET" }
309
+
310
+ @routing.answer
311
+ end
312
+ end
313
+ end
314
+ end
315
+
316
+ end
317
+
318
+ end
@@ -0,0 +1,42 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe Solr::SchemaGenerator do
5
+
6
+ before(:each) do
7
+ @types = stub :types
8
+ @configuration = stub :configuration, :types => @types
9
+ @generator = Solr::SchemaGenerator.new @configuration
10
+ end
11
+
12
+ describe 'bound_field_names' do
13
+ before(:each) do
14
+ @generator.stub! :combine_field_names => :some_field_names
15
+ end
16
+ it 'should bind field_names' do
17
+ b = @generator.bound_field_names
18
+
19
+ eval('field_names', b).should == :some_field_names
20
+ end
21
+ end
22
+
23
+ describe 'generate' do
24
+ before(:each) do
25
+ @generator.stub! :bound_field_names
26
+ @generator.stub! :generate_schema_for
27
+ end
28
+ it 'should receive generate_schema_for once with the result of extract_binding' do
29
+ @generator.stub! :bound_field_names => :some_binding
30
+
31
+ @generator.should_receive(:generate_schema_for).once.with :some_binding
32
+
33
+ @generator.generate
34
+ end
35
+ it 'should extract the binding' do
36
+ @generator.should_receive(:bound_field_names).once.with
37
+
38
+ @generator.generate
39
+ end
40
+ end
41
+
42
+ end
@@ -0,0 +1,91 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sources::DB do
4
+
5
+ before(:each) do
6
+ @type = stub :type, :name => 'some_type_name'
7
+ @connection = stub :connection
8
+
9
+ @adapter = stub :adapter, :connection => @connection
10
+ @select_statement = stub :statement
11
+
12
+ @source = Sources::DB.new @select_statement, @adapter
13
+ end
14
+
15
+ describe "count" do
16
+ it "should get the count through the public DB connection" do
17
+ result = stub(:result, :to_i => 12_345)
18
+ @connection.should_receive(:select_value).once.and_return(result)
19
+
20
+ @source.count @type
21
+ end
22
+ it "should get the id count" do
23
+ result = stub(:result, :to_i => 12_345)
24
+ @connection.should_receive(:select_value).once.with("SELECT COUNT(id) FROM some_type_name_type_index")
25
+
26
+ @source.count @type
27
+ end
28
+ end
29
+
30
+ describe "harvest" do
31
+ before(:each) do
32
+ @adapter.stub! :connect
33
+ @source.stub! :harvest_statement_with_offset
34
+ end
35
+ context 'expectations' do
36
+ before(:each) do
37
+ @connection.stub! :execute
38
+ end
39
+ after(:each) do
40
+ @source.harvest :some_type, :some_field, :some_offset, :some_chunksize
41
+ end
42
+ context "with WHERE" do
43
+ before(:each) do
44
+ @source.stub! :select_statement => 'bla WHERE blu'
45
+ end
46
+ it "should connect" do
47
+ @adapter.should_receive(:connect).once.with
48
+ end
49
+ it "should call the harvest statement with an offset" do
50
+ @source.should_receive(:harvest_statement_with_offset).once.with :some_type, :some_field, :some_offset, :some_chunksize
51
+ end
52
+ end
53
+ context "without WHERE" do
54
+ it "should connect" do
55
+ @adapter.should_receive(:connect).once.with
56
+ end
57
+ it "should call the harvest statement with an offset" do
58
+ @source.should_receive(:harvest_statement_with_offset).once.with :some_type, :some_field, :some_offset, :some_chunksize
59
+ end
60
+ end
61
+ end
62
+ context 'returns' do
63
+ it "should return whatever the execute statement returns" do
64
+ @connection.stub! :execute => :some_result
65
+
66
+ @source.harvest(:some_type, :some_field, :some_offset, :some_chunksize).should == :some_result
67
+ end
68
+ end
69
+ end
70
+
71
+ describe "harvest_statement_with_offset" do
72
+ before(:each) do
73
+ @source.should_receive(:type_name).any_number_of_times.and_return :books
74
+ @field = stub :field, :name => :some_field
75
+ @type = stub :type, :name => :some_type
76
+ end
77
+ it "should get a harvest statement and the chunksize to put the statement together" do
78
+ @source.should_receive(:harvest_statement).once.and_return 'some_example_statement'
79
+ @source.harvest_statement_with_offset(@type, @field, :some_offset, :some_chunksize)
80
+ end
81
+ it "should add an AND if it already contains a WHERE statement" do
82
+ @source.should_receive(:harvest_statement).and_return 'WHERE'
83
+ @source.harvest_statement_with_offset(@type, @field, :some_offset, :some_chunksize).should == "WHERE AND st.id > some_offset LIMIT some_chunksize"
84
+ end
85
+ it "should add a WHERE if it doesn't already contain one" do
86
+ @source.should_receive(:harvest_statement).and_return 'some_statement'
87
+ @source.harvest_statement_with_offset(@type, @field, :some_offset, :some_chunksize).should == "some_statement WHERE st.id > some_offset LIMIT some_chunksize"
88
+ end
89
+ end
90
+
91
+ end