class ThinkingSphinx::Configuration

This class both keeps track of the configuration settings for Sphinx and also generates the resulting file for Sphinx to use.

Here are the default settings, relative to Rails.root where relevant:

config file

config/#{environment}.sphinx.conf

searchd log file

log/searchd.log

query log file

log/searchd.query.log

pid file

log/searchd.#{environment}.pid

searchd files

db/sphinx/#{environment}/

address

127.0.0.1

port

9312

allow star

false

stop timeout

5

min prefix length

1

min infix length

1

mem limit

64M

max matches

1000

morphology

nil

charset type

utf-8

charset table

nil

ignore chars

nil

html strip

false

html remove elements

''

#searchd_binary_name

searchd

#indexer_binary_name

indexer

#hard_retry_count

0

If you want to change these settings, create a YAML file at config/sphinx.yml with settings for each environment, in a similar fashion to database.yml - using the following keys: #config_file, #searchd_log_file, #query_log_file, #pid_file, #searchd_file_path, port, #allow_star, enable_star, min_prefix_len, min_infix_len, mem_limit, max_matches, morphology, charset_type, charset_table, ignore_chars, html_strip, html_remove_elements, #delayed_job_priority, #searchd_binary_name, indexer_binary_name.

I think you've got the idea.

Each setting in the YAML file is optional - so only put in the ones you want to change.

Keep in mind, if for some particular reason you're using a version of Sphinx older than 0.9.8 r871 (that's prior to the proper 0.9.8 release), don't set #allow_star to true.

Constants

CustomOptions
IndexOptions
SourceOptions

Attributes

allow_star[RW]
app_root[RW]
configuration[R]
controller[R]
delayed_job_priority[RW]
hard_retry_count[RW]
index_options[RW]
indexed_models[RW]
model_directories[RW]
searchd_file_path[RW]
shuffle[RW]
source_options[RW]
stop_timeout[RW]
timeout[RW]
touched_reindex_file[RW]
use_64_bit[RW]
version[RW]

Public Class Methods

configure() { |instance| ... } click to toggle source
# File lib/thinking_sphinx/configuration.rb, line 84
def self.configure(&block)
  yield instance
  instance.reset(instance.app_root)
end
environment() click to toggle source
# File lib/thinking_sphinx/configuration.rb, line 134
def self.environment
  @@environment ||= if defined?(Merb)
    Merb.environment
  elsif defined?(Rails)
    Rails.env
  elsif defined?(Sinatra)
    Sinatra::Application.environment.to_s
  else
    ENV['RAILS_ENV'] || 'development'
  end
end
new(app_root = Dir.pwd) click to toggle source

Load in the configuration settings - this will look for config/sphinx.yml and parse it according to the current environment.

# File lib/thinking_sphinx/configuration.rb, line 80
def initialize(app_root = Dir.pwd)
  self.reset
end
reset_environment() click to toggle source
# File lib/thinking_sphinx/configuration.rb, line 146
def self.reset_environment
  ThinkingSphinx.mutex.synchronize do
    @@environment = nil
  end
end

Public Instance Methods

address() click to toggle source
# File lib/thinking_sphinx/configuration.rb, line 182
def address
  @address
end
address=(address) click to toggle source
# File lib/thinking_sphinx/configuration.rb, line 186
def address=(address)
  @address = address
  @configuration.searchd.address = address
end
bin_path() click to toggle source
# File lib/thinking_sphinx/configuration.rb, line 240
def bin_path
  @controller.bin_path
end
bin_path=(path) click to toggle source
# File lib/thinking_sphinx/configuration.rb, line 244
def bin_path=(path)
  @controller.bin_path = path
end
build(file_path=nil) click to toggle source

Generate the config file for Sphinx by using all the settings defined and looping through all the models with indexes to build the relevant indexer and searchd configuration, and sources and indexes details.

# File lib/thinking_sphinx/configuration.rb, line 172
def build(file_path=nil)
  file_path ||= "#{self.config_file}"

  generate

  open(file_path, "w") do |file|
    file.write @configuration.render
  end
end
client() click to toggle source
# File lib/thinking_sphinx/configuration.rb, line 266
def client
  client = Riddle::Client.new shuffled_addresses, port,
    configuration.searchd.client_key
  client.max_matches = configuration.searchd.max_matches || 1000
  client.timeout = timeout || 0
  client
