thinking-sphinx 2.0.11 → 2.0.12

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.
@@ -95,6 +95,11 @@ module ThinkingSphinx
95
95
  populate if @options[:populate]
96
96
  end
97
97
 
98
+ def ==(object)
99
+ populate
100
+ super
101
+ end
102
+
98
103
  def to_a
99
104
  populate
100
105
  @array
@@ -442,6 +447,8 @@ module ThinkingSphinx
442
447
  def compose_results
443
448
  if options[:ids_only]
444
449
  compose_ids_results
450
+ elsif options[:attributes_only]
451
+ compose_attributes_results
445
452
  elsif options[:only]
446
453
  compose_only_results
447
454
  else
@@ -458,6 +465,16 @@ module ThinkingSphinx
458
465
  }
459
466
  end
460
467
 
468
+ def compose_attributes_results
469
+ replace @results[:matches].collect { |match|
470
+ attributes = {}
471
+ match[:attributes].each do |name, value|
472
+ attributes[name.to_sym] = match[:attributes][name]
473
+ end
474
+ attributes
475
+ }
476
+ end
477
+
461
478
  def compose_only_results
462
479
  replace @results[:matches].collect { |match|
463
480
  case only = options[:only]
@@ -544,7 +561,7 @@ module ThinkingSphinx
544
561
  [
545
562
  :max_matches, :group_by, :group_function, :group_clause,
546
563
  :group_distinct, :id_range, :cut_off, :retry_count, :retry_delay,
547
- :rank_mode, :max_query_time, :field_weights
564
+ :rank_mode, :rank_expr, :max_query_time, :field_weights
548
565
  ].each do |key|
549
566
  value = options[key] || index_options[key]
550
567
  client.send("#{key}=", value) if value
@@ -775,8 +792,10 @@ module ThinkingSphinx
775
792
  filter_value(value.first).first..filter_value(value.last).first
776
793
  when Array
777
794
  value.collect { |v| filter_value(v) }.flatten
778
- when Date, Time
779
- [value.to_time.to_i]
795
+ when Time
796
+ [value.to_i]
797
+ when Date
798
+ [Time.utc(value.year, value.month, value.day).to_i]
780
799
  when NilClass
781
800
  0
782
801
  else
@@ -885,7 +904,7 @@ module ThinkingSphinx
885
904
  index_options = klass.sphinx_index_options
886
905
 
887
906
  ids = matches.collect { |match| match[:attributes]["sphinx_internal_id"] }
888
- instances = ids.length > 0 ? klass.find(
907
+ instances = ids.length > 0 ? klass.unscoped.find(
889
908
  :all,
890
909
  :joins => options[:joins],
891
910
  :conditions => {klass.primary_key_for_sphinx.to_sym => ids},
@@ -27,11 +27,6 @@ module ThinkingSphinx
27
27
  @model, [], initial_joins
28
28
  )
29
29
 
30
- unless @model.descends_from_active_record?
31
- stored_class = @model.store_full_sti_class ? @model.name : @model.name.demodulize
32
- @conditions << "#{@model.quoted_table_name}.#{quote_column(@model.inheritance_column)} = '#{stored_class}'"
33
- end
34
-
35
30
  add_internal_attributes_and_facets
36
31
  end
37
32
 
@@ -97,6 +92,11 @@ module ThinkingSphinx
97
92
  source.sql_db = config[:database]
98
93
  source.sql_port = config[:port]
99
94
  source.sql_sock = config[:socket]
95
+
96
+ # MySQL SSL support
97
+ source.mysql_ssl_ca = config[:sslca] if config[:sslca]
98
+ source.mysql_ssl_cert = config[:sslcert] if config[:sslcert]
99
+ source.mysql_ssl_key = config[:sslkey] if config[:sslkey]
100
100
  end
101
101
 
102
102
  def set_source_fields(source)
@@ -6,9 +6,9 @@ module ThinkingSphinx
6
6
  # the version filtered for delta values, send through :delta => true in
7
7
  # the options. Won't do much though if the index isn't set up to support a
8
8
  # delta sibling.
9
- #
9
+ #
10
10
  # Examples:
11
- #
11
+ #
12
12
  # source.to_sql
13
13
  # source.to_sql(:delta => true)
14
14
  #
@@ -32,10 +32,10 @@ module ThinkingSphinx
32
32
  # Simple helper method for the query range SQL - which is a statement that
33
33
  # returns minimum and maximum id values. These can be filtered by delta -
34
34
  # so pass in :delta => true to get the delta version of the SQL.
35
- #
35
+ #
36
36
  def to_sql_query_range(options={})
37
37
  return nil if @index.options[:disable_range]
38
-
38
+
39
39
  min_statement = adapter.convert_nulls(
40
40
  "MIN(#{quote_column(@model.primary_key_for_sphinx)})", 1
41
41
  )
@@ -54,7 +54,7 @@ module ThinkingSphinx
54
54
 
55
55
  # Simple helper method for the query info SQL - which is a statement that
56
56
  # returns the single row for a corresponding id.
57
- #
57
+ #
58
58
  def to_sql_query_info(offset)
59
59
  "SELECT * FROM #{@model.quoted_table_name} WHERE " +
60
60
  "#{quote_column(@model.primary_key_for_sphinx)} = (($id - #{offset}) / #{ThinkingSphinx.context.indexed_models.size})"
@@ -64,7 +64,7 @@ module ThinkingSphinx
64
64
  unique_id_expr = ThinkingSphinx.unique_id_expression(adapter, offset)
65
65
 
66
66
  (
67
- ["#{@model.quoted_table_name}.#{quote_column(@model.primary_key_for_sphinx)} #{unique_id_expr} AS #{quote_column(@model.primary_key_for_sphinx)} "] +
67
+ ["#{@model.quoted_table_name}.#{quote_column(@model.primary_key_for_sphinx)} #{unique_id_expr} AS #{quote_column(@model.primary_key_for_sphinx)} "] +
68
68
  @fields.collect { |field| field.to_select_sql } +
69
69
  @attributes.collect { |attribute| attribute.to_select_sql }
70
70
  ).compact.join(", ")
@@ -92,7 +92,7 @@ module ThinkingSphinx
92
92
  end
93
93
 
94
94
  (
95
- ["#{@model.quoted_table_name}.#{quote_column(@model.primary_key_for_sphinx)}"] +
95
+ ["#{@model.quoted_table_name}.#{quote_column(@model.primary_key_for_sphinx)}"] +
96
96
  @fields.collect { |field| field.to_group_sql }.compact +
97
97
  @attributes.collect { |attribute| attribute.to_group_sql }.compact +
98
98
  @groupings + internal_groupings
@@ -118,40 +118,57 @@ module ThinkingSphinx
118
118
  def crc_column
119
119
  if @model.table_exists? &&
120
120
  @model.column_names.include?(@model.inheritance_column)
121
-
121
+
122
122
  types = types_to_crcs
123
123
  return @model.to_crc32.to_s if types.empty?
124
-
124
+
125
125
  adapter.case(adapter.convert_nulls(
126
- adapter.quote_with_table(@model.inheritance_column)),
126
+ adapter.quote_with_table(@model.inheritance_column), @model.name),
127
127
  types, @model.to_crc32)
128
128
  else
129
129
  @model.to_crc32.to_s
130
130
  end
131
131
  end
132
-
132
+
133
133
  def internal_class_column
134
+ quoted_name = "'#{@model.name}'"
135
+
134
136
  if @model.table_exists? &&
135
137
  @model.column_names.include?(@model.inheritance_column)
136
- adapter.quote_with_table(@model.inheritance_column)
138
+
139
+ types = types_to_hash
140
+ return quoted_name if types.empty?
141
+
142
+ adapter.case(adapter.convert_nulls(
143
+ adapter.quote_with_table(@model.inheritance_column), @model.name),
144
+ types, quoted_name)
137
145
  else
138
- "'#{@model.name}'"
146
+ quoted_name
139
147
  end
140
148
  end
141
-
149
+
142
150
  def type_values
151
+ return @model.sphinx_types unless @model.sphinx_types.nil?
152
+
143
153
  @model.connection.select_values <<-SQL
144
154
  SELECT DISTINCT #{@model.inheritance_column}
145
155
  FROM #{@model.table_name}
146
156
  SQL
147
157
  end
148
-
158
+
149
159
  def types_to_crcs
150
160
  type_values.compact.inject({}) { |hash, type|
151
161
  hash[type] = type.to_crc32
152
162
  hash
153
163
  }
154
164
  end
165
+
166
+ def types_to_hash
167
+ type_values.compact.inject({}) { |hash, type|
168
+ hash[type] = "'#{type}'"
169
+ hash
170
+ }
171
+ end
155
172
  end
156
173
  end
157
- end
174
+ end
@@ -1,3 +1,3 @@
1
1
  module ThinkingSphinx
2
- Version = '2.0.11'
2
+ Version = '2.0.12'
3
3
  end
@@ -99,6 +99,9 @@ class Child < Person
99
99
  end
100
100
  end
101
101
 
102
+ class Teenager < Child
103
+ end
104
+
102
105
  class Alpha < ActiveRecord::Base
103
106
  has_many :betas, :class_name => 'Beta'
104
107
  has_many :thetas
@@ -10,7 +10,6 @@ require 'bundler'
10
10
  Bundler.require :default, :development
11
11
 
12
12
  require 'active_support/core_ext/module/attribute_accessors'
13
- require 'active_support/core_ext/class/inheritable_attributes'
14
13
  require "#{File.dirname(__FILE__)}/sphinx_helper"
15
14
 
16
15
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
@@ -18,6 +18,9 @@ class SphinxHelper
18
18
  @username = config['username']
19
19
  @password = config['password']
20
20
  @socket = config['socket']
21
+ @sslca = config['sslca']
22
+ @sslcert = config['sslcert']
23
+ @sslkey = config['sslkey']
21
24
  end
22
25
 
23
26
  @path = File.expand_path(File.dirname(__FILE__))
@@ -30,7 +33,10 @@ class SphinxHelper
30
33
  :username => @username,
31
34
  :password => @password,
32
35
  :host => @host,
33
- :socket => @socket
36
+ :socket => @socket,
37
+ :sslca => @sslca,
38
+ :sslcert => @sslcert,
39
+ :sslkey => @sslkey
34
40
  )
35
41
  ActiveRecord::Base.logger = Logger.new(File.open('tmp/activerecord.log', 'a'))
36
42
 
@@ -419,6 +419,21 @@ describe ThinkingSphinx::ActiveRecord do
419
419
  end
420
420
  end
421
421
 
422
+ describe '#types_for_sphinx' do
423
+ after :each do
424
+ Person.set_sphinx_types nil
425
+ end
426
+
427
+ it "should return nil by default" do
428
+ Person.sphinx_types.should == nil
429
+ end
430
+
431
+ it "should return the specified value" do
432
+ Person.set_sphinx_types %w(Person Parent)
433
+ Person.sphinx_types.should == %w(Person Parent)
434
+ end
435
+ end
436
+
422
437
  describe '.sphinx_index_names' do
423
438
  it "should return the core index" do
424
439
  Alpha.define_index { indexes :name }
@@ -54,6 +54,14 @@ describe ThinkingSphinx::AutoVersion do
54
54
  ThinkingSphinx::AutoVersion.detect
55
55
  end
56
56
 
57
+ it "should require 2.1.0 if using Sphinx 2.0.3" do
58
+ ThinkingSphinx::AutoVersion.should_receive(:require).
59
+ with('riddle/2.1.0')
60
+
61
+ @config.stub!(:version => '2.0.3-release')
62
+ ThinkingSphinx::AutoVersion.detect
63
+ end
64
+
57
65
  it "should require 2.1.0 if using Sphinx 2.1.0 dev" do
58
66
  ThinkingSphinx::AutoVersion.should_receive(:require).
59
67
  with('riddle/2.1.0')
@@ -10,338 +10,338 @@ describe ThinkingSphinx::Index::Builder do
10
10
  indexes first_name, last_name
11
11
  has birthday
12
12
  has id, :as => :internal_id
13
-
13
+
14
14
  set_property :sql_range_step => 1000
15
-
15
+
16
16
  where "birthday <= NOW()"
17
17
  group_by "first_name"
18
18
  end
19
-
19
+
20
20
  @source = @index.sources.first
21
21
  end
22
-
22
+
23
23
  it "should return an index" do
24
24
  @index.should be_a_kind_of(ThinkingSphinx::Index)
25
25
  end
26
-
26
+
27
27
  it "should have one source for the index" do
28
28
  @index.sources.length.should == 1
29
29
  end
30
-
30
+
31
31
  it "should have two fields" do
32
32
  @source.fields.length.should == 2
33
33
  @source.fields[0].unique_name.should == :first_name
34
34
  @source.fields[1].unique_name.should == :last_name
35
35
  end
36
-
36
+
37
37
  it "should have two attributes alongside the internal ones" do
38
38
  @source.attributes.length.should == 2 + internal_attribute_count
39
39
  @source.attributes[internal_attribute_count].unique_name.should == :birthday
40
40
  @source.attributes[1 + internal_attribute_count].unique_name.should == :internal_id
41
41
  end
42
-
42
+
43
43
  it "should have one condition" do
44
44
  @source.conditions.length.should == 1
45
45
  @source.conditions.first.should == "birthday <= NOW()"
46
46
  end
47
-
47
+
48
48
  it "should have one grouping" do
49
49
  @source.groupings.length.should == 1
50
50
  @source.groupings.first.should == "first_name"
51
51
  end
52
-
52
+
53
53
  it "should have one option" do
54
54
  @source.options.length.should == 1
55
55
  @source.options[:sql_range_step].should == 1000
56
56
  end
57
57
  end
58
-
58
+
59
59
  describe 'aliased field' do
60
60
  before :each do
61
61
  @index = ThinkingSphinx::Index::Builder.generate(Person) do
62
62
  indexes first_name, :as => 'name'
63
63
  end
64
-
64
+
65
65
  @source = @index.sources.first
66
66
  end
67
-
67
+
68
68
  it "should store the alias as a symbol for consistency" do
69
69
  @source.fields.last.unique_name.should == :name
70
70
  end
71
71
  end
72
-
72
+
73
73
  describe 'aliased attribute' do
74
74
  before :each do
75
75
  @index = ThinkingSphinx::Index::Builder.generate(Person) do
76
76
  indexes first_name
77
77
  has :id, :as => 'real_id'
78
78
  end
79
-
79
+
80
80
  @source = @index.sources.first
81
81
  end
82
-
82
+
83
83
  it "should store the alias as a symbol for consistency" do
84
84
  @source.attributes.last.unique_name.should == :real_id
85
85
  end
86
86
  end
87
-
87
+
88
88
  describe "sortable field" do
89
89
  before :each do
90
90
  @index = ThinkingSphinx::Index::Builder.generate(Person) do
91
91
  indexes first_name, :sortable => true
92
92
  end
93
-
93
+
94
94
  @source = @index.sources.first
95
95
  end
96
-
96
+
97
97
  it "should have one field" do
98
98
  @source.fields.length.should == 1
99
99
  end
100
-
100
+
101
101
  it "should have one attribute alongside the internal ones" do
102
102
  @source.attributes.length.should == 1 + internal_attribute_count
103
103
  end
104
-
104
+
105
105
  it "should set the attribute name to have the _sort suffix" do
106
106
  @source.attributes.last.unique_name.should == :first_name_sort
107
107
  end
108
-
108
+
109
109
  it "should set the attribute column to be the same as the field" do
110
110
  @source.attributes.last.columns.length.should == 1
111
111
  @source.attributes.last.columns.first.__name.should == :first_name
112
112
  end
113
113
  end
114
-
114
+
115
115
  describe '#join' do
116
116
  before :each do
117
117
  @index = ThinkingSphinx::Index::Builder.generate(Person) do
118
118
  indexes first_name
119
-
119
+
120
120
  join contacts
121
121
  end
122
-
122
+
123
123
  @source = @index.sources.first
124
124
  end
125
-
125
+
126
126
  it "should include the explicit join" do
127
127
  @source.joins.length.should == 1
128
128
  end
129
129
  end
130
-
130
+
131
131
  describe "faceted field" do
132
132
  before :each do
133
133
  @index = ThinkingSphinx::Index::Builder.generate(Person) do
134
134
  indexes first_name, :facet => true
135
135
  end
136
-
136
+
137
137
  @source = @index.sources.first
138
138
  end
139
-
139
+
140
140
  after :each do
141
141
  Person.sphinx_facets.delete_at(-1)
142
142
  end
143
-
143
+
144
144
  it "should have one field" do
145
145
  @source.fields.length.should == 1
146
146
  end
147
-
147
+
148
148
  it "should have one attribute alongside the internal ones" do
149
149
  @source.attributes.length.should == 1 + internal_attribute_count
150
150
  end
151
-
151
+
152
152
  it "should set the attribute name to have the _facet suffix" do
153
153
  @source.attributes.last.unique_name.should == :first_name_facet
154
154
  end
155
-
155
+
156
156
  it "should set the attribute type to integer" do
157
157
  @source.attributes.last.type.should == :integer
158
158
  end
159
-
159
+
160
160
  it "should set the attribute column to be the same as the field" do
161
161
  @source.attributes.last.columns.length.should == 1
162
162
  @source.attributes.last.columns.first.__name.should == :first_name
163
163
  end
164
164
  end
165
-
165
+
166
166
  describe "faceted integer attribute" do
167
167
  before :each do
168
168
  @index = ThinkingSphinx::Index::Builder.generate(Alpha) do
169
169
  indexes :name
170
170
  has value, :facet => true
171
171
  end
172
-
172
+
173
173
  @source = @index.sources.first
174
174
  end
175
-
175
+
176
176
  after :each do
177
177
  Alpha.sphinx_facets.delete_at(-1)
178
178
  end
179
-
179
+
180
180
  it "should have just one attribute alongside the internal ones" do
181
181
  @source.attributes.length.should == 1 + internal_attribute_count
182
182
  end
183
183
  end
184
-
184
+
185
185
  describe "faceted timestamp attribute" do
186
186
  before :each do
187
187
  @index = ThinkingSphinx::Index::Builder.generate(Person) do
188
188
  indexes first_name
189
189
  has birthday, :facet => true
190
190
  end
191
-
191
+
192
192
  @source = @index.sources.first
193
193
  end
194
-
194
+
195
195
  after :each do
196
196
  Person.sphinx_facets.delete_at(-1)
197
197
  end
198
-
198
+
199
199
  it "should have just one attribute alongside the internal ones" do
200
200
  @source.attributes.length.should == 1 + internal_attribute_count
201
201
  end
202
202
  end
203
-
203
+
204
204
  describe "faceted boolean attribute" do
205
205
  before :each do
206
206
  @index = ThinkingSphinx::Index::Builder.generate(Beta) do
207
207
  indexes :name
208
208
  has delta, :facet => true
209
209
  end
210
-
210
+
211
211
  @source = @index.sources.first
212
212
  end
213
-
213
+
214
214
  after :each do
215
215
  Beta.sphinx_facets.delete_at(-1)
216
216
  end
217
-
217
+
218
218
  it "should have just one attribute alongside the internal ones" do
219
219
  @source.attributes.length.should == 1 + internal_attribute_count
220
220
  end
221
221
  end
222
-
222
+
223
223
  describe "faceted float attribute" do
224
224
  before :each do
225
225
  @index = ThinkingSphinx::Index::Builder.generate(Alpha) do
226
226
  indexes :name
227
227
  has cost, :facet => true
228
228
  end
229
-
229
+
230
230
  @source = @index.sources.first
231
231
  end
232
-
232
+
233
233
  after :each do
234
234
  Alpha.sphinx_facets.delete_at(-1)
235
235
  end
236
-
236
+
237
237
  it "should have just one attribute alongside the internal ones" do
238
238
  @source.attributes.length.should == 1 + internal_attribute_count
239
239
  end
240
240
  end
241
-
241
+
242
242
  describe "faceted string attribute" do
243
243
  before :each do
244
244
  @index = ThinkingSphinx::Index::Builder.generate(Person) do
245
245
  indexes first_name
246
246
  has last_name, :facet => true
247
247
  end
248
-
248
+
249
249
  @source = @index.sources.first
250
250
  end
251
-
251
+
252
252
  after :each do
253
253
  Person.sphinx_facets.delete_at(-1)
254
254
  end
255
-
255
+
256
256
  it "should have two attributes alongside the internal ones" do
257
257
  @source.attributes.length.should == 2 + internal_attribute_count
258
258
  end
259
-
259
+
260
260
  it "should set the facet attribute name to have the _facet suffix" do
261
261
  @source.attributes.last.unique_name.should == :last_name_facet
262
262
  end
263
-
263
+
264
264
  it "should set the attribute type to integer" do
265
265
  @source.attributes.last.type.should == :integer
266
266
  end
267
-
267
+
268
268
  it "should set the attribute column to be the same as the field" do
269
269
  @source.attributes.last.columns.length.should == 1
270
270
  @source.attributes.last.columns.first.__name.should == :last_name
271
271
  end
272
272
  end
273
-
273
+
274
274
  describe 'faceted manual MVA' do
275
275
  before :each do
276
276
  @index = ThinkingSphinx::Index::Builder.generate(Person) do
277
277
  indexes first_name
278
278
  has 'SQL STATEMENT', :type => :multi, :as => :sql, :facet => true
279
279
  end
280
-
280
+
281
281
  @source = @index.sources.first
282
282
  end
283
-
283
+
284
284
  after :each do
285
285
  Person.sphinx_facets.delete_at(-1)
286
286
  end
287
-
287
+
288
288
  it "should have two attributes alongside the internal ones" do
289
289
  @source.attributes.length.should == 2 + internal_attribute_count
290
290
  end
291
-
291
+
292
292
  it "should set the facet attribute name to have the _facet suffix" do
293
293
  @source.attributes.last.unique_name.should == :sql_facet
294
294
  end
295
-
295
+
296
296
  it "should keep the original attribute's name set as requested" do
297
297
  @source.attributes[-2].unique_name.should == :sql
298
298
  end
299
-
299
+
300
300
  it "should set the attribute type to multi" do
301
301
  @source.attributes.last.type.should == :multi
302
302
  end
303
-
303
+
304
304
  it "should set the attribute column to be the same as the field" do
305
305
  @source.attributes.last.columns.length.should == 1
306
306
  @source.attributes.last.columns.first.__name.should == 'SQL STATEMENT'
307
307
  end
308
308
  end
309
-
309
+
310
310
  describe 'faceted MVA field' do
311
311
  before :each do
312
312
  @index = ThinkingSphinx::Index::Builder.generate(Person) do
313
313
  indexes tags(:name), :as => :tags, :facet => true
314
314
  end
315
-
315
+
316
316
  @source = @index.sources.first
317
317
  end
318
-
318
+
319
319
  after :each do
320
320
  Person.sphinx_facets.delete_at(-1)
321
321
  end
322
-
322
+
323
323
  it "should have one field" do
324
324
  @source.fields.length.should == 1
325
325
  end
326
-
326
+
327
327
  it "should have one attribute alongside the internal ones" do
328
328
  @source.attributes.length.should == 1 + internal_attribute_count
329
329
  end
330
-
330
+
331
331
  it "should set the attribute name to have the _facet suffix" do
332
332
  @source.attributes.last.unique_name.should == :tags_facet
333
333
  end
334
-
334
+
335
335
  it "should set the attribute type to multi" do
336
336
  @source.attributes.last.type.should == :multi
337
337
  end
338
-
338
+
339
339
  it "should set the attribute column to be the same as the field" do
340
340
  @source.attributes.last.columns.length.should == 1
341
341
  @source.attributes.last.columns.first.__name.should == :name
342
342
  end
343
343
  end
344
-
344
+
345
345
  describe "no fields" do
346
346
  it "should raise an exception" do
347
347
  lambda {
@@ -351,7 +351,7 @@ describe ThinkingSphinx::Index::Builder do
351
351
  }.should raise_error
352
352
  end
353
353
  end
354
-
354
+
355
355
  describe "explicit source" do
356
356
  before :each do
357
357
  @index = ThinkingSphinx::Index::Builder.generate(Person) do
@@ -359,38 +359,38 @@ describe ThinkingSphinx::Index::Builder do
359
359
  indexes first_name, last_name
360
360
  has birthday
361
361
  has id, :as => :internal_id
362
-
362
+
363
363
  set_property :delta => true
364
-
364
+
365
365
  where "birthday <= NOW()"
366
366
  group_by "first_name"
367
367
  end
368
368
  end
369
-
369
+
370
370
  @source = @index.sources.first
371
371
  end
372
-
372
+
373
373
  it "should return an index" do
374
374
  @index.should be_a_kind_of(ThinkingSphinx::Index)
375
375
  end
376
-
376
+
377
377
  it "should have one source for the index" do
378
378
  @index.sources.length.should == 1
379
379
  end
380
-
380
+
381
381
  it "should have two fields" do
382
382
  @source.fields.length.should == 2
383
383
  @source.fields[0].unique_name.should == :first_name
384
384
  @source.fields[1].unique_name.should == :last_name
385
385
  end
386
-
386
+
387
387
  it "should have two attributes alongside the internal ones" do
388
388
  @source.attributes.length.should == 2 + internal_attribute_count
389
389
  @source.attributes[internal_attribute_count].unique_name.should == :birthday
390
390
  @source.attributes[1 + internal_attribute_count].unique_name.should == :internal_id
391
391
  end
392
392
  end
393
-
393
+
394
394
  describe "multiple sources" do
395
395
  before :each do
396
396
  @index = ThinkingSphinx::Index::Builder.generate(Person) do
@@ -398,104 +398,125 @@ describe ThinkingSphinx::Index::Builder do
398
398
  indexes first_name
399
399
  has birthday
400
400
  end
401
-
401
+
402
402
  define_source do
403
403
  indexes last_name
404
404
  has :id, :as => :internal_id
405
405
  end
406
406
  end
407
407
  end
408
-
408
+
409
409
  it "should have two sources" do
410
410
  @index.sources.length.should == 2
411
411
  end
412
-
412
+
413
413
  it "should have two fields" do
414
414
  @index.fields.length.should == 2
415
415
  end
416
-
416
+
417
417
  it "should have one field in each source" do
418
418
  @index.sources.each do |source|
419
419
  source.fields.length.should == 1
420
420
  end
421
421
  end
422
-
422
+
423
423
  it "should have two attributes alongside the six internal ones" do
424
424
  @index.attributes.length.should == 2 + (internal_attribute_count * 2)
425
425
  end
426
-
426
+
427
427
  it "should have one attribute in each source alongside the internal ones" do
428
428
  @index.sources.each do |source|
429
429
  source.attributes.length.should == 1 + internal_attribute_count
430
430
  end
431
431
  end
432
432
  end
433
-
433
+
434
+ describe "multiple local indexes" do
435
+ before :each do
436
+ @index = ThinkingSphinx::Index::Builder.generate(Person) do
437
+ indexes first_name
438
+
439
+ use_local_index :other_local_index_1
440
+ use_local_indices "other_local_index_2", "other_local_index_3"
441
+ end
442
+ end
443
+
444
+ it "should have three additional indexes" do
445
+ @index.additional_indices.length.should == 3
446
+ end
447
+
448
+ it "should append _core to the name of each local index" do
449
+ @index.additional_indices[0].should eql("other_local_index_1_core")
450
+ @index.additional_indices[1].should eql("other_local_index_2_core")
451
+ @index.additional_indices[2].should eql("other_local_index_3_core")
452
+ end
453
+ end
454
+
434
455
  describe "index options" do
435
456
  before :each do
436
457
  @index = ThinkingSphinx::Index::Builder.generate(Person) do
437
458
  indexes first_name
438
-
459
+
439
460
  set_property :charset_type => "utf16"
440
461
  set_property :group_concat_max_len => 1024
441
462
  end
442
463
  end
443
-
464
+
444
465
  it "should store the index setting for the index" do
445
466
  @index.local_options[:charset_type].should == "utf16"
446
467
  end
447
-
468
+
448
469
  it "should store non-Sphinx settings for the index" do
449
470
  @index.local_options[:group_concat_max_len].should == 1024
450
471
  end
451
472
  end
452
-
473
+
453
474
  describe "delta options" do
454
475
  before :each do
455
476
  @index = ThinkingSphinx::Index::Builder.generate(Person) do
456
477
  indexes first_name
457
-
478
+
458
479
  set_property :delta => true
459
480
  end
460
481
  end
461
-
482
+
462
483
  it "should not keep the delta setting in source options" do
463
484
  @index.sources.first.options.should be_empty
464
485
  end
465
-
486
+
466
487
  it "should not keep the delta setting in index options" do
467
488
  @index.local_options.should be_empty
468
489
  end
469
-
490
+
470
491
  it "should set the index delta object set" do
471
492
  @index.delta_object.should be_a_kind_of(ThinkingSphinx::Deltas::DefaultDelta)
472
493
  end
473
494
  end
474
-
495
+
475
496
  context 'index options' do
476
497
  before :each do
477
498
  @index = ThinkingSphinx::Index::Builder.generate(Person) do
478
499
  indexes first_name
479
-
500
+
480
501
  set_property :index_exact_words => true
481
502
  end
482
503
  end
483
-
504
+
484
505
  it "should track the index_exact_words option to the index" do
485
506
  @index.local_options[:index_exact_words].should be_true
486
507
  end
487
508
  end
488
-
509
+
489
510
  context 'with an explicit name' do
490
511
  it "should set the index's name using the provided value" do
491
512
  index = ThinkingSphinx::Index::Builder.generate(Person, 'custom') do
492
513
  indexes first_name
493
514
  end
494
-
515
+
495
516
  index.name.should == 'custom'
496
517
  end
497
518
  end
498
-
519
+
499
520
  describe "sanitize_sql" do
500
521
  def index
501
522
  @index ||= ThinkingSphinx::Index::Builder.generate(Person) do
@@ -503,7 +524,7 @@ describe ThinkingSphinx::Index::Builder do
503
524
  where sanitize_sql(["gender = ?", "female"])
504
525
  end
505
526
  end
506
-
527
+
507
528
  it "should be aliased to ActiveRecord::Base.sanitize_sql" do
508
529
  index.sources.first.conditions.first.should == index.model.send(:sanitize_sql, ["gender = ?", "female"])
509
530
  end