freelancing-god-thinking-sphinx 0.9.12 → 0.9.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/README +2 -0
  2. data/lib/thinking_sphinx.rb +21 -2
  3. data/lib/thinking_sphinx/active_record.rb +82 -0
  4. data/lib/thinking_sphinx/active_record/delta.rb +2 -1
  5. data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +55 -56
  6. data/lib/thinking_sphinx/attribute.rb +18 -17
  7. data/lib/thinking_sphinx/collection.rb +18 -4
  8. data/lib/thinking_sphinx/configuration.rb +71 -131
  9. data/lib/thinking_sphinx/field.rb +3 -1
  10. data/lib/thinking_sphinx/index.rb +93 -69
  11. data/lib/thinking_sphinx/index/builder.rb +8 -4
  12. data/lib/thinking_sphinx/search.rb +184 -25
  13. data/spec/unit/thinking_sphinx/active_record/delta_spec.rb +11 -7
  14. data/spec/unit/thinking_sphinx/active_record_spec.rb +1 -62
  15. data/spec/unit/thinking_sphinx/attribute_spec.rb +0 -148
  16. data/spec/unit/thinking_sphinx/collection_spec.rb +9 -66
  17. data/spec/unit/thinking_sphinx/configuration_spec.rb +17 -393
  18. data/spec/unit/thinking_sphinx/field_spec.rb +0 -79
  19. data/spec/unit/thinking_sphinx/index/builder_spec.rb +1 -30
  20. data/spec/unit/thinking_sphinx/index/faux_column_spec.rb +1 -39
  21. data/spec/unit/thinking_sphinx/index_spec.rb +0 -263
  22. data/spec/unit/thinking_sphinx/search_spec.rb +30 -174
  23. data/spec/unit/thinking_sphinx_spec.rb +16 -31
  24. data/vendor/riddle/lib/riddle.rb +5 -5
  25. data/vendor/riddle/lib/riddle/client.rb +5 -25
  26. data/vendor/riddle/lib/riddle/configuration.rb +33 -0
  27. data/vendor/riddle/lib/riddle/configuration/distributed_index.rb +48 -0
  28. data/vendor/riddle/lib/riddle/configuration/index.rb +142 -0
  29. data/vendor/riddle/lib/riddle/configuration/indexer.rb +19 -0
  30. data/vendor/riddle/lib/riddle/configuration/remote_index.rb +17 -0
  31. data/vendor/riddle/lib/riddle/configuration/searchd.rb +25 -0
  32. data/vendor/riddle/lib/riddle/configuration/section.rb +32 -0
  33. data/vendor/riddle/lib/riddle/configuration/source.rb +23 -0
  34. data/vendor/riddle/lib/riddle/configuration/sql_source.rb +34 -0
  35. data/vendor/riddle/lib/riddle/configuration/xml_source.rb +28 -0
  36. data/vendor/riddle/lib/riddle/controller.rb +44 -0
  37. metadata +14 -7
data/README CHANGED
@@ -92,3 +92,5 @@ Since I first released this library, there's been quite a few people who have su
92
92
  - Jim Remsik
93
93
  - Kennon Ballou
94
94
  - Henrik Nyh
95
+ - Emil Tin
96
+ - Doug Cole
@@ -30,7 +30,7 @@ module ThinkingSphinx
30
30
  module Version #:nodoc:
31
31
  Major = 0
32
32
  Minor = 9
33
- Tiny = 12
33
+ Tiny = 13
34
34
 
35
35
  String = [Major, Minor, Tiny].join('.')
36
36
  end
@@ -40,6 +40,15 @@ module ThinkingSphinx
40
40
  class ConnectionError < StandardError
41
41
  end
42
42
 
43
+ # A StaleIdsException is thrown by Collection.instances_from_matches if there
44
+ # are records in Sphinx but not in the database, so the search can be retried.
45
+ class StaleIdsException < StandardError
46
+ attr_accessor :ids
47
+ def initialize(ids)
48
+ self.ids = ids
49
+ end
50
+ end
51
+
43
52
  # The collection of indexed models. Keep in mind that Rails lazily loads
44
53
  # its classes, so this may not actually be populated with _all_ the models
45
54
  # that have Sphinx indexes.
