Module: ThinkingSphinx::ActiveRecord::ClassMethods

Defined in:
lib/thinking_sphinx/active_record.rb

Instance Method Summary collapse

Instance Method Details

#add_sphinx_index(index) ⇒ Object



191
192
193
194
# File 'lib/thinking_sphinx/active_record.rb', line 191

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

#core_index_namesObject



215
216
217
218
# File 'lib/thinking_sphinx/active_record.rb', line 215

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
163
164
# 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
  }
  
  include ThinkingSphinx::ActiveRecord::Scopes
  include ThinkingSphinx::SearchMethods
end

#define_indexesObject



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

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



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

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



220
221
222
223
# File 'lib/thinking_sphinx/active_record.rb', line 220

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

#delta_indexed_by_sphinx?Boolean

Returns:

  • (Boolean)


206
207
208
# File 'lib/thinking_sphinx/active_record.rb', line 206

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

#has_sphinx_indexes?Boolean

Returns:

  • (Boolean)


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

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)


202
203
204
# File 'lib/thinking_sphinx/active_record.rb', line 202

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

#source_of_sphinx_indexObject



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

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



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

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

#sphinx_offsetObject



256
257
258
259
# File 'lib/thinking_sphinx/active_record.rb', line 256

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


276
277
278
279
280
281
282
283
284
285
286
# File 'lib/thinking_sphinx/active_record.rb', line 276

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



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

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