nixme-thinking-sphinx 0.9.7

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 (38) hide show
  1. data/LICENCE +20 -0
  2. data/README +52 -0
  3. data/lib/riddle.rb +22 -0
  4. data/lib/riddle/client.rb +593 -0
  5. data/lib/riddle/client/filter.rb +44 -0
  6. data/lib/riddle/client/message.rb +65 -0
  7. data/lib/riddle/client/response.rb +84 -0
  8. data/lib/test.rb +46 -0
  9. data/lib/thinking_sphinx.rb +82 -0
  10. data/lib/thinking_sphinx/active_record.rb +138 -0
  11. data/lib/thinking_sphinx/active_record/delta.rb +90 -0
  12. data/lib/thinking_sphinx/active_record/has_many_association.rb +29 -0
  13. data/lib/thinking_sphinx/active_record/search.rb +43 -0
  14. data/lib/thinking_sphinx/association.rb +140 -0
  15. data/lib/thinking_sphinx/attribute.rb +282 -0
  16. data/lib/thinking_sphinx/configuration.rb +277 -0
  17. data/lib/thinking_sphinx/field.rb +198 -0
  18. data/lib/thinking_sphinx/index.rb +334 -0
  19. data/lib/thinking_sphinx/index/builder.rb +212 -0
  20. data/lib/thinking_sphinx/index/faux_column.rb +97 -0
  21. data/lib/thinking_sphinx/rails_additions.rb +56 -0
  22. data/lib/thinking_sphinx/search.rb +455 -0
  23. data/spec/unit/thinking_sphinx/active_record/delta_spec.rb +185 -0
  24. data/spec/unit/thinking_sphinx/active_record/has_many_association_spec.rb +53 -0
  25. data/spec/unit/thinking_sphinx/active_record/search_spec.rb +81 -0
  26. data/spec/unit/thinking_sphinx/active_record_spec.rb +201 -0
  27. data/spec/unit/thinking_sphinx/association_spec.rb +247 -0
  28. data/spec/unit/thinking_sphinx/attribute_spec.rb +356 -0
  29. data/spec/unit/thinking_sphinx/configuration_spec.rb +476 -0
  30. data/spec/unit/thinking_sphinx/field_spec.rb +215 -0
  31. data/spec/unit/thinking_sphinx/index/builder_spec.rb +33 -0
  32. data/spec/unit/thinking_sphinx/index/faux_column_spec.rb +41 -0
  33. data/spec/unit/thinking_sphinx/index_spec.rb +230 -0
  34. data/spec/unit/thinking_sphinx/search_spec.rb +163 -0
  35. data/spec/unit/thinking_sphinx_spec.rb +107 -0
  36. data/tasks/thinking_sphinx_tasks.rake +1 -0
  37. data/tasks/thinking_sphinx_tasks.rb +86 -0
  38. metadata +90 -0