@@ -97,6 +106,16 @@ module ThinkingSphinx
97
106
  @@updates_enabled = value
98
107
  end
99
108
 
109
+ @@suppress_delta_output = false
110
+
111
+ def self.suppress_delta_output?
112
+ @@suppress_delta_output
113
+ end
114
+
115
+ def self.suppress_delta_output=(value)
116
+ @@suppress_delta_output = value
117
+ end
118
+
100
119
  # Checks to see if MySQL will allow simplistic GROUP BY statements. If not,
101
120
  # or if not using MySQL, this will return false.
102
121
  #
@@ -113,7 +132,7 @@ module ThinkingSphinx
113
132
  def self.sphinx_running?
114
133
  pid_file = ThinkingSphinx::Configuration.instance.pid_file
115
134
 
116
- if File.exists?(pid_file)
135
+ if pid_file && File.exists?(pid_file)
117
136
  pid = `cat #{pid_file}`[/\d+/]
118
137
  `ps -p #{pid} | wc -l`.to_i > 1
119
138
  else
@@ -83,6 +83,10 @@ module ThinkingSphinx
83
83
  end
84
84
  alias_method :sphinx_index, :define_index
85
85
 
86
+ def sphinx_index_options
87
+ sphinx_indexes.last.options
88
+ end
89
+
86
90
  # Generate a unique CRC value for the model's name, to use to
87
91
  # determine which Sphinx documents belong to which AR records.
88
92
  #
@@ -115,6 +119,82 @@ module ThinkingSphinx
115
119
 
116
120
  return parent
117
121
  end
122
+
123
+ def to_riddle(offset)
124
+ ThinkingSphinx::AbstractAdapter.detect(self).setup
125
+
126
+ indexes = [to_riddle_for_core(offset)]
127
+ indexes << to_riddle_for_delta(offset) if sphinx_delta?
128
+ indexes << to_riddle_for_distributed
129
+ end
130
+
131
+ private
132
+
133
+ def sphinx_name
134
+ self.name.underscore.tr(':/\\', '_')
135
+ end
136
+
137
+ def sphinx_delta?
138
+ self.sphinx_indexes.any? { |index| index.delta? }
139
+ end
140
+
141
+ def to_riddle_for_core(offset)
142
+ index = Riddle::Configuration::Index.new("#{sphinx_name}_core")
143
+ index.path = File.join(
144
+ ThinkingSphinx::Configuration.instance.searchd_file_path, index.name
145
+ )
146
+
147
+ set_configuration_options_for_indexes index
148
+ set_field_settings_for_indexes index
149
+
150
+ self.sphinx_indexes.select { |ts_index|
151
+ ts_index.model == self
152
+ }.each_with_index do |ts_index, i|
153
+ index.sources << ts_index.to_riddle_for_core(offset, i)
154
+ end
155
+
156
+ index
157
+ end
158
+
159
+ def to_riddle_for_delta(offset)
160
+ index = Riddle::Configuration::Index.new("#{sphinx_name}_delta")
161
+ index.parent = "#{sphinx_name}_core"
162
+ index.path = File.join(ThinkingSphinx::Configuration.instance.searchd_file_path, index.name)
163
+
164
+ self.sphinx_indexes.each_with_index do |ts_index, i|
165
+ index.sources << ts_index.to_riddle_for_delta(offset, i) if ts_index.delta?
166
+ end
167
+
168
+ index
169
+ end
170
+
171
+ def to_riddle_for_distributed
172
+ index = Riddle::Configuration::DistributedIndex.new(sphinx_name)
173
+ index.local_indexes << "#{sphinx_name}_core"
174
+ index.local_indexes.unshift "#{sphinx_name}_delta" if sphinx_delta?
175
+ index
176
+ end
177
+
178
+ def set_configuration_options_for_indexes(index)
179
+ ThinkingSphinx::Configuration.instance.index_options.each do |key, value|
180
+ index.send("#{key}=".to_sym, value)
181
+ end
182
+
183
+ self.sphinx_indexes.each do |ts_index|
184
+ ts_index.options.each do |key, value|
185
+ index.send("#{key}=".to_sym, value) if ThinkingSphinx::Configuration::IndexOptions.include?(key.to_s) && !value.nil?
186
+ end
187
+ end
188
+ end
189
+
190
+ def set_field_settings_for_indexes(index)
191
+ field_names = lambda { |field| field.unique_name.to_s }
192
+
193
+ self.sphinx_indexes.each do |ts_index|
194
+ index.prefix_field_names += ts_index.prefix_fields.collect(&field_names)
195
+ index.infix_field_names += ts_index.infix_fields.collect(&field_names)
196
+ end
197
+ end
118
198
  end
