freelancing-god-thinking-sphinx 0.9.6 → 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.
- data/README +23 -1
- data/lib/thinking_sphinx.rb +4 -1
- data/lib/thinking_sphinx/active_record.rb +19 -0
- data/lib/thinking_sphinx/active_record/delta.rb +4 -0
- data/lib/thinking_sphinx/association.rb +5 -5
- data/lib/thinking_sphinx/attribute.rb +5 -2
- data/lib/thinking_sphinx/configuration.rb +86 -104
- data/lib/thinking_sphinx/field.rb +17 -5
- data/lib/thinking_sphinx/index.rb +71 -2
- data/lib/thinking_sphinx/index/builder.rb +5 -5
- data/lib/thinking_sphinx/search.rb +7 -1
- data/spec/unit/thinking_sphinx/active_record/delta_spec.rb +4 -0
- data/spec/unit/thinking_sphinx/active_record/search_spec.rb +63 -0
- data/spec/unit/thinking_sphinx/active_record_spec.rb +74 -2
- data/spec/unit/thinking_sphinx/association_spec.rb +247 -0
- data/spec/unit/thinking_sphinx/attribute_spec.rb +285 -2
- data/spec/unit/thinking_sphinx/configuration_spec.rb +431 -0
- data/spec/unit/thinking_sphinx/field_spec.rb +169 -5
- data/spec/unit/thinking_sphinx/index_spec.rb +186 -1
- data/spec/unit/thinking_sphinx_spec.rb +25 -0
- metadata +2 -2
@@ -1,7 +1,21 @@
|
|
1
1
|
require 'spec/spec_helper'
|
2
2
|
|
3
3
|
describe ThinkingSphinx::Attribute do
|
4
|
-
describe
|
4
|
+
describe '#initialize' do
|
5
|
+
it 'raises if no columns are provided so that configuration errors are easier to track down' do
|
6
|
+
lambda {
|
7
|
+
ThinkingSphinx::Attribute.new([])
|
8
|
+
}.should raise_error(RuntimeError)
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'raises if an element of the columns param is an integer - as happens when you use id instead of :id - so that configuration errors are easier to track down' do
|
12
|
+
lambda {
|
13
|
+
ThinkingSphinx::Attribute.new([1234])
|
14
|
+
}.should raise_error(RuntimeError)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "to_select_sql method with MySQL" do
|
5
19
|
before :each do
|
6
20
|
@index = Person.indexes.first
|
7
21
|
@index.link!
|
@@ -36,9 +50,43 @@ describe ThinkingSphinx::Attribute do
|
|
36
50
|
end
|
37
51
|
end
|
38
52
|
|
53
|
+
describe "to_select_sql method with PostgreSQL" do
|
54
|
+
before :each do
|
55
|
+
@index = Person.indexes.first
|
56
|
+
Person.connection.class.stub_method(
|
57
|
+
:name => "ActiveRecord::ConnectionAdapters::PostgreSQLAdapter"
|
58
|
+
)
|
59
|
+
@index.link!
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should concat with spaces if there's more than one non-integer column" do
|
63
|
+
@index.attributes[0].to_select_sql.should match(/|| ' ' ||/)
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should concat with spaces if there's more than one association for a non-integer column" do
|
67
|
+
@index.attributes[1].to_select_sql.should match(/|| ' ' ||/)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should concat with commas if there's multiple integer columns" do
|
71
|
+
@index.attributes[2].to_select_sql.should match(/|| ',' ||/)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should concat with commas if there's more than one association for an integer column" do
|
75
|
+
@index.attributes[3].to_select_sql.should match(/|| ',' ||/)
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should group with spaces if there's string columns from a has_many or has_and_belongs_to_many association" do
|
79
|
+
@index.attributes[4].to_select_sql.should match(/array_to_string\(array_accum\(.+, ' '\)/)
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should group with commas if there's integer columns from a has_many or has_and_belongs_to_many association" do
|
83
|
+
@index.attributes[5].to_select_sql.should match(/array_to_string\(array_accum\(.+, ','\)/)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
39
87
|
describe "to_group_sql method" do
|
40
88
|
before :each do
|
41
|
-
@attribute = ThinkingSphinx::Attribute.new([])
|
89
|
+
@attribute = ThinkingSphinx::Attribute.new([Object.stub_instance(:__stack => [])])
|
42
90
|
@attribute.stub_method(:is_many? => false, :is_string? => false)
|
43
91
|
|
44
92
|
ThinkingSphinx.stub_method(:use_group_by_shortcut? => false)
|
@@ -63,6 +111,7 @@ describe ThinkingSphinx::Attribute do
|
|
63
111
|
end
|
64
112
|
|
65
113
|
it "should return an array if neither is_many? or shortcut allowed" do
|
114
|
+
@attribute.stub_method(:column_with_prefix => 'hello')
|
66
115
|
@attribute.to_group_sql.should be_a_kind_of(Array)
|
67
116
|
end
|
68
117
|
|
@@ -70,4 +119,238 @@ describe ThinkingSphinx::Attribute do
|
|
70
119
|
ThinkingSphinx.unstub_method(:use_group_by_shortcut?)
|
71
120
|
end
|
72
121
|
end
|
122
|
+
|
123
|
+
describe "to_sphinx_clause method" do
|
124
|
+
before :each do
|
125
|
+
@attribute = ThinkingSphinx::Attribute.new [Object.stub_instance(:__stack => [])]
|
126
|
+
@attribute.stub_method(:unique_name => "unique name")
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should use sql_attr_multi syntax for MVA attributes" do
|
130
|
+
@attribute.stub_method(:type => :multi)
|
131
|
+
@attribute.to_sphinx_clause.should match(/^sql_attr_multi\s+= uint unique name from field$/)
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should use sql_attr_timestamp syntax for datetime values" do
|
135
|
+
@attribute.stub_method(:type => :datetime)
|
136
|
+
@attribute.to_sphinx_clause.should match(/^sql_attr_timestamp\s+= unique name$/)
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should use sql_attr_str2ordinal for string values" do
|
140
|
+
@attribute.stub_method(:type => :string)
|
141
|
+
@attribute.to_sphinx_clause.should match(/^sql_attr_str2ordinal\s+= unique name$/)
|
142
|
+
end
|
143
|
+
|
144
|
+
it "should use sql_attr_float for float values" do
|
145
|
+
@attribute.stub_method(:type => :float)
|
146
|
+
@attribute.to_sphinx_clause.should match(/^sql_attr_float\s+= unique name$/)
|
147
|
+
end
|
148
|
+
|
149
|
+
it "should use sql_attr_bool for boolean values" do
|
150
|
+
@attribute.stub_method(:type => :boolean)
|
151
|
+
@attribute.to_sphinx_clause.should match(/^sql_attr_bool\s+= unique name$/)
|
152
|
+
end
|
153
|
+
|
154
|
+
it "should use sql_attr_uint for integer values" do
|
155
|
+
@attribute.stub_method(:type => :integer)
|
156
|
+
@attribute.to_sphinx_clause.should match(/^sql_attr_uint\s+= unique name$/)
|
157
|
+
end
|
158
|
+
|
159
|
+
it "should assume integer for any other types" do
|
160
|
+
@attribute.stub_method(:type => :unknown)
|
161
|
+
@attribute.to_sphinx_clause.should match(/^sql_attr_uint\s+= unique name$/)
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
|
166
|
+
describe "unique_name method" do
|
167
|
+
before :each do
|
168
|
+
@attribute = ThinkingSphinx::Attribute.new [
|
169
|
+
Object.stub_instance(:__stack => [], :__name => "col_name")
|
170
|
+
]
|
171
|
+
end
|
172
|
+
|
173
|
+
it "should use the alias if there is one" do
|
174
|
+
@attribute.alias = "alias"
|
175
|
+
@attribute.unique_name.should == "alias"
|
176
|
+
end
|
177
|
+
|
178
|
+
it "should use the alias if there's multiple columns" do
|
179
|
+
@attribute.columns << Object.stub_instance(:__stack => [], :__name => "col_name")
|
180
|
+
@attribute.unique_name.should be_nil
|
181
|
+
|
182
|
+
@attribute.alias = "alias"
|
183
|
+
@attribute.unique_name.should == "alias"
|
184
|
+
end
|
185
|
+
|
186
|
+
it "should use the column name if there's no alias and just one column" do
|
187
|
+
@attribute.unique_name.should == "col_name"
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
describe "column_with_prefix method" do
|
192
|
+
before :each do
|
193
|
+
@attribute = ThinkingSphinx::Attribute.new [
|
194
|
+
ThinkingSphinx::Index::FauxColumn.new(:col_name)
|
195
|
+
]
|
196
|
+
@attribute.columns.each { |col| @attribute.associations[col] = [] }
|
197
|
+
@attribute.model = Person
|
198
|
+
|
199
|
+
@first_join = Object.stub_instance(:aliased_table_name => "tabular")
|
200
|
+
@second_join = Object.stub_instance(:aliased_table_name => "data")
|
201
|
+
|
202
|
+
@first_assoc = ThinkingSphinx::Association.stub_instance(:join => @first_join)
|
203
|
+
@second_assoc = ThinkingSphinx::Association.stub_instance(:join => @second_join)
|
204
|
+
end
|
205
|
+
|
206
|
+
it "should return the column name if the column is a string" do
|
207
|
+
@attribute.columns = [ThinkingSphinx::Index::FauxColumn.new("string")]
|
208
|
+
@attribute.send(:column_with_prefix, @attribute.columns.first).should == "string"
|
209
|
+
end
|
210
|
+
|
211
|
+
it "should return the column with model's table prefix if there's no associations for the column" do
|
212
|
+
@attribute.send(:column_with_prefix, @attribute.columns.first).should == "`people`.`col_name`"
|
213
|
+
end
|
214
|
+
|
215
|
+
it "should return the column with its join table prefix if an association exists" do
|
216
|
+
column = @attribute.columns.first
|
217
|
+
@attribute.associations[column] = [@first_assoc]
|
218
|
+
@attribute.send(:column_with_prefix, column).should == "`tabular`.`col_name`"
|
219
|
+
end
|
220
|
+
|
221
|
+
it "should return multiple columns concatenated if more than one association exists" do
|
222
|
+
column = @attribute.columns.first
|
223
|
+
@attribute.associations[column] = [@first_assoc, @second_assoc]
|
224
|
+
@attribute.send(:column_with_prefix, column).should == "`tabular`.`col_name`, `data`.`col_name`"
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
describe "is_many? method" do
|
229
|
+
before :each do
|
230
|
+
@assoc_a = Object.stub_instance(:is_many? => true)
|
231
|
+
@assoc_b = Object.stub_instance(:is_many? => true)
|
232
|
+
@assoc_c = Object.stub_instance(:is_many? => true)
|
233
|
+
|
234
|
+
@attribute = ThinkingSphinx::Attribute.new(
|
235
|
+
[ThinkingSphinx::Index::FauxColumn.new(:col_name)]
|
236
|
+
)
|
237
|
+
@attribute.associations = {
|
238
|
+
:a => @assoc_a, :b => @assoc_b, :c => @assoc_c
|
239
|
+
}
|
240
|
+
end
|
241
|
+
|
242
|
+
it "should return true if all associations return true to is_many?" do
|
243
|
+
@attribute.send(:is_many?).should be_true
|
244
|
+
end
|
245
|
+
|
246
|
+
it "should return true if one association returns true to is_many?" do
|
247
|
+
@assoc_b.stub_method(:is_many? => false)
|
248
|
+
@assoc_c.stub_method(:is_many? => false)
|
249
|
+
|
250
|
+
@attribute.send(:is_many?).should be_true
|
251
|
+
end
|
252
|
+
|
253
|
+
it "should return false if all associations return false to is_many?" do
|
254
|
+
@assoc_a.stub_method(:is_many? => false)
|
255
|
+
@assoc_b.stub_method(:is_many? => false)
|
256
|
+
@assoc_c.stub_method(:is_many? => false)
|
257
|
+
|
258
|
+
@attribute.send(:is_many?).should be_false
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
describe "is_string? method" do
|
263
|
+
before :each do
|
264
|
+
@col_a = ThinkingSphinx::Index::FauxColumn.new("a")
|
265
|
+
@col_b = ThinkingSphinx::Index::FauxColumn.new("b")
|
266
|
+
@col_c = ThinkingSphinx::Index::FauxColumn.new("c")
|
267
|
+
|
268
|
+
@attribute = ThinkingSphinx::Attribute.new(
|
269
|
+
[@col_a, @col_b, @col_c]
|
270
|
+
)
|
271
|
+
end
|
272
|
+
|
273
|
+
it "should return true if all columns return true to is_string?" do
|
274
|
+
@attribute.send(:is_string?).should be_true
|
275
|
+
end
|
276
|
+
|
277
|
+
it "should return false if one column returns true to is_string?" do
|
278
|
+
@col_a.send(:instance_variable_set, :@name, :a)
|
279
|
+
@attribute.send(:is_string?).should be_false
|
280
|
+
end
|
281
|
+
|
282
|
+
it "should return false if all columns return false to is_string?" do
|
283
|
+
@col_a.send(:instance_variable_set, :@name, :a)
|
284
|
+
@col_b.send(:instance_variable_set, :@name, :b)
|
285
|
+
@col_c.send(:instance_variable_set, :@name, :c)
|
286
|
+
@attribute.send(:is_string?).should be_false
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
describe "type method" do
|
291
|
+
before :each do
|
292
|
+
@column = ThinkingSphinx::Index::FauxColumn.new(:col_name)
|
293
|
+
@attribute = ThinkingSphinx::Attribute.new([@column])
|
294
|
+
@attribute.model = Person
|
295
|
+
@attribute.stub_method(:is_many? => false)
|
296
|
+
end
|
297
|
+
|
298
|
+
it "should return :multi if is_many? is true" do
|
299
|
+
@attribute.stub_method(:is_many? => true)
|
300
|
+
@attribute.send(:type).should == :multi
|
301
|
+
end
|
302
|
+
|
303
|
+
it "should return :string if there's more than one association" do
|
304
|
+
@attribute.associations = {:a => :assoc, :b => :assoc}
|
305
|
+
@attribute.send(:type).should == :string
|
306
|
+
end
|
307
|
+
|
308
|
+
it "should return the column type from the database if not :multi or more than one association" do
|
309
|
+
@column.send(:instance_variable_set, :@name, "birthday")
|
310
|
+
@attribute.send(:type).should == :datetime
|
311
|
+
|
312
|
+
@attribute.send(:instance_variable_set, :@type, nil)
|
313
|
+
@column.send(:instance_variable_set, :@name, "first_name")
|
314
|
+
@attribute.send(:type).should == :string
|
315
|
+
|
316
|
+
@attribute.send(:instance_variable_set, :@type, nil)
|
317
|
+
@column.send(:instance_variable_set, :@name, "id")
|
318
|
+
@attribute.send(:type).should == :integer
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
describe "all_ints? method" do
|
323
|
+
it "should return true if all columns are integers" do
|
324
|
+
attribute = ThinkingSphinx::Attribute.new(
|
325
|
+
[ ThinkingSphinx::Index::FauxColumn.new(:id),
|
326
|
+
ThinkingSphinx::Index::FauxColumn.new(:team_id) ]
|
327
|
+
)
|
328
|
+
attribute.model = Person
|
329
|
+
attribute.columns.each { |col| attribute.associations[col] = [] }
|
330
|
+
|
331
|
+
attribute.send(:all_ints?).should be_true
|
332
|
+
end
|
333
|
+
|
334
|
+
it "should return false if only some columns are integers" do
|
335
|
+
attribute = ThinkingSphinx::Attribute.new(
|
336
|
+
[ ThinkingSphinx::Index::FauxColumn.new(:id),
|
337
|
+
ThinkingSphinx::Index::FauxColumn.new(:first_name) ]
|
338
|
+
)
|
339
|
+
attribute.model = Person
|
340
|
+
attribute.columns.each { |col| attribute.associations[col] = [] }
|
341
|
+
|
342
|
+
attribute.send(:all_ints?).should be_false
|
343
|
+
end
|
344
|
+
|
345
|
+
it "should return false if no columns are integers" do
|
346
|
+
attribute = ThinkingSphinx::Attribute.new(
|
347
|
+
[ ThinkingSphinx::Index::FauxColumn.new(:first_name),
|
348
|
+
ThinkingSphinx::Index::FauxColumn.new(:last_name) ]
|
349
|
+
)
|
350
|
+
attribute.model = Person
|
351
|
+
attribute.columns.each { |col| attribute.associations[col] = [] }
|
352
|
+
|
353
|
+
attribute.send(:all_ints?).should be_false
|
354
|
+
end
|
355
|
+
end
|
73
356
|
end
|
@@ -1,7 +1,438 @@
|
|
1
1
|
require 'spec/spec_helper'
|
2
2
|
|
3
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
|
+
|
4
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
|
63
|
+
)
|
64
|
+
@person_index_b = ThinkingSphinx::Index.stub_instance(
|
65
|
+
:to_config => "", :adapter => :mysql, :delta? => false
|
66
|
+
)
|
67
|
+
@friendship_index_a = ThinkingSphinx::Index.stub_instance(
|
68
|
+
:to_config => "", :adapter => :mysql, :delta? => false
|
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
|
+
"mem_limit" => "128M",
|
216
|
+
"max_matches" => 1001,
|
217
|
+
"morphology" => "stem_ru",
|
218
|
+
"charset_type" => "latin1",
|
219
|
+
"charset_table" => "table",
|
220
|
+
"ignore_chars" => "e"
|
221
|
+
}
|
222
|
+
}
|
223
|
+
# puts YAML.dump(settings)
|
224
|
+
open("#{RAILS_ROOT}/config/sphinx.yml", "w") do |f|
|
225
|
+
f.write YAML.dump(@settings)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
it "should use the accessors to set the configuration values" do
|
230
|
+
config = ThinkingSphinx::Configuration.new
|
231
|
+
@settings["development"].each do |key, value|
|
232
|
+
config.send(key).should == value
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
describe "core_index_for_model method" do
|
238
|
+
before :each do
|
239
|
+
@config = ThinkingSphinx::Configuration.new
|
240
|
+
@model = Class.stub_instance(
|
241
|
+
:indexes => [],
|
242
|
+
:name => "SpecModel"
|
243
|
+
)
|
244
|
+
end
|
5
245
|
|
246
|
+
it "should take its name from the model, with _core appended" do
|
247
|
+
@config.send(:core_index_for_model, @model, "my sources").should match(
|
248
|
+
/index specmodel_core/
|
249
|
+
)
|
250
|
+
end
|
251
|
+
|
252
|
+
it "should set the path to follow the name" do
|
253
|
+
@config.searchd_file_path = "/my/file/path"
|
254
|
+
@config.send(:core_index_for_model, @model, "my sources").should match(
|
255
|
+
/path = \/my\/file\/path\/specmodel_core/
|
256
|
+
)
|
257
|
+
end
|
258
|
+
|
259
|
+
it "should include the charset type setting" do
|
260
|
+
@config.charset_type = "specchars"
|
261
|
+
@config.send(:core_index_for_model, @model, "my sources").should match(
|
262
|
+
/charset_type = specchars/
|
263
|
+
)
|
264
|
+
end
|
265
|
+
|
266
|
+
it "should include the morphology setting if it isn't blank" do
|
267
|
+
@config.morphology = "morph"
|
268
|
+
@config.send(:core_index_for_model, @model, "my sources").should match(
|
269
|
+
/morphology\s+= morph/
|
270
|
+
)
|
271
|
+
end
|
272
|
+
|
273
|
+
it "should not include the morphology setting if it is blank" do
|
274
|
+
@config.morphology = nil
|
275
|
+
@config.send(:core_index_for_model, @model, "my sources").should_not match(
|
276
|
+
/morphology\s+=/
|
277
|
+
)
|
278
|
+
|
279
|
+
@config.morphology = ""
|
280
|
+
@config.send(:core_index_for_model, @model, "my sources").should_not match(
|
281
|
+
/morphology\s+=/
|
282
|
+
)
|
283
|
+
end
|
284
|
+
|
285
|
+
it "should include the charset_table value if it isn't nil" do
|
286
|
+
@config.charset_table = "table_chars"
|
287
|
+
@config.send(:core_index_for_model, @model, "my sources").should match(
|
288
|
+
/charset_table\s+= table_chars/
|
289
|
+
)
|
290
|
+
end
|
291
|
+
|
292
|
+
it "should not set the charset_table value if it is nil" do
|
293
|
+
@config.charset_table = nil
|
294
|
+
@config.send(:core_index_for_model, @model, "my sources").should_not match(
|
295
|
+
/charset_table\s+=/
|
296
|
+
)
|
297
|
+
end
|
298
|
+
|
299
|
+
it "should set the ignore_chars value if it isn't nil" do
|
300
|
+
@config.ignore_chars = "ignorable"
|
301
|
+
@config.send(:core_index_for_model, @model, "my sources").should match(
|
302
|
+
/ignore_chars\s+= ignorable/
|
303
|
+
)
|
304
|
+
end
|
305
|
+
|
306
|
+
it "should not set the ignore_chars value if it is nil" do
|
307
|
+
@config.ignore_chars = nil
|
308
|
+
@config.send(:core_index_for_model, @model, "my sources").should_not match(
|
309
|
+
/ignore_chars\s+=/
|
310
|
+
)
|
311
|
+
end
|
312
|
+
|
313
|
+
it "should include the star-related settings when allow_star is true" do
|
314
|
+
@config.allow_star = true
|
315
|
+
text = @config.send(:core_index_for_model, @model, "my sources")
|
316
|
+
|
317
|
+
text.should match(/enable_star\s+= 1/)
|
318
|
+
text.should match(/min_prefix_len\s+= 1/)
|
319
|
+
text.should match(/min_infix_len\s+= 1/)
|
320
|
+
end
|
321
|
+
|
322
|
+
it "should not include the star-related settings when allow_star is false" do
|
323
|
+
@config.allow_star = false
|
324
|
+
text = @config.send(:core_index_for_model, @model, "my sources")
|
325
|
+
|
326
|
+
text.should_not match(/enable_star\s+=/)
|
327
|
+
text.should_not match(/min_prefix_len\s+=/)
|
328
|
+
text.should_not match(/min_infix_len\s+=/)
|
329
|
+
end
|
330
|
+
|
331
|
+
it "should set prefix_fields if any fields are flagged explicitly" do
|
332
|
+
@index = ThinkingSphinx::Index.stub_instance(
|
333
|
+
:prefix_fields => ["a", "b", "c"],
|
334
|
+
:infix_fields => ["d", "e", "f"]
|
335
|
+
)
|
336
|
+
@model.stub_method(:indexes => [@index])
|
337
|
+
|
338
|
+
@config.send(:core_index_for_model, @model, "my sources").should match(
|
339
|
+
/prefix_fields\s+= a, b, c/
|
340
|
+
)
|
341
|
+
end
|
342
|
+
|
343
|
+
it "shouldn't set prefix_fields if none are flagged explicitly" do
|
344
|
+
@config.send(:core_index_for_model, @model, "my sources").should_not match(
|
345
|
+
/prefix_fields\s+=/
|
346
|
+
)
|
347
|
+
end
|
348
|
+
|
349
|
+
it "should set infix_fields if any fields are flagged explicitly" do
|
350
|
+
@index = ThinkingSphinx::Index.stub_instance(
|
351
|
+
:prefix_fields => ["a", "b", "c"],
|
352
|
+
:infix_fields => ["d", "e", "f"]
|
353
|
+
)
|
354
|
+
@model.stub_method(:indexes => [@index])
|
355
|
+
|
356
|
+
@config.send(:core_index_for_model, @model, "my sources").should match(
|
357
|
+
/infix_fields\s+= d, e, f/
|
358
|
+
)
|
359
|
+
end
|
360
|
+
|
361
|
+
it "shouldn't set infix_fields if none are flagged explicitly" do
|
362
|
+
@config.send(:core_index_for_model, @model, "my sources").should_not match(
|
363
|
+
/infix_fields\s+=/
|
364
|
+
)
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
describe "delta_index_for_model method" do
|
369
|
+
before :each do
|
370
|
+
@config = ThinkingSphinx::Configuration.new
|
371
|
+
@model = Class.stub_instance(
|
372
|
+
:name => "SpecModel"
|
373
|
+
)
|
374
|
+
end
|
375
|
+
|
376
|
+
it "should take its name from the model, with _delta appended" do
|
377
|
+
@config.send(:delta_index_for_model, @model, "delta_sources").should match(
|
378
|
+
/index specmodel_delta/
|
379
|
+
)
|
380
|
+
end
|
381
|
+
|
382
|
+
it "should inherit from the equivalent core index" do
|
383
|
+
@config.send(:delta_index_for_model, @model, "delta_sources").should match(
|
384
|
+
/index specmodel_delta : specmodel_core/
|
385
|
+
)
|
386
|
+
end
|
387
|
+
|
388
|
+
it "should set the path to follow the name" do
|
389
|
+
@config.searchd_file_path = "/my/file/path"
|
390
|
+
@config.send(:delta_index_for_model, @model, "delta_sources").should match(
|
391
|
+
/path = \/my\/file\/path\/specmodel_delta/
|
392
|
+
)
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
396
|
+
describe "distributed_index_for_model method" do
|
397
|
+
before :each do
|
398
|
+
@config = ThinkingSphinx::Configuration.new
|
399
|
+
@model = Class.stub_instance(
|
400
|
+
:name => "SpecModel",
|
401
|
+
:indexes => []
|
402
|
+
)
|
403
|
+
end
|
404
|
+
|
405
|
+
it "should take its name from the model" do
|
406
|
+
@config.send(:distributed_index_for_model, @model).should match(
|
407
|
+
/index specmodel/
|
408
|
+
)
|
409
|
+
end
|
410
|
+
|
411
|
+
it "should have a type of distributed" do
|
412
|
+
@config.send(:distributed_index_for_model, @model).should match(
|
413
|
+
/type = distributed/
|
414
|
+
)
|
415
|
+
end
|
416
|
+
|
417
|
+
it "should include the core as a local source" do
|
418
|
+
@config.send(:distributed_index_for_model, @model).should match(
|
419
|
+
/local = specmodel_core/
|
420
|
+
)
|
421
|
+
end
|
422
|
+
|
423
|
+
it "should only include the delta as a local source if an index is flagged to be delta" do
|
424
|
+
@config.send(:distributed_index_for_model, @model).should_not match(
|
425
|
+
/local = specmodel_delta/
|
426
|
+
)
|
427
|
+
|
428
|
+
@model.stub_method(:indexes => [ThinkingSphinx::Index.stub_instance(:delta? => true)])
|
429
|
+
@config.send(:distributed_index_for_model, @model).should match(
|
430
|
+
/local = specmodel_delta/
|
431
|
+
)
|
432
|
+
end
|
433
|
+
end
|
434
|
+
|
435
|
+
describe "create_array_accum method" do
|
436
|
+
it "should create the array_accum method on PostgreSQL"
|
6
437
|
end
|
7
438
|
end
|