Module: ActsAsFerret::ClassMethods
- Defined in:
- lib/acts_as_ferret/class_methods.rb
Instance Method Summary collapse
-
#aaf_index ⇒ Object
Retrieve the index instance for this model class.
-
#bulk_index(*ids) ⇒ Object
re-index a number records specified by the given ids.
-
#disable_ferret ⇒ Object
Disables ferret index updates for this model.
- #enable_ferret ⇒ Object
- #ferret_enabled? ⇒ Boolean
-
#find_ids_with_ferret(q, options = {}, &block) ⇒ Object
Finds instance model name, ids and scores by contents.
-
#find_with_ferret(q, options = {}, find_options = {}) ⇒ Object
Finds instances by searching the Ferret index.
-
#rebuild_index ⇒ Object
rebuild the index from all data stored for this model, and any other model classes associated with the same index.
-
#records_for_bulk_index(ids, batch_size = 1000) ⇒ Object
yields the records with the given ids, in batches of batch_size.
-
#records_for_rebuild(batch_size = 1000) ⇒ Object
runs across all records yielding those to be indexed when the index is rebuilt.
-
#records_modified_since(time) ⇒ Object
Returns all records modified or created after the specified time.
-
#total_hits(q, options = {}) ⇒ Object
Returns the total number of hits for the given query .
-
#use_fast_batches? ⇒ Boolean
true if our db and table appear to be suitable for the mysql fast batch hack (see weblog.jamisbuck.org/2007/4/6/faking-cursors-in-activerecord).
Instance Method Details
#aaf_index ⇒ Object
Retrieve the index instance for this model class. This can either be a LocalIndex, or a RemoteIndex instance.
106 107 108 |
# File 'lib/acts_as_ferret/class_methods.rb', line 106 def aaf_index @index ||= ActsAsFerret::get_index(aaf_configuration[:name]) end |
#bulk_index(*ids) ⇒ Object
re-index a number records specified by the given ids. Use for large indexing jobs i.e. after modifying a lot of records with Ferret disabled. Please note that the state of Ferret (enabled or disabled at class or record level) is not checked by this method, so if you need to do so (e.g. because of a custom ferret_enabled? implementation), you have to do so yourself.
37 38 39 40 41 |
# File 'lib/acts_as_ferret/class_methods.rb', line 37 def bulk_index(*ids) = Hash === ids.last ? ids.pop : {} ids = ids.first if ids.size == 1 && ids.first.is_a?(Enumerable) aaf_index.bulk_index(self.name, ids, ) end |
#disable_ferret ⇒ Object
Disables ferret index updates for this model. When a block is given, Ferret will be re-enabled again after executing the block.
7 8 9 10 11 12 13 |
# File 'lib/acts_as_ferret/class_methods.rb', line 7 def disable_ferret aaf_configuration[:enabled] = false if block_given? yield enable_ferret end end |
#enable_ferret ⇒ Object
15 16 17 |
# File 'lib/acts_as_ferret/class_methods.rb', line 15 def enable_ferret aaf_configuration[:enabled] = true end |
#ferret_enabled? ⇒ Boolean
19 20 21 |
# File 'lib/acts_as_ferret/class_methods.rb', line 19 def ferret_enabled? aaf_configuration[:enabled] end |
#find_ids_with_ferret(q, options = {}, &block) ⇒ Object
Finds instance model name, ids and scores by contents. Useful e.g. if you want to search across models or do not want to fetch all result records (yet).
Options are the same as for find_with_ferret
A block can be given too, it will be executed with every result: find_ids_with_ferret(q, options) do |model, id, score|
id_array << id
scores_by_id[id] = score
end NOTE: in case a block is given, only the total_hits value will be returned instead of the [total_hits, results] array!
181 182 183 |
# File 'lib/acts_as_ferret/class_methods.rb', line 181 def find_ids_with_ferret(q, = {}, &block) aaf_index.find_ids(q, , &block) end |
#find_with_ferret(q, options = {}, find_options = {}) ⇒ Object
Finds instances by searching the Ferret index. Terms are ANDed by default, use OR between terms for ORed queries. Or specify :or_default => true in the :ferret
options hash of acts_as_ferret.
You may either use the offset
and limit
options to implement your own pagination logic, or use the page
and per_page
options to use the built in pagination support which is compatible with will_paginate’s view helpers. If page
and per_page
are given, offset
and limit
will be ignored.
options:
- page
-
page of search results to retrieve
- per_page
-
number of search results that are displayed per page
- offset
-
first hit to retrieve (useful for paging)
- limit
-
number of hits to retrieve, or :all to retrieve all results
- lazy
-
Array of field names whose contents should be read directly from the index. Those fields have to be marked :store => :yes in their field options. Give true to get all stored fields. Note that if you have a shared index, you have to explicitly state the fields you want to fetch, true won’t work here)
find_options
is a hash passed on to active_record’s find when retrieving the data from db, useful to i.e. prefetch relationships with :include or to specify additional filter criteria with :conditions (only string and array syntax supported). You can also call find_with_ferret inside named or dynamic scopes, if you like the conditions hash syntax more.
This method returns a SearchResults
instance, which really is an Array that has been decorated with a total_hits attribute holding the total number of hits. Additionally, SearchResults is compatible with the pagination helper methods of the will_paginate plugin.
Please keep in mind that the number of results delivered might be less than limit
if you specify any active record conditions that further limit the result. Use limit
and offset
as AR find_options instead. page
and per_page
are supposed to work regardless of any conditions
present in find_options
.
148 149 150 151 152 153 154 155 |
# File 'lib/acts_as_ferret/class_methods.rb', line 148 def find_with_ferret(q, = {}, = {}) if self.scoped.to_sql =~ /WHERE/ && self.scoped.where_values_hash.empty? # Treat external scope the same as if :conditions present # (i.e. when it comes to counting results). [:conditions] ||= '1=1' end return ActsAsFerret::find q, self, , end |
#rebuild_index ⇒ Object
rebuild the index from all data stored for this model, and any other model classes associated with the same index. This is called automatically when no index exists yet.
27 28 29 |
# File 'lib/acts_as_ferret/class_methods.rb', line 27 def rebuild_index aaf_index.rebuild_index end |
#records_for_bulk_index(ids, batch_size = 1000) ⇒ Object
yields the records with the given ids, in batches of batch_size
91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/acts_as_ferret/class_methods.rb', line 91 def records_for_bulk_index(ids, batch_size = 1000) transaction do offset = 0 ids.each_slice(batch_size) do |id_slice| records = where(:id => id_slice).all #yield records, offset yield where(:id => id_slice).all, offset offset += batch_size end end end |
#records_for_rebuild(batch_size = 1000) ⇒ Object
runs across all records yielding those to be indexed when the index is rebuilt
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/acts_as_ferret/class_methods.rb', line 73 def records_for_rebuild(batch_size = 1000) transaction do if use_fast_batches? offset = 0 while (rows = where([ "#{table_name}.id > ?", offset ]).limit(batch_size).all).any? offset = rows.last.id yield rows, offset end else order = "#{primary_key} ASC" # fixes #212 0.step(self.count, batch_size) do |offset| yield scoped.limit(batch_size).offset(offset).order(order).all, offset end end end end |
#records_modified_since(time) ⇒ Object
Returns all records modified or created after the specified time. Used by the rake rebuild task to find models that need to be updated in the index after the rebuild finished because they changed while the rebuild was running. Override if your models don’t stick to the created_at/updated_at convention.
59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/acts_as_ferret/class_methods.rb', line 59 def records_modified_since(time) condition = [] %w(updated_at created_at).each do |col| condition << "#{col} >= ?" if column_names.include? col end if condition.empty? logger.warn "#{self.name}: Override records_modified_since(time) to keep the index up to date with records changed during rebuild." [] else where([ condition.join(' AND '), *([time]*condition.size) ]).all end end |
#total_hits(q, options = {}) ⇒ Object
Returns the total number of hits for the given query
Note that since we don’t query the database here, this method won’t deliver the expected results when used on an AR association.
163 164 165 |
# File 'lib/acts_as_ferret/class_methods.rb', line 163 def total_hits(q, ={}) aaf_index.total_hits(q, ) end |
#use_fast_batches? ⇒ Boolean
true if our db and table appear to be suitable for the mysql fast batch hack (see weblog.jamisbuck.org/2007/4/6/faking-cursors-in-activerecord)
46 47 48 49 50 51 |
# File 'lib/acts_as_ferret/class_methods.rb', line 46 def use_fast_batches? if connection.class.name =~ /Mysql/ && primary_key == 'id' && aaf_configuration[:mysql_fast_batches] logger.info "using mysql specific batched find :all. Turn off with :mysql_fast_batches => false if you encounter problems (i.e. because of non-integer UUIDs in the id column)" true end end |