119
199
  end
120
200
 
@@ -155,6 +235,8 @@ module ThinkingSphinx
155
235
  ) if ThinkingSphinx.deltas_enabled? &&
156
236
  self.class.sphinx_indexes.any? { |index| index.delta? } &&
157
237
  self.delta?
238
+ rescue ::ThinkingSphinx::ConnectionError
239
+ # nothing
158
240
  end
159
241
 
160
242
  def sphinx_document_id
@@ -54,7 +54,8 @@ module ThinkingSphinx
54
54
  {instance.sphinx_document_id => 1}
55
55
  ) if instance && instance.in_core_index?
56
56
 
57
- system "#{config.bin_path}indexer --config #{config.config_file} --rotate #{self.sphinx_indexes.first.name}_delta"
57
+ output = `#{config.bin_path}indexer --config #{config.config_file} --rotate #{self.sphinx_indexes.first.name}_delta`
58
+ puts output unless ThinkingSphinx.suppress_delta_output?
58
59
 
59
60
  true
60
61
  end
@@ -8,76 +8,75 @@ module ThinkingSphinx
8
8
 
9
9
  private
10
10
 
11
- def create_array_accum_function
11
+ def execute(command, output_error = false)
12
12
  connection.execute "begin"
13
13
  connection.execute "savepoint ts"
14
14
  begin
15
- # See http://www.postgresql.org/docs/8.2/interactive/sql-createaggregate.html
16
- if connection.raw_connection.server_version > 80200
17
- connection.execute <<-SQL
18
- CREATE AGGREGATE array_accum (anyelement)
19
- (
20
- sfunc = array_append,
21
- stype = anyarray,
22
- initcond = '{}'
23
- );
24
- SQL
25
- else
26
- connection.execute <<-SQL
27
- CREATE AGGREGATE array_accum
28
- (
29
- basetype = anyelement,
30
- sfunc = array_append,
31
- stype = anyarray,
32
- initcond = '{}'
33
- );
34
- SQL
35
- end
36
- rescue
15
+ connection.execute command
16
+ rescue StandardError => err
17
+ puts err if output_error
37
18
  connection.execute "rollback to savepoint ts"
38
19
  end
39
20
  connection.execute "release savepoint ts"
40
21
  connection.execute "commit"
41
22
  end
42
23
 
24
+ def create_array_accum_function
25
+ if connection.raw_connection.server_version > 80200
26
+ execute <<-SQL
27
+ CREATE AGGREGATE array_accum (anyelement)
28
+ (
29
+ sfunc = array_append,
30
+ stype = anyarray,
31
+ initcond = '{}'
32
+ );
33
+ SQL
34
+ else
35
+ execute <<-SQL
36
+ CREATE AGGREGATE array_accum
37
+ (
38
+ basetype = anyelement,
39
+ sfunc = array_append,
40
+ stype = anyarray,
41
+ initcond = '{}'
42
+ );
43
+ SQL
44
+ end
45
+ end
46
+
43
47
  def create_crc32_function
