Module: ActsAsIndexed::ClassMethods
- Defined in:
- lib/acts_as_indexed/class_methods.rb
Instance Method Summary collapse
-
#acts_as_indexed(options = {}) ⇒ Object
Declares a class as searchable.
-
#build_index ⇒ Object
Builds an index from scratch for the current model class.
-
#index_add(record) ⇒ Object
Adds the passed
record
to the index. -
#index_remove(record) ⇒ Object
Removes the passed
record
from the index. -
#index_update(record) ⇒ Object
Updates the index.
-
#search_index(query, find_options = {}, options = {}) ⇒ Object
Finds instances matching the terms passed in
query
.
Instance Method Details
#acts_as_indexed(options = {}) ⇒ Object
Declares a class as searchable.
options:
- fields
-
Names of fields to include in the index. Symbols pointing to instance methods of your model may also be given here.
- index_file_depth
-
Tuning value for the index partitioning. Larger values result in quicker searches, but slower indexing. Default is 3.
- min_word_size
-
Sets the minimum length for a word in a query. Words shorter than this value are ignored in searches unless preceded by the ‘+’ operator. Default is 3.
- index_file
-
Sets the location for the index. By default this is RAILS_ROOT/tmp/index. Specify as an array. The default, for example, would be set as [Rails.root,‘tmp’,‘index].
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 |
# File 'lib/acts_as_indexed/class_methods.rb', line 20 def acts_as_indexed( = {}) class_eval do extend ActsAsIndexed::SingletonMethods end include ActsAsIndexed::InstanceMethods after_create :add_to_index before_update :update_index after_destroy :remove_from_index # scope for Rails 3.x, named_scope for Rails 2.x. if self.respond_to?(:where) scope :with_query, lambda { |query| where("#{table_name}.#{primary_key} IN (?)", search_index(query, {}, {:ids_only => true})) } else named_scope :with_query, lambda { |query| { :conditions => ["#{table_name}.#{primary_key} IN (?)", search_index(query, {}, {:ids_only => true}) ] } } end cattr_accessor :aai_config, :aai_fields self.aai_fields = .delete(:fields) raise(ArgumentError, 'no fields specified') if self.aai_fields.nil? || self.aai_fields.empty? self.aai_config = ActsAsIndexed.configuration.dup self.aai_config.if_proc = .delete(:if) .each do |k, v| self.aai_config.send("#{k}=", v) end # Add the Rails environment and this model's name to the index file path. self.aai_config.index_file = self.aai_config.index_file.join(Rails.env, self.name.underscore) end |
#build_index ⇒ Object
Builds an index from scratch for the current model class. Does not run if the index already exists.
161 162 163 164 165 166 167 168 |
# File 'lib/acts_as_indexed/class_methods.rb', line 161 def build_index return if aai_config.index_file.directory? index = new_index find_in_batches({ :batch_size => 500 }) do |records| index.add_records(records) end end |
#index_add(record) ⇒ Object
Adds the passed record
to the index. Index is built if it does not already exist. Clears the query cache.
54 55 56 57 58 59 60 61 |
# File 'lib/acts_as_indexed/class_methods.rb', line 54 def index_add(record) return if self.aai_config.disable_auto_indexing build_index index = new_index index.add_record(record) @query_cache = {} end |
#index_remove(record) ⇒ Object
Removes the passed record
from the index. Clears the query cache.
65 66 67 68 69 70 71 |
# File 'lib/acts_as_indexed/class_methods.rb', line 65 def index_remove(record) return if self.aai_config.disable_auto_indexing index = new_index index.remove_record(record) @query_cache = {} end |
#index_update(record) ⇒ Object
Updates the index.
-
Removes the previous version of the record from the index
-
Adds the new version to the index.
77 78 79 80 81 82 83 84 |
# File 'lib/acts_as_indexed/class_methods.rb', line 77 def index_update(record) return if self.aai_config.disable_auto_indexing build_index index = new_index index.update_record(record,find(record.id)) @query_cache = {} end |
#search_index(query, find_options = {}, options = {}) ⇒ Object
Finds instances matching the terms passed in query
. Terms are ANDed by default. Returns an array of model instances or, if ids_only
is true, an array of integer IDs.
Keeps a cache of matched IDs for the current session to speed up multiple identical searches.
find_options
Same as ActiveRecord#find options hash. An :order key will override the relevance ranking
options
- ids_only
-
Method returns an array of integer IDs when set to true.
- no_query_cache
-
Turns off the query cache when set to true. Useful for testing.
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 |
# File 'lib/acts_as_indexed/class_methods.rb', line 101 def search_index(query, ={}, ={}) # Clear the query cache off if the key is set. @query_cache = {} if [:no_query_cache] # Run the query if not already in cache. if !@query_cache || !@query_cache[query] build_index (@query_cache ||= {})[query] = new_index.search(query) end if [:ids_only] find_option_keys = .keys.map{ |k| k.to_sym } find_option_keys -= [:limit, :offset] if find_option_keys.any? raise ArgumentError, 'ids_only can not be combined with find option keys other than :offset or :limit' end end if .include?(:order) part_query = @query_cache[query].map{ |r| r.first } else # slice up the results by offset and limit offset = [:offset] || 0 limit = .include?(:limit) ? [:limit] : @query_cache[query].size part_query = sort(@query_cache[query]).slice(offset,limit).map{ |r| r.first } # Set these to nil as we are dealing with the pagination by setting # exactly what records we want. [:offset] = nil [:limit] = nil end return part_query if [:ids_only] with_scope :find => do # Doing the find like this eliminates the possibility of errors occuring # on either missing records (out-of-sync) or an empty results array. records = find(:all, :conditions => [ "#{table_name}.#{primary_key} IN (?)", part_query]) if .include?(:order) records # Just return the records without ranking them. else # Results come back in random order from SQL, so order again. ranked_records = ActiveSupport::OrderedHash.new records.each do |r| ranked_records[r] = @query_cache[query][r.id] end sort(ranked_records.to_a).map{ |r| r.first } end end end |