Module: ThinkingSphinx::ActiveRecord::ClassMethods

Defined in:
lib/thinking_sphinx/active_record.rb

Instance Method Summary collapse

Instance Method Details

#add_sphinx_index(index) ⇒ Object



189
190
191
192
# File 'lib/thinking_sphinx/active_record.rb', line 189

def add_sphinx_index(index)
  self.sphinx_indexes << index
  subclasses.each { |klass| klass.add_sphinx_index(index) }
end

#core_index_namesObject



213
214
215
216
# File 'lib/thinking_sphinx/active_record.rb', line 213

def core_index_names
  define_indexes
  sphinx_indexes.collect(&:core_name)
end

#define_index(name = nil, &block) ⇒ Object

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.



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/thinking_sphinx/active_record.rb', line 144

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 {
    index = ThinkingSphinx::Index::Builder.generate self, name, &block
    add_sphinx_callbacks_and_extend(index.delta?)
    add_sphinx_index index
  }
  
end

#define_indexesObject



164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/thinking_sphinx/active_record.rb', line 164

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", "Java::JavaSql::SQLException", "ActiveRecord::StatementInvalid"
    return
  else
    raise err
  end
end

#delete_in_index(index, document_id) ⇒ Object



245
246
247
248
249
250
251
252
# File 'lib/thinking_sphinx/active_record.rb', line 245

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]}
  )
end

#delta_index_namesObject



218
219
220
221
# File 'lib/thinking_sphinx/active_record.rb', line 218

def delta_index_names
  define_indexes
  sphinx_indexes.select(&:delta?).collect(&:delta_name)
end

#delta_indexed_by_sphinx?Boolean

Returns:

  • (Boolean)


204
205
206
# File 'lib/thinking_sphinx/active_record.rb', line 204

def delta_indexed_by_sphinx?
  sphinx_indexes && sphinx_indexes.any? { |index| index.delta? }
end

#has_sphinx_indexes?Boolean

Returns:

  • (Boolean)


194
195
196
197
198
# File 'lib/thinking_sphinx/active_record.rb', line 194

def has_sphinx_indexes?
  sphinx_indexes      && 
  sphinx_index_blocks &&
  (sphinx_indexes.length > 0 || sphinx_index_blocks.length > 0)
end

#indexed_by_sphinx?Boolean

Returns:

  • (Boolean)


200
201
202
# File 'lib/thinking_sphinx/active_record.rb', line 200

def indexed_by_sphinx?
  sphinx_indexes && sphinx_indexes.length > 0
end

#source_of_sphinx_indexObject



232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/thinking_sphinx/active_record.rb', line 232

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_namesObject



208
209
210
211
# File 'lib/thinking_sphinx/active_record.rb', line 208

def sphinx_index_names
  define_indexes
  sphinx_indexes.collect(&:all_names).flatten
end

#sphinx_offsetObject



254
255
256
257
# File 'lib/thinking_sphinx/active_record.rb', line 254

def sphinx_offset
  ThinkingSphinx.context.superclass_indexed_models.
    index eldest_indexed_ancestor
end

#suspended_delta(reindex_after = true, &block) ⇒ Object

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


274
275
276
277
278
279
280
281
282
283
# File 'lib/thinking_sphinx/active_record.rb', line 274

def suspended_delta(reindex_after = true, &block)
  define_indexes
  original_setting = ThinkingSphinx.deltas_enabled?
  ThinkingSphinx.deltas_enabled = false
  begin
    yield
  ensure
    ThinkingSphinx.deltas_enabled = original_setting
  end
end

#to_riddleObject



223
224
225
226
227
228
229
230
# File 'lib/thinking_sphinx/active_record.rb', line 223

def to_riddle
  define_indexes
  sphinx_database_adapter.setup
  
  local_sphinx_indexes.collect { |index|
    index.to_riddle(sphinx_offset)
  }.flatten
end