Module: ThinkingSphinx::ActiveRecord
- Defined in:
- lib/thinking_sphinx/active_record.rb,
lib/thinking_sphinx/active_record/delta.rb,
lib/thinking_sphinx/active_record/scopes.rb,
lib/thinking_sphinx/active_record/attribute_updates.rb,
lib/thinking_sphinx/active_record/has_many_association.rb
Overview
Core additions to ActiveRecord models - define_index for creating indexes for models. If you want to interrogate the index objects created for the model, you can use the class-level accessor :sphinx_indexes.
Defined Under Namespace
Modules: AttributeUpdates, Delta, HasManyAssociation, Scopes
Class Method Summary collapse
Instance Method Summary collapse
- #in_both_indexes? ⇒ Boolean
- #in_core_index? ⇒ Boolean
- #in_delta_index? ⇒ Boolean
- #in_index?(suffix) ⇒ Boolean
-
#primary_key_for_sphinx ⇒ Integer
Returns the unique integer id for the object.
- #sphinx_document_id ⇒ Object
- #toggle_deleted ⇒ Object
Class Method Details
.included(base) ⇒ Object
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 |
# File 'lib/thinking_sphinx/active_record.rb', line 12 def self.included(base) base.class_eval do class_inheritable_array :sphinx_indexes, :sphinx_facets class << self def set_sphinx_primary_key(attribute) @sphinx_primary_key_attribute = attribute end def primary_key_for_sphinx @sphinx_primary_key_attribute || primary_key end # 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. # def define_index(&block) return unless ThinkingSphinx.define_indexes? self.sphinx_indexes ||= [] index = ThinkingSphinx::Index::Builder.generate(self, &block) self.sphinx_indexes << index unless ThinkingSphinx.indexed_models.include?(self.name) ThinkingSphinx.indexed_models << self.name end if index.delta? before_save :toggle_delta after_commit :index_delta end after_destroy :toggle_deleted include ThinkingSphinx::SearchMethods include ThinkingSphinx::ActiveRecord::AttributeUpdates include ThinkingSphinx::ActiveRecord::Scopes index # 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 alias_method :sphinx_index, :define_index def sphinx_indexes.last. end # Generate a unique CRC value for the model's name, to use to # determine which Sphinx documents belong to which AR records. # # Really only written for internal use - but hey, if it's useful to # you in some other way, awesome. # def to_crc32 self.name.to_crc32 end def to_crc32s (subclasses << self).collect { |klass| klass.to_crc32 } end def source_of_sphinx_index 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 def to_riddle(offset) sphinx_database_adapter.setup indexes = [to_riddle_for_core(offset)] indexes << to_riddle_for_delta(offset) if sphinx_delta? indexes << to_riddle_for_distributed end def sphinx_database_adapter @sphinx_database_adapter ||= ThinkingSphinx::AbstractAdapter.detect(self) end def sphinx_name self.name.underscore.tr(':/\\', '_') end private def sphinx_delta? self.sphinx_indexes.any? { |index| index.delta? } end def to_riddle_for_core(offset) index = Riddle::Configuration::Index.new("#{sphinx_name}_core") index.path = File.join( ThinkingSphinx::Configuration.instance.searchd_file_path, index.name ) index set_field_settings_for_indexes index self.sphinx_indexes.select { |ts_index| ts_index.model == self }.each_with_index do |ts_index, i| index.sources += ts_index.sources.collect { |source| source.to_riddle_for_core(offset, i) } end index end def to_riddle_for_delta(offset) index = Riddle::Configuration::Index.new("#{sphinx_name}_delta") index.parent = "#{sphinx_name}_core" index.path = File.join(ThinkingSphinx::Configuration.instance.searchd_file_path, index.name) self.sphinx_indexes.each_with_index do |ts_index, i| index.sources += ts_index.sources.collect { |source| source.to_riddle_for_delta(offset, i) } if ts_index.delta? end index end def to_riddle_for_distributed index = Riddle::Configuration::DistributedIndex.new(sphinx_name) index.local_indexes << "#{sphinx_name}_core" index.local_indexes.unshift "#{sphinx_name}_delta" if sphinx_delta? index end def (index) ThinkingSphinx::Configuration.instance..each do |key, value| index.send("#{key}=".to_sym, value) end self.sphinx_indexes.each do |ts_index| ts_index..each do |key, value| index.send("#{key}=".to_sym, value) if ThinkingSphinx::Configuration::IndexOptions.include?(key.to_s) && !value.nil? end end end def set_field_settings_for_indexes(index) field_names = lambda { |field| field.unique_name.to_s } self.sphinx_indexes.each do |ts_index| index.prefix_field_names += ts_index.prefix_fields.collect(&field_names) index.infix_field_names += ts_index.infix_fields.collect(&field_names) end end end end base.send(:include, ThinkingSphinx::ActiveRecord::Delta) ::ActiveRecord::Associations::HasManyAssociation.send( :include, ThinkingSphinx::ActiveRecord::HasManyAssociation ) ::ActiveRecord::Associations::HasManyThroughAssociation.send( :include, ThinkingSphinx::ActiveRecord::HasManyAssociation ) end |
Instance Method Details
#in_both_indexes? ⇒ Boolean
250 251 252 |
# File 'lib/thinking_sphinx/active_record.rb', line 250 def in_both_indexes? in_core_index? && in_delta_index? end |
#in_core_index? ⇒ Boolean
242 243 244 |
# File 'lib/thinking_sphinx/active_record.rb', line 242 def in_core_index? in_index? "core" end |
#in_delta_index? ⇒ Boolean
246 247 248 |
# File 'lib/thinking_sphinx/active_record.rb', line 246 def in_delta_index? in_index? "delta" end |
#in_index?(suffix) ⇒ Boolean
238 239 240 |
# File 'lib/thinking_sphinx/active_record.rb', line 238 def in_index?(suffix) self.class.search_for_id self.sphinx_document_id, sphinx_index_name(suffix) end |
#primary_key_for_sphinx ⇒ Integer
Returns the unique integer id for the object. This method uses the attribute hash to get around ActiveRecord always mapping the #id method to whatever the real primary key is (which may be a unique string hash).
283 284 285 |
# File 'lib/thinking_sphinx/active_record.rb', line 283 def primary_key_for_sphinx @primary_key_for_sphinx ||= read_attribute(self.class.primary_key_for_sphinx) end |
#sphinx_document_id ⇒ Object
287 288 289 290 |
# File 'lib/thinking_sphinx/active_record.rb', line 287 def sphinx_document_id primary_key_for_sphinx * ThinkingSphinx.indexed_models.size + ThinkingSphinx.indexed_models.index(self.class.source_of_sphinx_index.name) end |
#toggle_deleted ⇒ Object
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 |
# File 'lib/thinking_sphinx/active_record.rb', line 254 def toggle_deleted return unless ThinkingSphinx.updates_enabled? && ThinkingSphinx.sphinx_running? config = ThinkingSphinx::Configuration.instance client = Riddle::Client.new config.address, config.port client.update( "#{self.class.sphinx_indexes.first.name}_core", ['sphinx_deleted'], {self.sphinx_document_id => 1} ) if self.in_core_index? client.update( "#{self.class.sphinx_indexes.first.name}_delta", ['sphinx_deleted'], {self.sphinx_document_id => 1} ) if ThinkingSphinx.deltas_enabled? && self.class.sphinx_indexes.any? { |index| index.delta? } && self.toggled_delta? rescue ::ThinkingSphinx::ConnectionError # nothing end |