Module: ThinkingSphinx::ActiveRecord::ClassMethods

Defined in:
lib/thinking_sphinx/active_record.rb

Instance Method Summary collapse

Instance Method Details

#add_sphinx_index(name, &block) ⇒ Object



189
190
191
192
193
194
195
196
# File 'lib/thinking_sphinx/active_record.rb', line 189

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_namesObject



222
223
224
225
# File 'lib/thinking_sphinx/active_record.rb', line 222

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 {
    add_sphinx_index name, &block
  }
  
  include ThinkingSphinx::ActiveRecord::Scopes
  include ThinkingSphinx::SearchMethods
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



254
255
256
257
258
259
260
261
# File 'lib/thinking_sphinx/active_record.rb', line 254

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



227
228
229
230
# File 'lib/thinking_sphinx/active_record.rb', line 227

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

#delta_indexed_by_sphinx?Boolean

Returns:

  • (Boolean)


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

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

#has_sphinx_indexes?Boolean

Returns:

  • (Boolean)


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

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)


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

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

#insert_sphinx_index(index) ⇒ Object



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

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

#source_of_sphinx_indexObject



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

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



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

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

#sphinx_offsetObject



263
264
265
266
# File 'lib/thinking_sphinx/active_record.rb', line 263

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


283
284
285
286
287
288
289
290
291
292
293
# File 'lib/thinking_sphinx/active_record.rb', line 283

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
    self.index_delta if reindex_after
  end
end

#to_riddleObject



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

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