44
- connection.execute "begin"
45
- connection.execute "savepoint ts"
46
- begin
47
- connection.execute "CREATE LANGUAGE 'plpgsql';"
48
- connection.execute <<-SQL
49
- CREATE OR REPLACE FUNCTION crc32(word text)
50
- RETURNS bigint AS $$
51
- DECLARE tmp bigint;
52
- DECLARE i int;
53
- DECLARE j int;
54
- BEGIN
55
- i = 0;
56
- tmp = 4294967295;
48
+ execute "CREATE LANGUAGE 'plpgsql';"
49
+ function = <<-SQL
50
+ CREATE OR REPLACE FUNCTION crc32(word text)
51
+ RETURNS bigint AS $$
52
+ DECLARE tmp bigint;
53
+ DECLARE i int;
54
+ DECLARE j int;
55
+ DECLARE word_array bytea;
56
+ BEGIN
57
+ i = 0;
58
+ tmp = 4294967295;
59
+ word_array = decode(replace(word, E'\\\\', E'\\\\\\\\'), 'escape');
60
+ LOOP
61
+ tmp = (tmp # get_byte(word_array, i))::bigint;
62
+ i = i + 1;
63
+ j = 0;
57
64
  LOOP
58
- tmp = (tmp # get_byte(word::bytea, i))::bigint;
59
- i = i + 1;
60
- j = 0;
61
- LOOP
62
- tmp = ((tmp >> 1) # (3988292384 * (tmp & 1)))::bigint;
63
- j = j + 1;
64
- IF j >= 8 THEN
65
- EXIT;
66
- END IF;
67
- END LOOP;
68
- IF i >= char_length(word) THEN
65
+ tmp = ((tmp >> 1) # (3988292384 * (tmp & 1)))::bigint;
66
+ j = j + 1;
67
+ IF j >= 8 THEN
69
68
  EXIT;
70
69
  END IF;
71
70
  END LOOP;
72
- return (tmp # 4294967295);
73
- END
74
- $$ IMMUTABLE STRICT LANGUAGE plpgsql;
75
- SQL
76
- rescue
77
- connection.execute "rollback to savepoint ts"
78
- end
79
- connection.execute "release savepoint ts"
80
- connection.execute "commit"
71
+ IF i >= char_length(word) THEN
72
+ EXIT;
73
+ END IF;
74
+ END LOOP;
75
+ return (tmp # 4294967295);
76
+ END
77
+ $$ IMMUTABLE STRICT LANGUAGE plpgsql;
78
+ SQL
79
+ execute function, true
81
80
  end
82
81
  end
83
82
  end
@@ -101,23 +101,22 @@ module ThinkingSphinx
101
101
  end
102
102
  end
103
103
 
104
- # Generates the appropriate attribute statement for a Sphinx configuration
105
- # file, depending on the attribute's type.
106
- #
107
- def to_sphinx_clause
108
- case type
109
- when :multi
110
- "sql_attr_multi = uint #{unique_name} from field"
111
- when :datetime
112
- "sql_attr_timestamp = #{unique_name}"
113
- when :string
114
- "sql_attr_str2ordinal = #{unique_name}"
115
- when :float
116
- "sql_attr_float = #{unique_name}"
117
- when :boolean
118
- "sql_attr_bool = #{unique_name}"
104
+ def type_to_config
105
+ {
106
+ :multi => :sql_attr_multi,
107
+ :datetime => :sql_attr_timestamp,
108
+ :string => :sql_attr_str2ordinal,
109
+ :float => :sql_attr_float,
110
+ :boolean => :sql_attr_bool,
111
+ :integer => :sql_attr_uint
112
+ }[type]
113
+ end
114
+
115
+ def config_value
116
+ if type == :multi
117
+ "uint #{unique_name} from field"
119
118
  else
120
- "sql_attr_uint = #{unique_name}"
119
+ unique_name
121
120
  end
122
121
  end
123
122
 
@@ -141,7 +140,9 @@ module ThinkingSphinx
141
140
  when "ActiveRecord::ConnectionAdapters::MysqlAdapter"
142
141
  "CONCAT_WS('#{separator}', #{clause})"
143
142
  when "ActiveRecord::ConnectionAdapters::PostgreSQLAdapter"
144
- clause.split(', ').join(" || '#{separator}' || ")
143
+ clause.split(', ').collect { |attribute|
144
+ "COALESCE(#{attribute}, '')"
145
+ }.join(" || ' ' || ")
145
146
  else
146
147
  clause
147
148
  end
@@ -1,7 +1,10 @@
1
1
  module ThinkingSphinx
2
2
  class Collection < ::Array
3
- attr_reader :total_entries, :total_pages, :current_page
3
+ attr_reader :total_entries, :total_pages, :current_page, :per_page
4
4
  attr_accessor :results
5
+
6
+ # Compatibility with older versions of will_paginate
7
+ alias_method :page_count, :total_pages
5
8
 
6
9
  def initialize(page, per_page, entries, total_entries)
7
10
  @current_page, @per_page, @total_entries = page, per_page, total_entries
@@ -34,25 +37,36 @@ module ThinkingSphinx
34
37
  instance_from_match match, options
35
38
  } unless klass = options[:class]
36
39
 
40
+ index_options = klass.sphinx_index_options
41
+
37
42
  ids = matches.collect { |match| match[:attributes]["sphinx_internal_id"] }
38
43
  instances = ids.length > 0 ? klass.find(
39
44
  :all,
40
45
  :conditions => {klass.primary_key.to_sym => ids},
41
- :include => options[:include],
42
- :select => options[:select]
46
+ :include => (options[:include] || index_options[:include]),
47
+ :select => (options[:select] || index_options[:select])
43
48
  ) : []
49
+
50
+ # Raise an exception if we find records in Sphinx but not in the DB, so the search method
51
+ # can retry without them. See ThinkingSphinx::Search.retry_search_on_stale_index.
52
+ if options[:raise_on_stale] && instances.length < ids.length
53
+ stale_ids = ids - instances.map {|i| i.id }
54
+ raise StaleIdsException, stale_ids
55
+ end
56
+
44
57
  ids.collect { |obj_id|
45
58
  instances.detect { |obj| obj.id == obj_id }
46
59
  }
47
60
  end
48
61
 
49
62
  def self.instance_from_match(match, options)
50
- # puts "ARGS: #{match[:attributes]["sphinx_internal_id"].inspect}, {:include => #{options[:include].inspect}, :select => #{options[:select].inspect}}"
51
63
  class_from_crc(match[:attributes]["class_crc"]).find(
52
64
  match[:attributes]["sphinx_internal_id"],
53
65
  :include => options[:include],
54
66
  :select => options[:select]
55
67
  )
68
+ rescue ::ActiveRecord::RecordNotFound
69
+ nil
56
70
  end
57
71
 
58
72
  def self.class_from_crc(crc)
@@ -52,20 +52,14 @@ module ThinkingSphinx
52
52
  min_infix_len min_prefix_len min_word_len mlock morphology ngram_chars
53
53
  ngram_len phrase_boundary phrase_boundary_step preopen stopwords
54
54
  wordforms )
55
-
56
- IndexerOptions = %w( max_iops max_iosize mem_limit )
57
-
58
- SearchdOptions = %w( read_timeout max_children max_matches seamless_rotate
59
- preopen_indexes unlink_old )
60
-
55
+
61
56
  attr_accessor :config_file, :searchd_log_file, :query_log_file,
62
57
  :pid_file, :searchd_file_path, :address, :port, :allow_star,
63
58
  :database_yml_file, :app_root, :bin_path
64
59
 
65
- attr_accessor :source_options, :index_options, :indexer_options,
66
- :searchd_options
60
+ attr_accessor :source_options, :index_options
67
61
 
68
- attr_reader :environment
62
+ attr_reader :environment, :configuration
69
63
 
70
64
  # Load in the configuration settings - this will look for config/sphinx.yml
71
65
  # and parse it according to the current environment.
@@ -79,14 +73,16 @@ module ThinkingSphinx
79
73
  self.app_root = Merb.root if defined?(Merb)
80
74
  self.app_root ||= app_root
81
75
 
76
+ @configuration = Riddle::Configuration.new
77
+ @configuration.searchd.address = "127.0.0.1"
78
+ @configuration.searchd.port = 3312
79
+ @configuration.searchd.pid_file = "#{self.app_root}/log/searchd.#{environment}.pid"
80
+ @configuration.searchd.log = "#{self.app_root}/log/searchd.log"
81
+ @configuration.searchd.query_log = "#{self.app_root}/log/searchd.query.log"
82
+
82
83
  self.database_yml_file = "#{self.app_root}/config/database.yml"
83
84
  self.config_file = "#{self.app_root}/config/#{environment}.sphinx.conf"
84
- self.searchd_log_file = "#{self.app_root}/log/searchd.log"
85
- self.query_log_file = "#{self.app_root}/log/searchd.query.log"
86
- self.pid_file = "#{self.app_root}/log/searchd.#{environment}.pid"
87
85
  self.searchd_file_path = "#{self.app_root}/db/sphinx/#{environment}"
88
- self.address = "127.0.0.1"
89
- self.port = 3312
90
86
  self.allow_star = false
91
87
  self.bin_path = ""
92
88
 
@@ -95,9 +91,7 @@ module ThinkingSphinx
95
91
  :charset_type => "utf-8",
96
92
  :morphology => "stem_en"
97
93
  }
98
- self.indexer_options = {}
99
- self.searchd_options = {}
100
-
94
+
101
95
  parse_config
102
96
 
103
97
  self
@@ -113,6 +107,10 @@ module ThinkingSphinx
113
107
  self.class.environment
114
108
  end
115
109
 
110
+ def controller
111
+ @controller ||= Riddle::Controller.new(@configuration, self.config_file)
112
+ end
113
+
116
114
  # Generate the config file for Sphinx by using all the settings defined and
117
115
  # looping through all the models with indexes to build the relevant
118
116
  # indexer and searchd configuration, and sources and indexes details.
@@ -120,57 +118,15 @@ module ThinkingSphinx
120
118
  def build(file_path=nil)
121
119
  load_models
122
120
  file_path ||= "#{self.config_file}"
123
- database_confs = YAML::load(ERB.new(IO.read("#{self.database_yml_file}")).result)
124
- database_confs.symbolize_keys!
125
- database_conf = database_confs[environment.to_sym]
126
- database_conf.symbolize_keys!
121
+
122
+ @configuration.indexes.clear
123
+
124
+ ThinkingSphinx.indexed_models.each_with_index do |model, model_index|
125
+ @configuration.indexes.concat model.constantize.to_riddle(model_index)
126
+ end
127
127
 
128
128
  open(file_path, "w") do |file|
129
- file.write <<-CONFIG
130
- indexer
131
- {
132
- #{hash_to_config(self.indexer_options)}
133
- }
134
-
135
- searchd
136
- {
137
- address = #{self.address}
138
- port = #{self.port}
139
- log = #{self.searchd_log_file}
140
- query_log = #{self.query_log_file}
141
- pid_file = #{self.pid_file}
142
- #{hash_to_config(self.searchd_options)}
143
- }
144
- CONFIG
145
-
146
- ThinkingSphinx.indexed_models.each_with_index do |model, model_index|
147
- model = model.constantize
148
- sources = []
149
- delta_sources = []
150
- prefixed_fields = []
151
- infixed_fields = []
152
-
153
- model.sphinx_indexes.select { |index| index.model == model }.each_with_index do |index, i|
154
- file.write index.to_config(model, i, database_conf, model_index)
155
-
156
- index.adapter_object.setup
157
-
158
- sources << "#{ThinkingSphinx::Index.name(model)}_#{i}_core"
159
- delta_sources << "#{ThinkingSphinx::Index.name(model)}_#{i}_delta" if index.delta?
160
- end
161
-
162
- next if sources.empty?
163
-
164
- source_list = sources.collect { |s| "source = #{s}" }.join("\n")
165
- delta_list = delta_sources.collect { |s| "source = #{s}" }.join("\n")
166
-
167
- file.write core_index_for_model(model, source_list)
168
- unless delta_list.blank?
169
- file.write delta_index_for_model(model, delta_list)
170
- end
171
-
172
- file.write distributed_index_for_model(model)
173
- end
129
+ file.write @configuration.render
174
130
  end
175
131
  end
176
132
 
@@ -223,6 +179,46 @@ searchd
223
179
  base
224
180
  end
225
181
 
182
+ def address
183
+ @configuration.searchd.address
184
+ end
185
+
186
+ def address=(address)
187
+ @configuration.searchd.address = address
188
+ end
189
+
190
+ def port
191
+ @configuration.searchd.port
192
+ end
193
+
194
+ def port=(port)
195
+ @configuration.searchd.port = port
196
+ end
197
+
198
+ def pid_file
199
+ @configuration.searchd.pid_file
200
+ end
201
+
202
+ def pid_file=(pid_file)
203
+ @configuration.searchd.pid_file = pid_file
204
+ end
205
+
206
+ def searchd_log_file
207
+ @configuration.searchd.log
208
+ end
209
+
210
+ def searchd_log_file=(file)
211
+ @configuration.searchd.log = file
212
+ end
213
+
214
+ def query_log_file
215
+ @configuration.searchd.query_log
216
+ end
217
+
218
+ def query_log_file=(file)
219
+ @configuration.searchd.query_log = file
220
+ end
221
+
226
222
  private
227
223
 
228
224
  # Parse the config/sphinx.yml file - if it exists - then use the attribute
@@ -237,77 +233,21 @@ searchd
237
233
  conf.each do |key,value|
238
234
  self.send("#{key}=", value) if self.methods.include?("#{key}=")
239
235
 
240
- self.source_options[key.to_sym] = value if SourceOptions.include?(key.to_s)
241
- self.index_options[key.to_sym] = value if IndexOptions.include?(key.to_s)
242
- self.indexer_options[key.to_sym] = value if IndexerOptions.include?(key.to_s)
243
- self.searchd_options[key.to_sym] = value if SearchdOptions.include?(key.to_s)
236
+ set_sphinx_setting self.source_options, key, value, SourceOptions
237
+ set_sphinx_setting self.index_options, key, value, IndexOptions
238
+ set_sphinx_setting @configuration.searchd, key, value
239
+ set_sphinx_setting @configuration.indexer, key, value
244
240
  end unless conf.nil?
245
241
 
246
242
  self.bin_path += '/' unless self.bin_path.blank?
247
243
  end
248
244
 
249
- def core_index_for_model(model, sources)
250
- output = <<-INDEX
251
-
252
- index #{ThinkingSphinx::Index.name(model)}_core
253
- {
254
- #{sources}
255
- path = #{self.searchd_file_path}/#{ThinkingSphinx::Index.name(model)}_core
256
- INDEX
257
-
258
- unless combined_index_options(model).empty?
259
- output += hash_to_config(combined_index_options(model))
260
- end
261
-
262
- if self.allow_star
263
- # Ye Olde way of turning on enable_star
264
- output += " enable_star = 1\n"
265
- output += " min_prefix_len = #{combined_index_options[:min_prefix_len]}\n"
266
- end
267
-
268
- unless model.sphinx_indexes.collect(&:prefix_fields).flatten.empty?
269
- output += " prefix_fields = #{model.sphinx_indexes.collect(&:prefix_fields).flatten.map(&:unique_name).join(', ')}\n"
270
- else
271
- output += " prefix_fields = _\n" unless model.sphinx_indexes.collect(&:infix_fields).flatten.empty?
272
- end
273
-
274
- unless model.sphinx_indexes.collect(&:infix_fields).flatten.empty?
275
- output += " infix_fields = #{model.sphinx_indexes.collect(&:infix_fields).flatten.map(&:unique_name).join(', ')}\n"
245
+ def set_sphinx_setting(object, key, value, allowed = {})
246
+ if object.is_a?(Hash)
247
+ object[key.to_sym] = value if allowed.include?(key.to_s)
276
248
  else
277
- output += " infix_fields = -\n" unless model.sphinx_indexes.collect(&:prefix_fields).flatten.empty?
278
- end
279
-
280
- output + "\n}\n"
281
- end
282
-
283
- def delta_index_for_model(model, sources)
284
- <<-INDEX
285
- index #{ThinkingSphinx::Index.name(model)}_delta : #{ThinkingSphinx::Index.name(model)}_core
286
- {
287
- #{sources}
288
- path = #{self.searchd_file_path}/#{ThinkingSphinx::Index.name(model)}_delta
289
- }
290
- INDEX
291
- end
292
-
293
- def distributed_index_for_model(model)
294
- sources = ["local = #{ThinkingSphinx::Index.name(model)}_core"]
295
- if model.sphinx_indexes.any? { |index| index.delta? }
296
- sources << "local = #{ThinkingSphinx::Index.name(model)}_delta"
297
- end
298
-
299
- <<-INDEX
300
- index #{ThinkingSphinx::Index.name(model)}
301
- {
302
- type = distributed
303
- #{ sources.join("\n ") }
304
- }
305
- INDEX
306
- end
307
-
308
- def combined_index_options(model)
309
- model.sphinx_indexes.inject(self.index_options) do |options, index|
310
- self.class.options_merge(options, index.local_index_options)
249
+ object.send("#{key}=", value) if object.methods.include?("#{key}")
250
+ send("#{key}=", value) if self.methods.include?("#{key}")
311
251
  end
312
252
  end
313
253
  end