module ThinkingSphinx::ActiveRecord::ClassMethods

Public Instance Methods

add_sphinx_index(name, &block) click to toggle source
# File lib/thinking_sphinx/active_record.rb, line 206
def add_sphinx_index(name, &block)
  index = ThinkingSphinx::Index::Builder.generate self, name, &block

  unless sphinx_indexes.any? { |i| i.name == index.name }
    add_sphinx_callbacks_and_extend(index.delta?)
    insert_sphinx_index index
  end
end
core_index_names() click to toggle source
# File lib/thinking_sphinx/active_record.rb, line 238
def core_index_names
  define_indexes
  sphinx_indexes.collect(&:core_name)
end
define_index(name = nil, &block) click to toggle source

Allows creation of indexes for Sphinx. If you don’t do this, there isn’t much point trying to search (or using this plugin at all, really).

An example or two:

define_index
  indexes :id, :as => :model_id
  indexes name
end

You can also grab fields from associations - multiple levels deep if necessary.

define_index do
  indexes tags.name, :as => :tag
  indexes articles.content
  indexes orders.line_items.product.name, :as => :product
end

And it will automatically concatenate multiple fields:

define_index do
  indexes [author.first_name, author.last_name], :as => :author
end

The indexes method is for fields - if you want attributes, use has instead. All the same rules apply - but keep in mind that attributes are for sorting, grouping and filtering, not searching.

define_index do
  # fields ...

  has created_at, updated_at
end

One last feature is the delta index. This requires the model to have a boolean field named ‘delta’, and is enabled as follows:

define_index do
  # fields ...
  # attributes ...

  set_property :delta => true
end

Check out the more detailed documentation for each of these methods at ThinkingSphinx::Index::Builder.

# File lib/thinking_sphinx/active_record.rb, line 161
def define_index(name = nil, &block)
  self.sphinx_index_blocks ||= []
  self.sphinx_indexes      ||= []
  self.sphinx_facets       ||= []

  ThinkingSphinx.context.add_indexed_model self

  if sphinx_index_blocks.empty?
    before_validation :define_indexes
    before_destroy    :define_indexes
  end

  self.sphinx_index_blocks << lambda {
    add_sphinx_index name, &block
  }

  include ThinkingSphinx::ActiveRecord::Scopes
  include ThinkingSphinx::SearchMethods
end
define_indexes() click to toggle source
# File lib/thinking_sphinx/active_record.rb, line 181
def define_indexes
  superclass.define_indexes unless superclass == ::ActiveRecord::Base

  return if sphinx_index_blocks.nil? ||
    defined_indexes?                 ||
    !ThinkingSphinx.define_indexes?

  sphinx_index_blocks.each do |block|
    block.call
  end

  self.defined_indexes = true

  # We want to make sure that if the database doesn't exist, then Thinking
  # Sphinx doesn't mind when running non-TS tasks (like db:create, db:drop
  # and db:migrate). It's a bit hacky, but I can't think of a better way.
rescue StandardError => err
  case err.class.name
  when "Mysql::Error", "Mysql2::Error", "Java::JavaSql::SQLException", "ActiveRecord::StatementInvalid"
    return
  else
    raise err
  end
end
delete_in_index(index, document_id) click to toggle source
# File lib/thinking_sphinx/active_record.rb, line 270
def delete_in_index(index, document_id)
  return unless ThinkingSphinx.sphinx_running? &&
    search_for_id(document_id, index)

  ThinkingSphinx::Configuration.instance.client.update(
    index, ['sphinx_deleted'], {document_id => [1]}
  )
rescue Riddle::ConnectionError, Riddle::ResponseError,
  ThinkingSphinx::SphinxError, Errno::ETIMEDOUT
  # Not the end of the world if Sphinx isn't running.
end
delta_index_names() click to toggle source
# File lib/thinking_sphinx/active_record.rb, line 243
def delta_index_names
  define_indexes
  sphinx_indexes.select(&:delta?).collect(&:delta_name)
end
delta_indexed_by_sphinx?() click to toggle source
# File lib/thinking_sphinx/active_record.rb, line 229
def delta_indexed_by_sphinx?
  sphinx_indexes && sphinx_indexes.any? { |index| index.delta? }
end
has_sphinx_indexes?() click to toggle source
# File lib/thinking_sphinx/active_record.rb, line 219
def has_sphinx_indexes?
  sphinx_indexes      &&
  sphinx_index_blocks &&
  (sphinx_indexes.length > 0 || sphinx_index_blocks.length > 0)
end
indexed_by_sphinx?() click to toggle source
# File lib/thinking_sphinx/active_record.rb, line 225
def indexed_by_sphinx?
  sphinx_indexes && sphinx_indexes.length > 0
end
insert_sphinx_index(index) click to toggle source
# File lib/thinking_sphinx/active_record.rb, line 215
def insert_sphinx_index(index)
  self.sphinx_indexes += [index]
end
source_of_sphinx_index() click to toggle source
# File lib/thinking_sphinx/active_record.rb, line 257
def source_of_sphinx_index
  define_indexes
  possible_models = self.sphinx_indexes.collect { |index| index.model }
  return self if possible_models.include?(self)

  parent = self.superclass
  while !possible_models.include?(parent) && parent != ::ActiveRecord::Base
    parent = parent.superclass
  end

  return parent
end
sphinx_index_names() click to toggle source
# File lib/thinking_sphinx/active_record.rb, line 233
def sphinx_index_names
  define_indexes
  sphinx_indexes.collect(&:all_names).flatten
end
sphinx_offset() click to toggle source
# File lib/thinking_sphinx/active_record.rb, line 282
def sphinx_offset
  ThinkingSphinx.context.superclass_indexed_models.
    index eldest_indexed_ancestor
end
suspended_delta(reindex_after = true) { || ... } click to toggle source

Temporarily disable delta indexing inside a block, then perform a single rebuild of index at the end.

Useful when performing updates to batches of models to prevent the delta index being rebuilt after each individual update.

In the following example, the delta index will only be rebuilt once, not 10 times.

SomeModel.suspended_delta do
  10.times do
    SomeModel.create( ... )
  end
end
# File lib/thinking_sphinx/active_record.rb, line 302
def suspended_delta(reindex_after = true, &block)
  define_indexes
  original_setting = ThinkingSphinx.deltas_suspended?
  ThinkingSphinx.deltas_suspended = true
  begin
    yield
  ensure
    ThinkingSphinx.deltas_suspended = original_setting
    self.index_delta if reindex_after && !original_setting
  end
end
to_riddle() click to toggle source
# File lib/thinking_sphinx/active_record.rb, line 248
def to_riddle
  define_indexes
  sphinx_database_adapter.setup

  local_sphinx_indexes.collect { |index|
    index.to_riddle(sphinx_offset)
  }.flatten
end