3 module ARFerret #:nodoc:
8 # Returns an array of strings with the matches highlighted. The +query+ can
9 # either a query String or a Ferret::Search::Query object.
13 # field:: field to take the content from. This field has
14 # to have it's content stored in the index
15 # (:store => :yes in your call to aaf). If not
16 # given, all stored fields are searched, and the
17 # highlighted content found in all of them is returned.
18 # set :highlight => :no in the field options to
19 # avoid highlighting of contents from a :stored field.
20 # excerpt_length:: Default: 150. Length of excerpt to show. Highlighted
21 # terms will be in the centre of the excerpt.
22 # num_excerpts:: Default: 2. Number of excerpts to return.
23 # pre_tag:: Default: "<em>". Tag to place to the left of the
25 # post_tag:: Default: "</em>". This tag should close the
27 # ellipsis:: Default: "...". This is the string that is appended
28 # at the beginning and end of excerpts (unless the
29 # excerpt hits the start or end of the field. You'll
30 # probably want to change this so a Unicode elipsis
32 def highlight(query, options = {})
33 options = { :num_excerpts => 2, :pre_tag => '<em>', :post_tag => '</em>' }.update(options)
34 i = self.class.ferret_index
37 doc_num = self.document_number
39 highlights << i.highlight(query, doc_num, options)
41 query = i.process_query(query) # process only once
42 fields_for_ferret.each_pair do |field, config|
43 next if config[:store] == :no || config[:highlight] == :no
44 options[:field] = field
45 highlights << i.highlight(query, doc_num, options)
49 return highlights.compact.flatten[0..options[:num_excerpts]-1]
52 # re-eneable ferret indexing after a call to #disable_ferret
53 def ferret_enable; @ferret_disabled = nil end
55 # returns true if ferret indexing is enabled
56 def ferret_enabled?; @ferret_disabled.nil? end
58 # Disable Ferret for a specified amount of time. ::once will disable
59 # Ferret for the next call to #save (this is the default), ::always will
60 # do so for all subsequent calls.
61 # To manually trigger reindexing of a record, you can call #ferret_update
64 # When given a block, this will be executed without any ferret indexing of
65 # this object taking place. The optional argument in this case can be used
66 # to indicate if the object should be indexed after executing the block
67 # (::index_when_finished). Automatic Ferret indexing of this object will be
68 # turned on after the block has been executed.
69 def disable_ferret(option = :once)
71 @ferret_disabled = :always
74 ferret_update if option == :index_when_finished
75 elsif [:once, :always].include?(option)
76 @ferret_disabled = option
78 raise ArgumentError.new("Invalid Argument #{option}")
85 logger.debug "ferret_create/update: #{self.class.name} : #{self.id}"
86 self.class.ferret_index << self.to_doc
88 ferret_enable if @ferret_disabled == :once
90 @ferret_enabled = true
91 true # signal success to AR
93 alias :ferret_update :ferret_create
98 logger.debug "ferret_destroy: #{self.class.name} : #{self.id}"
100 self.class.ferret_index.query_delete(query_for_self)
102 logger.warn("Could not find indexed value for this object: #{$!}")
104 true # signal success to AR
107 # convert instance to ferret document
109 logger.debug "creating doc for class: #{self.class.name}, id: #{self.id}"
110 # Churn through the complete Active Record and add it to the Ferret document
111 doc = Ferret::Document.new
112 # store the id of each item
115 # store the class name if configured to do so
116 if configuration[:store_class_name]
117 doc[:class_name] = self.class.name
120 # iterate through the fields and add them to the document
121 fields_for_ferret.each_pair do |field, config|
122 doc[field] = self.send("#{field}_to_ferret") unless config[:ignore]
127 # returns the ferret document number this record has.
129 hits = self.class.ferret_index.search(query_for_self)
130 return hits.hits.first.doc if hits.total_hits == 1
131 raise "cannot determine document number from primary key: #{self}"
136 # build a ferret query matching only this record
138 query = Ferret::Search::TermQuery.new(:id, self.id.to_s)
139 if self.class.configuration[:single_index]
140 bq = Ferret::Search::BooleanQuery.new
141 bq.add_query(query, :must)
142 bq.add_query(Ferret::Search::TermQuery.new(:class_name, self.class.name), :must)