moneypools-thinking-sphinx 1.2.11

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 (91) hide show
  1. data/LICENCE +20 -0
  2. data/README.textile +157 -0
  3. data/VERSION.yml +4 -0
  4. data/lib/thinking_sphinx.rb +211 -0
  5. data/lib/thinking_sphinx/active_record.rb +307 -0
  6. data/lib/thinking_sphinx/active_record/attribute_updates.rb +48 -0
  7. data/lib/thinking_sphinx/active_record/delta.rb +87 -0
  8. data/lib/thinking_sphinx/active_record/has_many_association.rb +28 -0
  9. data/lib/thinking_sphinx/active_record/scopes.rb +39 -0
  10. data/lib/thinking_sphinx/adapters/abstract_adapter.rb +42 -0
  11. data/lib/thinking_sphinx/adapters/mysql_adapter.rb +54 -0
  12. data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +136 -0
  13. data/lib/thinking_sphinx/association.rb +164 -0
  14. data/lib/thinking_sphinx/attribute.rb +340 -0
  15. data/lib/thinking_sphinx/class_facet.rb +15 -0
  16. data/lib/thinking_sphinx/configuration.rb +282 -0
  17. data/lib/thinking_sphinx/core/array.rb +7 -0
  18. data/lib/thinking_sphinx/core/string.rb +15 -0
  19. data/lib/thinking_sphinx/deltas.rb +30 -0
  20. data/lib/thinking_sphinx/deltas/datetime_delta.rb +50 -0
  21. data/lib/thinking_sphinx/deltas/default_delta.rb +68 -0
  22. data/lib/thinking_sphinx/deltas/delayed_delta.rb +34 -0
  23. data/lib/thinking_sphinx/deltas/delayed_delta/delta_job.rb +24 -0
  24. data/lib/thinking_sphinx/deltas/delayed_delta/flag_as_deleted_job.rb +27 -0
  25. data/lib/thinking_sphinx/deltas/delayed_delta/job.rb +26 -0
  26. data/lib/thinking_sphinx/deploy/capistrano.rb +100 -0
  27. data/lib/thinking_sphinx/excerpter.rb +22 -0
  28. data/lib/thinking_sphinx/facet.rb +125 -0
  29. data/lib/thinking_sphinx/facet_search.rb +134 -0
  30. data/lib/thinking_sphinx/field.rb +82 -0
  31. data/lib/thinking_sphinx/index.rb +99 -0
  32. data/lib/thinking_sphinx/index/builder.rb +286 -0
  33. data/lib/thinking_sphinx/index/faux_column.rb +110 -0
  34. data/lib/thinking_sphinx/property.rb +162 -0
  35. data/lib/thinking_sphinx/rails_additions.rb +150 -0
  36. data/lib/thinking_sphinx/search.rb +689 -0
  37. data/lib/thinking_sphinx/search_methods.rb +421 -0
  38. data/lib/thinking_sphinx/source.rb +150 -0
  39. data/lib/thinking_sphinx/source/internal_properties.rb +46 -0
  40. data/lib/thinking_sphinx/source/sql.rb +128 -0
  41. data/lib/thinking_sphinx/tasks.rb +165 -0
  42. data/rails/init.rb +14 -0
  43. data/spec/lib/thinking_sphinx/active_record/delta_spec.rb +130 -0
  44. data/spec/lib/thinking_sphinx/active_record/has_many_association_spec.rb +49 -0
  45. data/spec/lib/thinking_sphinx/active_record/scopes_spec.rb +96 -0
  46. data/spec/lib/thinking_sphinx/active_record_spec.rb +364 -0
  47. data/spec/lib/thinking_sphinx/association_spec.rb +239 -0
  48. data/spec/lib/thinking_sphinx/attribute_spec.rb +500 -0
  49. data/spec/lib/thinking_sphinx/configuration_spec.rb +335 -0
  50. data/spec/lib/thinking_sphinx/core/array_spec.rb +9 -0
  51. data/spec/lib/thinking_sphinx/core/string_spec.rb +9 -0
  52. data/spec/lib/thinking_sphinx/excerpter_spec.rb +49 -0
  53. data/spec/lib/thinking_sphinx/facet_search_spec.rb +176 -0
  54. data/spec/lib/thinking_sphinx/facet_spec.rb +333 -0
  55. data/spec/lib/thinking_sphinx/field_spec.rb +154 -0
  56. data/spec/lib/thinking_sphinx/index/builder_spec.rb +455 -0
  57. data/spec/lib/thinking_sphinx/index/faux_column_spec.rb +30 -0
  58. data/spec/lib/thinking_sphinx/index_spec.rb +45 -0
  59. data/spec/lib/thinking_sphinx/rails_additions_spec.rb +203 -0
  60. data/spec/lib/thinking_sphinx/search_methods_spec.rb +152 -0
  61. data/spec/lib/thinking_sphinx/search_spec.rb +1066 -0
  62. data/spec/lib/thinking_sphinx/source_spec.rb +227 -0
  63. data/spec/lib/thinking_sphinx_spec.rb +162 -0
  64. data/tasks/distribution.rb +49 -0
  65. data/tasks/rails.rake +1 -0
  66. data/tasks/testing.rb +83 -0
  67. data/vendor/after_commit/LICENSE +20 -0
  68. data/vendor/after_commit/README +16 -0
  69. data/vendor/after_commit/Rakefile +22 -0
  70. data/vendor/after_commit/init.rb +8 -0
  71. data/vendor/after_commit/lib/after_commit.rb +45 -0
  72. data/vendor/after_commit/lib/after_commit/active_record.rb +114 -0
  73. data/vendor/after_commit/lib/after_commit/connection_adapters.rb +103 -0
  74. data/vendor/after_commit/test/after_commit_test.rb +53 -0
  75. data/vendor/riddle/lib/riddle.rb +30 -0
  76. data/vendor/riddle/lib/riddle/client.rb +622 -0
  77. data/vendor/riddle/lib/riddle/client/filter.rb +53 -0
  78. data/vendor/riddle/lib/riddle/client/message.rb +66 -0
  79. data/vendor/riddle/lib/riddle/client/response.rb +84 -0
  80. data/vendor/riddle/lib/riddle/configuration.rb +33 -0
  81. data/vendor/riddle/lib/riddle/configuration/distributed_index.rb +48 -0
  82. data/vendor/riddle/lib/riddle/configuration/index.rb +142 -0
  83. data/vendor/riddle/lib/riddle/configuration/indexer.rb +19 -0
  84. data/vendor/riddle/lib/riddle/configuration/remote_index.rb +17 -0
  85. data/vendor/riddle/lib/riddle/configuration/searchd.rb +25 -0
  86. data/vendor/riddle/lib/riddle/configuration/section.rb +43 -0
  87. data/vendor/riddle/lib/riddle/configuration/source.rb +23 -0
  88. data/vendor/riddle/lib/riddle/configuration/sql_source.rb +34 -0
  89. data/vendor/riddle/lib/riddle/configuration/xml_source.rb +28 -0
  90. data/vendor/riddle/lib/riddle/controller.rb +54 -0
  91. metadata +168 -0