end
config_file() click to toggle source
# File lib/thinking_sphinx/configuration.rb, line 232
def config_file
  @controller.path
end
config_file=(file) click to toggle source
# File lib/thinking_sphinx/configuration.rb, line 236
def config_file=(file)
  @controller.path = file
end
environment() click to toggle source
# File lib/thinking_sphinx/configuration.rb, line 152
def environment
  self.class.environment
end
generate() click to toggle source
# File lib/thinking_sphinx/configuration.rb, line 156
def generate
  @configuration.indices.clear

  ThinkingSphinx.context.indexed_models.each do |model|
    model = model.constantize
    model.define_indexes
    @configuration.indices.concat model.to_riddle

    enforce_common_attribute_types
  end
end
indexer_binary_name() click to toggle source
# File lib/thinking_sphinx/configuration.rb, line 256
def indexer_binary_name
  @controller.indexer_binary_name
end
indexer_binary_name=(name) click to toggle source
# File lib/thinking_sphinx/configuration.rb, line 260
def indexer_binary_name=(name)
  @controller.indexer_binary_name = name
end
models_by_crc() click to toggle source
# File lib/thinking_sphinx/configuration.rb, line 274
def models_by_crc
  @models_by_crc ||= begin
    ThinkingSphinx.context.indexed_models.inject({}) do |hash, model|
      hash[model.constantize.to_crc32] = model
      model.constantize.descendants.each { |subclass|
        hash[subclass.to_crc32] = subclass.name
      }
      hash
    end
  end
end
pid_file() click to toggle source
# File lib/thinking_sphinx/configuration.rb, line 208
def pid_file
  @configuration.searchd.pid_file
end
pid_file=(pid_file) click to toggle source
# File lib/thinking_sphinx/configuration.rb, line 212
def pid_file=(pid_file)
  @configuration.searchd.pid_file = pid_file
end
port() click to toggle source
# File lib/thinking_sphinx/configuration.rb, line 191
def port
  @port
end
port=(port) click to toggle source
# File lib/thinking_sphinx/configuration.rb, line 195
def port=(port)
  @port = port
  @configuration.searchd.port = port
end
query_log_file() click to toggle source
# File lib/thinking_sphinx/configuration.rb, line 224
def query_log_file
  @configuration.searchd.query_log
end
query_log_file=(file) click to toggle source
# File lib/thinking_sphinx/configuration.rb, line 228
def query_log_file=(file)
  @configuration.searchd.query_log = file
end
reset(custom_app_root=nil) click to toggle source
# File lib/thinking_sphinx/configuration.rb, line 89
def reset(custom_app_root=nil)
  if custom_app_root
    self.app_root = custom_app_root
  else
    self.app_root   = Merb.root                  if defined?(Merb)
    self.app_root   = Sinatra::Application.root  if defined?(Sinatra)
    self.app_root   = Rails.root                 if defined?(Rails)
    self.app_root ||= app_root
  end

  @configuration = Riddle::Configuration.new
  @configuration.searchd.pid_file   = "#{self.app_root}/log/searchd.#{environment}.pid"
  @configuration.searchd.log        = "#{self.app_root}/log/searchd.log"
  @configuration.searchd.query_log  = "#{self.app_root}/log/searchd.query.log"

  @controller = Riddle::Controller.new @configuration,
    "#{self.app_root}/config/#{environment}.sphinx.conf"

  self.address              = "127.0.0.1"
  self.port                 = 9312
  self.searchd_file_path    = "#{self.app_root}/db/sphinx/#{environment}"
  self.allow_star           = false
  self.stop_timeout         = 5
  self.model_directories    = initial_model_directories
  self.delayed_job_priority = 0
  self.indexed_models       = []
  self.shuffle              = false
  self.hard_retry_count     = 0

  self.source_options  = {}
  self.index_options   = {
    :charset_type => "utf-8"
  }

  self.version = nil
  parse_config
  self.version ||= @controller.sphinx_version

  ThinkingSphinx::Attribute::SphinxTypeMappings.merge!(
    :string => :sql_attr_string
  ) if Riddle.loaded_version.to_i > 1

  self