@@ -0,0 +1,476 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe ThinkingSphinx::Configuration do
4
+ describe "environment class method" do
5
+ before :each do
6
+ ThinkingSphinx::Configuration.send(:class_variable_set, :@@environment, nil)
7
+
8
+ ENV["RAILS_ENV"] = nil
9
+ ENV["MERB_ENV"] = nil
10
+ end
11
+
12
+ it "should use the Merb environment value if set" do
13
+ unless defined?(Merb)
14
+ module Merb; end
15
+ end
16
+
17
+ ThinkingSphinx::Configuration.stub_method(:defined? => true)
18
+ ENV["MERB_ENV"] = "merb_production"
19
+ ThinkingSphinx::Configuration.environment.should == "merb_production"
20
+
21
+ Object.send(:remove_const, :Merb)
22
+ end
23
+
24
+ it "should use the Rails environment value if set" do
25
+ ENV["RAILS_ENV"] = "rails_production"
26
+ ThinkingSphinx::Configuration.environment.should == "rails_production"
27
+ end
28
+
29
+ it "should default to development" do
30
+ ThinkingSphinx::Configuration.environment.should == "development"
31
+ end
32
+ end
33
+
34
+ describe "environment instance method" do
35
+ it "should return the class method" do
36
+ ThinkingSphinx::Configuration.stub_method(:environment => "spec")
37
+ ThinkingSphinx::Configuration.new.environment.should == "spec"
38
+ ThinkingSphinx::Configuration.should have_received(:environment)
39
+ end
40
+ end
41
+
42
+ describe "build method" do
43
+ before :each do
44
+ @config = ThinkingSphinx::Configuration.new
45
+
46
+ @config.stub_methods(
47
+ :load_models => "",
48
+ :core_index_for_model => "",
49
+ :delta_index_for_model => "",
50
+ :distributed_index_for_model => "",
51
+ :create_array_accum => true
52
+ )
53
+
54
+ ThinkingSphinx.stub_method :indexed_models => ["Person", "Friendship"]
55
+ YAML.stub_method(:load => {
56
+ :development => {
57
+ "option" => "value"
58
+ }
59
+ })
60
+
61
+ @person_index_a = ThinkingSphinx::Index.stub_instance(
62
+ :to_config => "", :adapter => :mysql, :delta? => false, :name => "person"
63
+ )
64
+ @person_index_b = ThinkingSphinx::Index.stub_instance(
65
+ :to_config => "", :adapter => :mysql, :delta? => false, :name => "person"
66
+ )
67
+ @friendship_index_a = ThinkingSphinx::Index.stub_instance(
68
+ :to_config => "", :adapter => :mysql, :delta? => false, :name => "friendship"
69
+ )
70
+
71
+ Person.stub_method(:indexes => [@person_index_a, @person_index_b])
72
+ Friendship.stub_method(:indexes => [@friendship_index_a])
73
+
74
+ FileUtils.mkdir_p "#{@config.app_root}/config"
75
+ FileUtils.touch "#{@config.app_root}/config/database.yml"
76
+ end
77
+
78
+ after :each do
79
+ ThinkingSphinx.unstub_method :indexed_models
80
+ YAML.unstub_method :load
81
+
82
+ Person.unstub_method :indexes
83
+ Friendship.unstub_method :indexes
84
+
85
+ FileUtils.rm_rf "#{@config.app_root}/config"
86
+ end
87
+
88
+ it "should load the models" do
89
+ @config.build
90
+
91
+ @config.should have_received(:load_models)
92
+ end
93
+
94
+ it "should load in the database YAML configuration" do
95
+ @config.build
96
+
97
+ YAML.should have_received(:load)
98
+ end
99
+
100
+ it "should set the mem limit based on the configuration" do
101
+ @config.build
102
+
103
+ file = open(@config.config_file) { |f| f.read }
104
+ file.should match(/mem_limit\s+= #{@config.mem_limit}/)
105
+ end
106
+
107
+ it "should use the configuration port" do
108
+ @config.build
109
+
110
+ file = open(@config.config_file) { |f| f.read }
111
+ file.should match(/port\s+= #{@config.port}/)
112
+ end
113
+
114
+ it "should use the configuration's log file locations" do
115
+ @config.build
116
+
117
+ file = open(@config.config_file) { |f| f.read }
118
+ file.should match(/log\s+= #{@config.searchd_log_file}/)
119
+ file.should match(/query_log\s+= #{@config.query_log_file}/)
120
+ end
121
+
122
+ it "should use the configuration's pid file location" do
123
+ @config.build
124
+
125
+ file = open(@config.config_file) { |f| f.read }
126
+ file.should match(/pid_file\s+= #{@config.pid_file}/)
127
+ end
128
+
129
+ it "should set max matches from configuration" do
130
+ @config.build
131
+
132
+ file = open(@config.config_file) { |f| f.read }
133
+ file.should match(/max_matches\s+= #{@config.max_matches}/)
134
+ end
135
+
136
+ it "should request configuration for each index for each model" do
137
+ @config.build
138
+
139
+ @person_index_a.should have_received(:to_config).with(
140
+ 0, {:option => "value"}, @config.charset_type
141
+ )
142
+ @person_index_b.should have_received(:to_config).with(
143
+ 1, {:option => "value"}, @config.charset_type
144
+ )
145
+ @friendship_index_a.should have_received(:to_config).with(
146
+ 0, {:option => "value"}, @config.charset_type
147
+ )
148
+ end
149
+
150
+ it "should call create_array_accum if any index uses postgres" do
151
+ @person_index_a.stub_method(:adapter => :postgres)
152
+
153
+ @config.build
154
+
155
+ @config.should have_received(:create_array_accum)
156
+ end
157
+
158
+ it "should not call create_array_accum if no index uses postgres" do
159
+ @config.build
160
+
161
+ @config.should_not have_received(:create_array_accum)
162
+ end
163
+
164
+ it "should call core_index_for_model for each model" do
165
+ @config.build
166
+
167
+ @config.should have_received(:core_index_for_model).with(
168
+ Person, "source = person_0_core\nsource = person_1_core"
169
+ )
170
+ @config.should have_received(:core_index_for_model).with(
171
+ Friendship, "source = friendship_0_core"
172
+ )
173
+ end
174
+
175
+ it "should call delta_index_for_model for each model if any index has a delta" do
176
+ @person_index_b.stub_method(:delta? => true)
177
+
178
+ @config.build
179
+
180
+ @config.should have_received(:delta_index_for_model).with(
181
+ Person, "source = person_1_delta"
182
+ )
183
+ end
184
+
185
+ it "should not call delta_index_for_model for each model if no indexes have deltas" do
186
+ @config.build
187
+
188
+ @config.should_not have_received(:delta_index_for_model)
189
+ end
190
+
191
+ it "should call distributed_index_for_model for each model" do
192
+ @config.build
193
+
194
+ @config.should have_received(:distributed_index_for_model).with(Person)
195
+ @config.should have_received(:distributed_index_for_model).with(Friendship)
196
+ end
197
+ end
198
+
199
+ describe "load_models method" do
200
+ it "should have some specs"
201
+ end
202
+
203
+ describe "parse_config method" do
204
+ before :each do
205
+ @settings = {
206
+ "development" => {
207
+ "config_file" => "my_conf_file.conf",
208
+ "searchd_log_file" => "searchd_log_file.log",
209
+ "query_log_file" => "query_log_file.log",
210
+ "pid_file" => "pid_file.pid",
211
+ "searchd_file_path" => "searchd/file/path",
212
+ "address" => "127.0.0.1",
213
+ "port" => 3333,
214
+ "allow_star" => true,
215
+ "min_prefix_len" => 2,
216
+ "min_infix_len" => 3,
217
+ "mem_limit" => "128M",
218
+ "max_matches" => 1001,
219
+ "morphology" => "stem_ru",
220
+ "charset_type" => "latin1",
221
+ "charset_table" => "table",
222
+ "ignore_chars" => "e"
223
+ }
224
+ }
225
+ # puts YAML.dump(settings)
226
+ open("#{RAILS_ROOT}/config/sphinx.yml", "w") do |f|
227
+ f.write YAML.dump(@settings)
228
+ end
229
+ end
230
+
231
+ it "should use the accessors to set the configuration values" do
232
+ config = ThinkingSphinx::Configuration.new
233
+ @settings["development"].each do |key, value|
234
+ config.send(key).should == value
235
+ end
236
+ end
237
+ end
238
+
239
+ describe "core_index_for_model method" do
240
+ before :each do
241
+ @config = ThinkingSphinx::Configuration.new
242
+ @model = Class.stub_instance(
243
+ :indexes => [ThinkingSphinx::Index.new(Person)]
244
+ )
245
+ end
246
+
247
+ it "should take its name from the model, with _core appended" do
248
+ @config.send(:core_index_for_model, @model, "my sources").should match(
249
+ /index person_core/
250
+ )
251
+ end
252
+
253
+ it "should set the path to follow the name" do
254
+ @config.searchd_file_path = "/my/file/path"
255
+ @config.send(:core_index_for_model, @model, "my sources").should match(
256
+ /path = \/my\/file\/path\/person_core/
257
+ )
258
+ end
259
+
260
+ it "should include the charset type setting" do
261
+ @config.charset_type = "specchars"
262
+ @config.send(:core_index_for_model, @model, "my sources").should match(
263
+ /charset_type = specchars/
264
+ )
265
+ end
266
+
267
+ it "should include the morphology setting if it isn't blank" do
268
+ @config.morphology = "morph"
269
+ @config.send(:core_index_for_model, @model, "my sources").should match(
270
+ /morphology\s+= morph/
271
+ )
272
+ end
273
+
274
+ it "should not include the morphology setting if it is blank" do
275
+ @config.morphology = nil
276
+ @config.send(:core_index_for_model, @model, "my sources").should_not match(
277
+ /morphology\s+=/
278
+ )
279
+
280
+ @config.morphology = ""
281
+ @config.send(:core_index_for_model, @model, "my sources").should_not match(
282
+ /morphology\s+=/
283
+ )
284
+ end
285
+
286
+ it "should include the charset_table value if it isn't nil" do
287
+ @config.charset_table = "table_chars"
288
+ @config.send(:core_index_for_model, @model, "my sources").should match(
289
+ /charset_table\s+= table_chars/
290
+ )
291
+ end
292
+
293
+ it "should not set the charset_table value if it is nil" do
294
+ @config.charset_table = nil
295
+ @config.send(:core_index_for_model, @model, "my sources").should_not match(
296
+ /charset_table\s+=/
297
+ )
298
+ end
299
+
300
+ it "should set the ignore_chars value if it isn't nil" do
301
+ @config.ignore_chars = "ignorable"
302
+ @config.send(:core_index_for_model, @model, "my sources").should match(
303
+ /ignore_chars\s+= ignorable/
304
+ )
305
+ end
306
+
307
+ it "should not set the ignore_chars value if it is nil" do
308
+ @config.ignore_chars = nil
309
+ @config.send(:core_index_for_model, @model, "my sources").should_not match(
310
+ /ignore_chars\s+=/
311
+ )
312
+ end
313
+
314
+ it "should include the star-related settings when allow_star is true" do
315
+ @config.allow_star = true
316
+ text = @config.send(:core_index_for_model, @model, "my sources")
317
+
318
+ text.should match(/enable_star\s+= 1/)
319
+ text.should match(/min_prefix_len\s+= 1/)
320
+ text.should match(/min_infix_len\s+= 1/)
321
+ end
322
+
323
+ it "should use the configuration's infix and prefix length values if set" do
324
+ @config.allow_star = true
325
+ @config.min_prefix_len = 3
326
+ @config.min_infix_len = 2
327
+ text = @config.send(:core_index_for_model, @model, "my sources")
328
+
329
+ text.should match(/min_prefix_len\s+= 3/)
330
+ text.should match(/min_infix_len\s+= 2/)
331
+ end
332
+
333
+ it "should not include the star-related settings when allow_star is false" do
334
+ @config.allow_star = false
335
+ text = @config.send(:core_index_for_model, @model, "my sources")
336
+
337
+ text.should_not match(/enable_star\s+=/)
338
+ text.should_not match(/min_prefix_len\s+=/)
339
+ text.should_not match(/min_infix_len\s+=/)
340
+ end
341
+
342
+ it "should set prefix_fields if any fields are flagged explicitly" do
343
+ @model.indexes.first.stub_methods(
344
+ :prefix_fields => ["a", "b", "c"],
345
+ :infix_fields => ["d", "e", "f"]
346
+ )
347
+
348
+ @config.send(:core_index_for_model, @model, "my sources").should match(
349
+ /prefix_fields\s+= a, b, c/
350
+ )
351
+ end
352
+
353
+ it "shouldn't set prefix_fields if none are flagged explicitly" do
354
+ @config.send(:core_index_for_model, @model, "my sources").should_not match(
355
+ /prefix_fields\s+=/
356
+ )
357
+ end
358
+
359
+ it "should set infix_fields if any fields are flagged explicitly" do
360
+ @model.indexes.first.stub_methods(
361
+ :prefix_fields => ["a", "b", "c"],
362
+ :infix_fields => ["d", "e", "f"]
363
+ )
364
+
365
+ @config.send(:core_index_for_model, @model, "my sources").should match(
366
+ /infix_fields\s+= d, e, f/
367
+ )
368
+ end
369
+
370
+ it "shouldn't set infix_fields if none are flagged explicitly" do
371
+ @config.send(:core_index_for_model, @model, "my sources").should_not match(
372
+ /infix_fields\s+=/
373
+ )
374
+ end
375
+
376
+ it "should include html_strip if value is set" do
377
+ @config.html_strip = 1
378
+ text = @config.send(:core_index_for_model, @model, "my sources")
379
+ text.should match(/html_strip\s+= 1/)
380
+ end
381
+
382
+ it "shouldn't include html_strip if value is not set" do
383
+ text = @config.send(:core_index_for_model, @model, "my sources")
384
+ text.should_not match(/html_strip/)
385
+ end
386
+
387
+ it "should include html_remove_elements if values are set" do
388
+ @config.html_remove_elements = 'script'
389
+ text = @config.send(:core_index_for_model, @model, "my sources")
390
+ text.should match(/html_remove_elements\s+= script/)
391
+ end
392
+
393
+ it "shouldn't include html_remove_elements if no values are set" do
394
+ text = @config.send(:core_index_for_model, @model, "my sources")
395
+ text.should_not match(/html_remove_elements/)
396
+ end
397
+ end
398
+
399
+ describe "delta_index_for_model method" do
400
+ before :each do
401
+ @config = ThinkingSphinx::Configuration.new
402
+ @model = Class.stub_instance(
403
+ :indexes => [ThinkingSphinx::Index.new(Person)]
404
+ )
405
+ end
406
+
407
+ it "should take its name from the model, with _delta appended" do
408
+ @config.send(:delta_index_for_model, @model, "delta_sources").should match(
409
+ /index person_delta/
410
+ )
411
+ end
412
+
413
+ it "should inherit from the equivalent core index" do
414
+ @config.send(:delta_index_for_model, @model, "delta_sources").should match(
415
+ /index person_delta : person_core/
416
+ )
417
+ end
418
+
419
+ it "should set the path to follow the name" do
420
+ @config.searchd_file_path = "/my/file/path"
421
+ @config.send(:delta_index_for_model, @model, "delta_sources").should match(
422
+ /path = \/my\/file\/path\/person_delta/
423
+ )
424
+ end
425
+ end
426
+
427
+ describe "distributed_index_for_model method" do
428
+ before :each do
429
+ @config = ThinkingSphinx::Configuration.new
430
+ @model = Class.stub_instance(
431
+ :indexes => [ThinkingSphinx::Index.new(Person)]
432
+ )
433
+ end
434
+
435
+ it "should take its name from the model" do
436
+ @config.send(:distributed_index_for_model, @model).should match(
437
+ /index person/
438
+ )
439
+ end
440
+
441
+ it "should have a type of distributed" do
442
+ @config.send(:distributed_index_for_model, @model).should match(
443
+ /type = distributed/
444
+ )
445
+ end
446
+
447
+ it "should include the core as a local source" do
448
+ @config.send(:distributed_index_for_model, @model).should match(
449
+ /local = person_core/
450
+ )
451
+ end
452
+
453
+ it "should only include the delta as a local source if an index is flagged to be delta" do
454
+ @config.send(:distributed_index_for_model, @model).should_not match(
455
+ /local = person_delta/
456
+ )
457
+
458
+ @model.indexes.first.stub_method(:delta? => true)
459
+ @config.send(:distributed_index_for_model, @model).should match(
460
+ /local = person_delta/
461
+ )
462
+ end
463
+
464
+ it "should handle namespaced models correctly" do
465
+ Person.stub_method(:name => "Namespaced::Model")
466
+
467
+ @config.send(:distributed_index_for_model, @model).should match(
468
+ /index namespaced_model/
469
+ )
470
+ end
471
+ end
472
+
473
+ describe "create_array_accum method" do
474
+ it "should create the array_accum method on PostgreSQL"
475
+ end
476
+ end