@@ -0,0 +1,335 @@
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
+ end
10
+
11
+ it "should use the Merb environment value if set" do
12
+ unless defined?(Merb)
13
+ module ::Merb; end
14
+ end
15
+
16
+ ThinkingSphinx::Configuration.stub!(:defined? => true)
17
+ Merb.stub!(:environment => "merb_production")
18
+ ThinkingSphinx::Configuration.environment.should == "merb_production"
19
+
20
+ Object.send(:remove_const, :Merb)
21
+ end
22
+
23
+ it "should use the Rails environment value if set" do
24
+ ENV["RAILS_ENV"] = "rails_production"
25
+ ThinkingSphinx::Configuration.environment.should == "rails_production"
26
+ end
27
+
28
+ it "should default to development" do
29
+ ThinkingSphinx::Configuration.environment.should == "development"
30
+ end
31
+ end
32
+
33
+ describe "parse_config method" do
34
+ before do
35
+ @config = ThinkingSphinx::Configuration.instance
36
+ end
37
+
38
+ it "should use the accessors to set the configuration values" do
39
+ settings = {
40
+ "development" => {
41
+ "config_file" => "tmp/config/development.sphinx.conf",
42
+ "searchd_log_file" => "searchd_log_file.log",
43
+ "query_log_file" => "query_log_file.log",
44
+ "pid_file" => "pid_file.pid",
45
+ "searchd_file_path" => "searchd/file/path",
46
+ "address" => "127.0.0.1",
47
+ "port" => 3333,
48
+ "mem_limit" => "128M",
49
+ "max_matches" => 1001,
50
+ "searchd_binary_name" => "sphinx-searchd",
51
+ "indexer_binary_name" => "sphinx-indexer"
52
+ }
53
+ }
54
+
55
+ open("#{RAILS_ROOT}/config/sphinx.yml", "w") do |f|
56
+ f.write YAML.dump(settings)
57
+ end
58
+
59
+ @config.send(:parse_config)
60
+
61
+ %w(config_file searchd_log_file query_log_file pid_file searchd_file_path
62
+ address port searchd_binary_name indexer_binary_name).each do |key|
63
+ @config.send(key).should == settings["development"][key]
64
+ end
65
+ end
66
+
67
+ describe "source options" do
68
+ it "should set SourceOptions as valid source options" do
69
+ source_options = {
70
+ "development" => {
71
+ "mysql_connect_flags" => 32,
72
+ "sql_range_step" => 1000,
73
+ "sql_query_pre" => "SET NAMES utf8",
74
+ "sql_query_post" => "SET NAMES utf8",
75
+ "sql_ranged_throttle" => 1000,
76
+ "sql_query_post_index" => "REPLACE INTO counters ( id, val ) VALUES ( 'max_indexed_id', $maxid )"
77
+ }
78
+ }
79
+
80
+ open("#{RAILS_ROOT}/config/sphinx.yml", "w") do |f|
81
+ f.write YAML.dump(source_options)
82
+ end
83
+
84
+ @config.send(:parse_config)
85
+
86
+ ThinkingSphinx::Configuration::SourceOptions.each do |key|
87
+ lambda {
88
+ @config.source_options[key] = source_options[key]
89
+ @config.build
90
+ }.should_not raise_error
91
+ end
92
+ end
93
+ end
94
+
95
+
96
+ describe "index options" do
97
+ it "should set IndexOptions as valid index options" do
98
+ index_options = {
99
+ "development" => {
100
+ "charset_table" => "latin1",
101
+ "charset_type" => "table",
102
+ "docinfo" => "inline",
103
+ "enable_star" => true,
104
+ "exceptions" => "/data/www/sphinx/exceptions",
105
+ "html_index_attrs" => "a=href;",
106
+ "html_remove_elements" => "style",
107
+ "html_strip" => false,
108
+ "ignore_chars" => "e",
109
+ "min_infix_len" => 3,
110
+ "min_prefix_len" => 2,
111
+ "min_word_len" => 5,
112
+ "mlock" => 0,
113
+ "morphology" => "stem_ru",
114
+ "ngram_chars" => "U+3000..U+2FA1F",
115
+ "ngram_len" => 1,
116
+ "phrase_boundary" => "., ?, !, U+2026",
117
+ "phrase_boundary_step" => 100,
118
+ "preopen" => true,
119
+ "stopwords" => "/data/www/sphinx/stopwords",
120
+ "wordforms" => "/data/www/sphinx/wordforms"
121
+ }
122
+ }
123
+
124
+ open("#{RAILS_ROOT}/config/sphinx.yml", "w") do |f|
125
+ f.write YAML.dump(index_options)
126
+ end
127
+
128
+ @config.send(:parse_config)
129
+
130
+ ThinkingSphinx::Configuration::IndexOptions.each do |key|
131
+ lambda {
132
+ @config.index_options[key] = index_options[key]
133
+ @config.build
134
+ }.should_not raise_error
135
+ end
136
+ end
137
+ end
138
+
139
+ describe "custom index options" do
140
+ it "should set CustomOptions as valid index options" do
141
+ custom_options = {
142
+ "development" => {
143
+ "disable_range" => true
144
+ }
145
+ }
146
+
147
+ open("#{RAILS_ROOT}/config/sphinx.yml", "w") do |f|
148
+ f.write YAML.dump(custom_options)
149
+ end
150
+
151
+ @config.send(:parse_config)
152
+
153
+ ThinkingSphinx::Configuration::CustomOptions.each do |key|
154
+ lambda {
155
+ @config.index_options[key] = custom_options[key]
156
+ @config.build
157
+ }.should_not raise_error
158
+ end
159
+ end
160
+ end
161
+
162
+ after :each do
163
+ FileUtils.rm "#{RAILS_ROOT}/config/sphinx.yml"
164
+ end
165
+ end
166
+
167
+ describe "block configuration" do
168
+ it "should let the user set-up a custom app_root" do
169
+ ThinkingSphinx::Configuration.configure do |config|
170
+ config.app_root = "/here/somewhere"
171
+ end
172
+ ThinkingSphinx::Configuration.instance.app_root.should == "/here/somewhere"
173
+ end
174
+ end
175
+
176
+ describe "initialisation" do
177
+ it "should have a default bin_path of nothing" do
178
+ ThinkingSphinx::Configuration.instance.bin_path.should == ""
179
+ end
180
+
181
+ it "should append a / to bin_path if one is supplied" do
182
+ @settings = {
183
+ "development" => {
184
+ "bin_path" => "path/to/somewhere"
185
+ }
186
+ }
187
+
188
+ open("#{RAILS_ROOT}/config/sphinx.yml", "w") do |f|
189
+ f.write YAML.dump(@settings)
190
+ end
191
+
192
+ ThinkingSphinx::Configuration.instance.send(:parse_config)
193
+ ThinkingSphinx::Configuration.instance.bin_path.should match(/\/$/)
194
+
195
+ FileUtils.rm "#{RAILS_ROOT}/config/sphinx.yml"
196
+ end
197
+ end
198
+
199
+ describe "#load_models" do
200
+ before :each do
201
+ @config = ThinkingSphinx::Configuration.instance
202
+ @config.model_directories = ['']
203
+
204
+ @file_name = 'a.rb'
205
+ @model_name_lower = 'a'
206
+ @class_name = 'A'
207
+
208
+ @file_name.stub!(:gsub).and_return(@model_name_lower)
209
+ @model_name_lower.stub!(:camelize).and_return(@class_name)
210
+ Dir.stub(:[]).and_return([@file_name])
211
+ end
212
+
213
+ it "should load the files by guessing the file name" do
214
+ @class_name.should_receive(:constantize).and_return(true)
215
+
216
+ @config.load_models
217
+ end
218
+
219
+ it "should not raise errors if the model name is nil" do
220
+ @file_name.stub!(:gsub).and_return(nil)
221
+
222
+ lambda {
223
+ @config.load_models
224
+ }.should_not raise_error
225
+ end
226
+
227
+ it "should not raise errors if the file name does not represent a class name" do
228
+ @class_name.should_receive(:constantize).and_raise(NameError)
229
+
230
+ lambda {
231
+ @config.load_models
232
+ }.should_not raise_error
233
+ end
234
+
235
+ it "should retry if the first pass fails and contains a directory" do
236
+ @model_name_lower.stub!(:gsub!).and_return(true, nil)
237
+ @class_name.stub(:constantize).and_raise(LoadError)
238
+ @model_name_lower.should_receive(:camelize).twice
239
+
240
+ lambda {
241
+ @config.load_models
242
+ }.should_not raise_error
243
+ end
244
+
245
+ it "should catch database errors with a warning" do
246
+ @class_name.should_receive(:constantize).and_raise(Mysql::Error)
247
+ @config.should_receive(:puts).with('Warning: Error loading a.rb')
248
+
249
+ lambda {
250
+ @config.load_models
251
+ }.should_not raise_error
252
+ end
253
+ end
254
+
255
+ it "should insert set index options into the configuration file" do
256
+ config = ThinkingSphinx::Configuration.instance
257
+ ThinkingSphinx::Configuration::IndexOptions.each do |option|
258
+ config.index_options[option.to_sym] = "something"
259
+ config.build
260
+
261
+ file = open(config.config_file) { |f| f.read }
262
+ file.should match(/#{option}\s+= something/)
263
+
264
+ config.index_options[option.to_sym] = nil
265
+ end
266
+ end
267
+
268
+ it "should insert set source options into the configuration file" do
269
+ config = ThinkingSphinx::Configuration.instance
270
+ ThinkingSphinx::Configuration::SourceOptions.each do |option|
271
+ config.source_options[option.to_sym] = "something"
272
+ config.build
273
+
274
+ file = open(config.config_file) { |f| f.read }
275
+ file.should match(/#{option}\s+= something/)
276
+
277
+ config.source_options[option.to_sym] = nil
278
+ end
279
+ end
280
+
281
+ it "should set any explicit prefixed or infixed fields" do
282
+ file = open(ThinkingSphinx::Configuration.instance.config_file) { |f|
283
+ f.read
284
+ }
285
+ file.should match(/prefix_fields\s+= city/)
286
+ file.should match(/infix_fields\s+= state/)
287
+ end
288
+
289
+ it "should not have prefix fields in indexes where nothing is set" do
290
+ file = open(ThinkingSphinx::Configuration.instance.config_file) { |f|
291
+ f.read
292
+ }
293
+ file.should_not match(/index alpha_core\s+\{\s+[^\}]*prefix_fields\s+=[^\}]*\}/m)
294
+ end
295
+
296
+ describe '#client' do
297
+ before :each do
298
+ @config = ThinkingSphinx::Configuration.instance
299
+ @config.address = 'domain.url'
300
+ @config.port = 3333
301
+ @config.configuration.searchd.max_matches = 100
302
+ end
303
+
304
+ it "should return an instance of Riddle::Client" do
305
+ @config.client.should be_a(Riddle::Client)
306
+ end
307
+
308
+ it "should use the configuration address" do
309
+ @config.client.server.should == 'domain.url'
310
+ end
311
+
312
+ it "should use the configuration port" do
313
+ @config.client.port.should == 3333
314
+ end
315
+
316
+ it "should use the configuration max matches" do
317
+ @config.client.max_matches.should == 100
318
+ end
319
+ end
320
+
321
+ describe '#models_by_crc' do
322
+ before :each do
323
+ @config = ThinkingSphinx::Configuration.instance
324
+ end
325
+
326
+ it "should return a hash" do
327
+ @config.models_by_crc.should be_a(Hash)
328
+ end
329
+
330
+ it "should pair class names to their crc codes" do
331
+ @config.models_by_crc[Person.to_crc32].should == 'Person'
332
+ @config.models_by_crc[Alpha.to_crc32].should == 'Alpha'
333
+ end
334
+ end
335
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe Array do
4
+ describe '.===' do
5
+ it "should return true if an instance of ThinkingSphinx::Search" do
6
+ Array.should === ThinkingSphinx::Search.new
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe String do
4
+ describe "to_crc32 instance method" do
5
+ it "should return an integer" do
6
+ 'to_crc32'.to_crc32.should be_a_kind_of(Integer)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,49 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe ThinkingSphinx::Excerpter do
4
+ before :each do
5
+ @alpha = Alpha.find(:first)
6
+ @search = mock 'search', :excerpt_for => 'excerpted value'
7
+ @excerpter = ThinkingSphinx::Excerpter.new(@search, @alpha)
8
+ end
9
+
10
+ it "should not respond to id" do
11
+ @excerpter.should_not respond_to(:id)
12
+ end
13
+
14
+ describe '#method_missing' do
15
+ it "should return the excerpt from Sphinx" do
16
+ @excerpter.name.should == 'excerpted value'
17
+ end
18
+
19
+ it "should send through the instance class to excerpt_for" do
20
+ @search.should_receive(:excerpt_for) do |string, model|
21
+ model.should == Alpha
22
+ end
23
+
24
+ @excerpter.name
25
+ end
26
+
27
+ it "should use attribute methods for excerpts calls" do
28
+ @search.should_receive(:excerpt_for) do |string, model|
29
+ string.should == 'one'
30
+ end
31
+
32
+ @excerpter.name
33
+ end
34
+
35
+ it "should use instance methods for excerpts calls" do
36
+ @search.should_receive(:excerpt_for) do |string, model|
37
+ string.should == 'ONE'
38
+ end
39
+
40
+ @excerpter.big_name
41
+ end
42
+
43
+ it "should still raise an exception if no column or method exists" do
44
+ lambda {
45
+ @excerpter.foo
46
+ }.should raise_error(NoMethodError)
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,176 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe ThinkingSphinx::FacetSearch do
4
+ describe 'populate' do
5
+ it "should make separate Sphinx queries for each facet" do
6
+ ThinkingSphinx.should_receive(:search).with(
7
+ hash_including(:group_by => 'city_facet')
8
+ ).and_return([])
9
+ ThinkingSphinx.should_receive(:search).with(
10
+ hash_including(:group_by => 'state_facet')
11
+ ).and_return([])
12
+ ThinkingSphinx.should_receive(:search).with(
13
+ hash_including(:group_by => 'birthday')
14
+ ).and_return([])
15
+
16
+ ThinkingSphinx::FacetSearch.new(:classes => [Person])
17
+ end
18
+
19
+ it "should request all shared facets in a multi-model request by default" do
20
+ ThinkingSphinx.stub!(:search => [])
21
+ ThinkingSphinx::FacetSearch.new.facet_names.should == ['class_crc']
22
+ end
23
+
24
+ it "should request all facets in a multi-model request if specified" do
25
+ ThinkingSphinx.stub!(:search => [])
26
+ ThinkingSphinx::FacetSearch.new(
27
+ :all_facets => true
28
+ ).facet_names.should == [
29
+ 'class_crc', 'city_facet', 'state_facet', 'birthday'
30
+ ]
31
+ end
32
+
33
+ describe ':facets option' do
34
+ it "should limit facets to the requested set" do
35
+ ThinkingSphinx.should_receive(:search).once.and_return([])
36
+
37
+ ThinkingSphinx::FacetSearch.new(
38
+ :classes => [Person], :facets => :state
39
+ )
40
+ end
41
+ end
42
+
43
+ describe "empty result set for attributes" do
44
+ before :each do
45
+ ThinkingSphinx.stub!(:search => [])
46
+ @facets = ThinkingSphinx::FacetSearch.new(
47
+ :classes => [Person], :facets => :state
48
+ )
49
+ end
50
+
51
+ it "should add key as attribute" do
52
+ @facets.should have_key(:state)
53
+ end
54
+
55
+ it "should return an empty hash for the facet results" do
56
+ @facets[:state].should be_empty
57
+ end
58
+ end
59
+
60
+ describe "non-empty result set" do
61
+ before :each do
62
+ @person = Person.find(:first)
63
+ @people = [@person]
64
+ @people.stub!(:each_with_groupby_and_count).
65
+ and_yield(@person, @person.city.to_crc32, 1)
66
+ ThinkingSphinx.stub!(:search => @people)
67
+
68
+ @facets = ThinkingSphinx::FacetSearch.new(
69
+ :classes => [Person], :facets => :city
70
+ )
71
+ end
72
+
73
+ it "should return a hash" do
74
+ @facets.should be_a_kind_of(Hash)
75
+ end
76
+
77
+ it "should add key as attribute" do
78
+ @facets.keys.should include(:city)
79
+ end
80
+
81
+ it "should return a hash" do
82
+ @facets[:city].should == {@person.city => 1}
83
+ end
84
+ end
85
+
86
+ before :each do
87
+ @config = ThinkingSphinx::Configuration.instance
88
+ @config.configuration.searchd.max_matches = 10_000
89
+ end
90
+
91
+ it "should use the system-set max_matches for limit on facet calls" do
92
+ ThinkingSphinx.should_receive(:search) do |options|
93
+ options[:max_matches].should == 10_000
94
+ options[:limit].should == 10_000
95
+ []
96
+ end
97
+
98
+ ThinkingSphinx::FacetSearch.new
99
+ end
100
+
101
+ it "should use the default max-matches if there is no explicit setting" do
102
+ @config.configuration.searchd.max_matches = nil
103
+ ThinkingSphinx.should_receive(:search) do |options|
104
+ options[:max_matches].should == 1000
105
+ options[:limit].should == 1000
106
+ []
107
+ end
108
+
109
+ ThinkingSphinx::FacetSearch.new
110
+ end
111
+
112
+ it "should ignore user-provided max_matches and limit on facet calls" do
113
+ ThinkingSphinx.should_receive(:search) do |options|
114
+ options[:max_matches].should == 10_000
115
+ options[:limit].should == 10_000
116
+ []
117
+ end
118
+
119
+ ThinkingSphinx::FacetSearch.new(
120
+ :max_matches => 500,
121
+ :limit => 200
122
+ )
123
+ end
124
+
125
+ it "should not use an explicit :page" do
126
+ ThinkingSphinx.should_receive(:search) do |options|
127
+ options[:page].should == 1
128
+ []
129
+ end
130
+
131
+ ThinkingSphinx::FacetSearch.new(:page => 3)
132
+ end
133
+
134
+ describe "conflicting facets" do
135
+ before :each do
136
+ @index = ThinkingSphinx::Index::Builder.generate(Alpha) do
137
+ indexes :name
138
+ has :value, :as => :city, :facet => true
139
+ end
140
+ end
141
+
142
+ after :each do
143
+ Alpha.sphinx_facets.delete_at(-1)
144
+ end
145
+
146
+ it "should raise an error if searching with facets of same name but different type" do
147
+ lambda {
148
+ facets = ThinkingSphinx.facets :all_facets => true
149
+ }.should raise_error
150
+ end
151
+ end
152
+ end
153
+
154
+ describe "#for" do
155
+ before do
156
+ @person = Person.find(:first)
157
+ @people = [@person]
158
+ @people.stub!(:each_with_groupby_and_count).
159
+ and_yield(@person, @person.city.to_crc32, 1)
160
+ ThinkingSphinx.stub!(:search => @people)
161
+
162
+ @facets = ThinkingSphinx::FacetSearch.new(
163
+ :classes => [Person], :facets => :city
164
+ )
165
+ end
166
+
167
+ it "should return the search results for the attribute and key pair" do
168
+ ThinkingSphinx.should_receive(:search) do |options|
169
+ options[:with].should have_key('city_facet')
170
+ options[:with]['city_facet'].should == @person.city.to_crc32
171
+ end
172
+
173
+ @facets.for(:city => @person.city)
174
+ end
175
+ end
176
+ end