end
searchd_binary_name() click to toggle source
# File lib/thinking_sphinx/configuration.rb, line 248
def searchd_binary_name
  @controller.searchd_binary_name
end
searchd_binary_name=(name) click to toggle source
# File lib/thinking_sphinx/configuration.rb, line 252
def searchd_binary_name=(name)
  @controller.searchd_binary_name = name
end
searchd_log_file() click to toggle source
# File lib/thinking_sphinx/configuration.rb, line 216
def searchd_log_file
  @configuration.searchd.log
end
searchd_log_file=(file) click to toggle source
# File lib/thinking_sphinx/configuration.rb, line 220
def searchd_log_file=(file)
  @configuration.searchd.log = file
end
touch_reindex_file(output) click to toggle source
# File lib/thinking_sphinx/configuration.rb, line 286
def touch_reindex_file(output)
  return FileUtils.touch(@touched_reindex_file) if @touched_reindex_file and output =~ /succesfully sent SIGHUP to searchd/
  false
end
use_socket=(use_socket) click to toggle source
# File lib/thinking_sphinx/configuration.rb, line 200
def use_socket=(use_socket)
  if use_socket
    socket = "#{app_root}/tmp/sockets/searchd.#{self.environment}.sock"
    @configuration.searchd.listen = socket
    self.address = socket
  end
end

Private Instance Methods

enforce_common_attribute_types() click to toggle source
# File lib/thinking_sphinx/configuration.rb, line 329
def enforce_common_attribute_types
  sql_indexes = configuration.indices.reject { |index|
    index.is_a? Riddle::Configuration::DistributedIndex
  }

  return unless sql_indexes.any? { |index|
    index.sources.any? { |source|
      source.sql_attr_bigint.include? :sphinx_internal_id
    }
  }

  sql_indexes.each { |index|
    index.sources.each { |source|
      next if source.sql_attr_bigint.include? :sphinx_internal_id

      source.sql_attr_bigint << :sphinx_internal_id
      source.sql_attr_uint.delete :sphinx_internal_id
    }
  }
end
initial_model_directories() click to toggle source
# File lib/thinking_sphinx/configuration.rb, line 361
def initial_model_directories
  directories = ["#{app_root}/app/models/"] +
    Dir.glob("#{app_root}/vendor/plugins/*/app/models/")

  if defined?(Rails) && Rails.application
    directories += Rails.application.paths['app/models'].to_a
    directories += Rails.application.railties.engines.collect { |engine|
      engine.paths['app/models'].to_a
          }.flatten
  end

  directories
end
parse_config() click to toggle source

Parse the config/sphinx.yml file - if it exists - then use the attribute accessors to set the appropriate values. Nothing too clever.

# File lib/thinking_sphinx/configuration.rb, line 296
def parse_config
  path = "#{app_root}/config/sphinx.yml"
  return unless File.exists?(path)

  conf = YAML::load(ERB.new(IO.read(path)).result)[environment]

  conf.each do |key,value|
    self.send("#{key}=", value) if self.respond_to?("#{key}=")

    set_sphinx_setting self.source_options, key, value, SourceOptions
    set_sphinx_setting self.index_options,  key, value, IndexOptions
    set_sphinx_setting self.index_options,  key, value, CustomOptions
    set_sphinx_setting @configuration.searchd, key, value
    set_sphinx_setting @configuration.indexer, key, value
  end unless conf.nil?

  self.bin_path += '/' unless self.bin_path.blank?

  if self.allow_star
    self.index_options[:enable_star]    = true
    self.index_options[:min_prefix_len] = 1
  end
end
set_sphinx_setting(object, key, value, allowed = {}) click to toggle source
# File lib/thinking_sphinx/configuration.rb, line 320
def set_sphinx_setting(object, key, value, allowed = {})
  if object.is_a?(Hash)
    object[key.to_sym] = value if allowed.include?(key.to_s)
  else
    object.send("#{key}=", value) if object.respond_to?("#{key}")
    send("#{key}=", value) if self.respond_to?("#{key}")
  end
end
shuffled_addresses() click to toggle source
# File lib/thinking_sphinx/configuration.rb, line 350
def shuffled_addresses
  return address unless shuffle

  addresses = Array(address)
  if addresses.respond_to?(:shuffle)
    addresses.shuffle
  else
    address.sort_by { rand }
  end
end