0
- class Exception < ::Exception
0
- class ConfigurationError < Exception
0
- class DaemonError < Exception
0
- CONF_PATH = "#{RAILS_ROOT}/config/environments/sphinx.#{RAILS_ENV}.conf"
0
- ENV_BASE_PATH = "#{RAILS_ROOT}/config/environments/sphinx.#{RAILS_ENV}.base"
0
- GENERIC_BASE_PATH = "#{RAILS_ROOT}/config/sphinx.base"
0
- BASE_PATH = (File.exist?(ENV_BASE_PATH) ? ENV_BASE_PATH : GENERIC_BASE_PATH)
0
- raise ConfigurationError, "Please create a #{BASE_PATH} configuration file." unless File.exist? BASE_PATH
0
- def self.options_for(heading)
0
- section = open(BASE_PATH).read[/^#{heading}.*?\{(.*?)\}/m, 1]
0
- raise "missing heading #{heading} in #{BASE_PATH}" if section.nil?
0
- lines = section.split("\n").reject { |l| l.strip.empty? }
0
- options = lines.map do |c|
0
- c =~ /\s*(.*?)\s*=\s*([^\#]*)/
0
- $1 ? [$1, $2.strip] : []
0
- Hash[*options.flatten]
0
- sql_query_pre = SET SESSION group_concat_max_len = 65535
0
- sql_query_pre = SET NAMES utf8
0
- sql_range_step = 20000
0
- COLUMN_TYPES = {:string => 'text', :text => 'text', :integer => 'numeric', :date => 'date', :datetime => 'date' }
0
- CONFIG_MAP = {:username => 'sql_user',
0
- :password => 'sql_pass',
0
- :database => 'sql_db',
0
- :socket => 'sql_sock'}
0
- OPTIONAL_SPHINX_KEYS = ['morphology', 'stopwords', 'min_word_len', 'charset_type', 'charset_table', 'docinfo']
0
- PLUGIN_SETTINGS = options_for('ultrasphinx')
0
- DAEMON_SETTINGS = options_for('searchd')
0
- MAX_WORDS = 2**16 # maximum number of stopwords built
0
- STOPWORDS_PATH = "#{Ultrasphinx::PLUGIN_SETTINGS['path']}/stopwords.txt}"
0
- #logger.debug "Ultrasphinx options are: #{PLUGIN_SETTINGS.inspect}"
0
- Dir["#{RAILS_ROOT}/app/models/**/*.rb"].each do |filename|
0
- next if filename =~ /\/(\.svn|CVS|\.bzr)\//
0
- open(filename) {|file| load filename if file.grep(/is_indexed/).any?}
0
- puts "Ultrasphinx: warning; autoload error on #{filename}"
0
- Fields.instance.configure(MODELS_HASH)
0
- puts "Rebuilding Ultrasphinx configurations for #{ENV['RAILS_ENV']} environment"
0
- puts "Available models are #{MODELS_HASH.keys.to_sentence}"
0
- File.open(CONF_PATH, "w") do |conf|
0
- conf.puts "\n# Auto-generated at #{Time.now}.\n# Hand modifications will be overwritten.\n"
0
- conf.puts "\n# #{BASE_PATH}"
0
- conf.puts open(BASE_PATH).read.sub(/^ultrasphinx.*?\{.*?\}/m, '') + "\n"
0
- index_list = {"complete" => []}
0
- conf.puts "\n# Source configuration\n\n"
0
- MODELS_HASH.each_with_index do |model_options, class_id|
0
- model, options = model_options
0
- klass, source = model.constantize, model.tableize
0
-# puts "SQL for #{model}"
0
- index_list[source] = [source]
0
- index_list["complete"] << source
0
- conf.puts "source #{source}\n{"
0
- conf.puts SOURCE_DEFAULTS
0
- klass.connection.instance_variable_get("@config").each do |key, value|
0
- conf.puts "#{CONFIG_MAP[key]} = #{value}" if CONFIG_MAP[key]
0
- table, pkey = klass.table_name, klass.primary_key
0
- condition_strings, join_strings = Array(options[:conditions]).map{|condition| "(#{condition})"}, []
0
- column_strings = ["(#{table}.#{pkey} * #{MODELS_HASH.size} + #{class_id}) AS id",
0
- "#{class_id} AS class_id", "'#{klass.name}' AS class"]
0
- remaining_columns = Fields.instance.keys - ["class", "class_id"]
0
- conf.puts "\nsql_query_range = SELECT MIN(#{pkey}), MAX(#{pkey}) FROM #{table}"
0
- options[:fields].to_a.each do |f|
0
- column, as = f.is_a?(Hash) ? [f[:field], f[:as]] : [f, f]
0
- column_strings << Fields.instance.cast("#{table}.#{column}", as)
0
- remaining_columns.delete(as)
0
- options[:includes].to_a.each do |join|
0
- join_klass = join[:model].constantize
0
- association = klass.reflect_on_association(join[:model].underscore.to_sym)
0
- join_strings << "LEFT OUTER JOIN #{join_klass.table_name} ON " +
0
- if (macro = association.macro) == :belongs_to
0
- "#{join_klass.table_name}.#{join_klass.primary_key} = #{table}.#{association.primary_key_name}"
0
- elsif macro == :has_one
0
- "#{table}.#{klass.primary_key} = #{join_klass.table_name}.#{association.instance_variable_get('@foreign_key_name')}"
0
- raise ConfigurationError, "Unidentified association macro #{macro.inspect}"
0
- column_strings << "#{join_klass.table_name}.#{join[:field]} AS #{join[:as] or join[:field]}"
0
- remaining_columns.delete(join[:as] || join[:field])
0
- options[:concats].to_a.select{|concat| concat[:model] and concat[:field]}.each do |group|
0
- # only has_many's right now
0
- join_klass = group[:model].constantize
0
- association = klass.reflect_on_association(group[:association_name] ? group[:association_name].to_sym : group[:model].underscore.pluralize.to_sym)
0
- join_strings << "LEFT OUTER JOIN #{join_klass.table_name} ON #{table}.#{klass.primary_key} = #{join_klass.table_name}.#{association.primary_key_name}" + (" AND (#{group[:conditions]})" if group[:conditions]).to_s # XXX make sure foreign key is right for polymorphic relationships
0
- column_strings << Fields.instance.cast("GROUP_CONCAT(#{join_klass.table_name}.#{group[:field]} SEPARATOR ' ')", group[:as])
0
- remaining_columns.delete(group[:as])
0
- options[:concats].to_a.select{|concat| concat[:fields]}.each do |concat|
0
- column_strings << Fields.instance.cast("CONCAT_WS(' ', #{concat[:fields].map{|field| "#{table}.#{field}"}.join(', ')})", concat[:as])
0
- remaining_columns.delete(concat[:as])
0
-# puts "#{model} has #{remaining_columns.inspect} remaining"
0
- remaining_columns.each do |field|
0
- column_strings << Fields.instance.null(field)
0
- query_strings = ["SELECT", column_strings.sort_by do |string|
0
- # sphinx wants them always in the same order, but "id" must be first
0
- (field = string[/.*AS (.*)/, 1]) == "id" ? "*" : field
0
- query_strings << "FROM #{table}"
0
- query_strings += join_strings.uniq
0
- query_strings << "WHERE #{table}.#{pkey} >= $start AND #{table}.#{pkey} <= $end"
0
- query_strings += condition_strings.uniq.map{|s| "AND #{s}"}
0
- query_strings << "GROUP BY id"
0
- conf.puts "sql_query = #{query_strings.join(" ")}"
0
- # group and date sorting params... this really only would have to be run once
0
- Fields.instance.each do |field, type|
0
- groups << "sql_group_column = #{field}"
0
- groups << "sql_date_column = #{field}"
0
- conf.puts "\n" + groups.sort_by{|s| s[/= (.*)/, 1]}.join("\n")
0
- conf.puts "\nsql_query_info = SELECT * FROM #{table} WHERE #{table}.#{pkey} = (($id - #{class_id}) / #{MODELS_HASH.size})"
0
- conf.puts "\n# Index configuration\n\n"
0
- index_list.to_a.sort_by {|x| x.first == "complete" ? 1 : 0}.each do |name, source_list|
0
- conf.puts "index #{name}\n{"
0
- source_list.each {|source| conf.puts "source = #{source}"}
0
- OPTIONAL_SPHINX_KEYS.each do |key|
0
- conf.puts "#{key} = #{PLUGIN_SETTINGS[key]}" if PLUGIN_SETTINGS[key]
0
- conf.puts "path = #{PLUGIN_SETTINGS["path"]}/sphinx_index_#{name}"
0
+require 'ultrasphinx/core_extensions'
0
+require 'ultrasphinx/ultrasphinx'
0
+require 'ultrasphinx/autoload'
0
+require 'ultrasphinx/fields'
0
+require 'ultrasphinx/is_indexed'
0
+require 'ultrasphinx/search'
0
+require 'ultrasphinx/spell'
Comments
No one has commented yet.