r1262@monsoon: jk | 2006-09-12 23:02:42 +0200
[acts_as_ferret.git] / lib / acts_as_ferret.rb
blob8c695a19d84c4e18e973a096aa83dddd8d9f700e
1 # Copyright (c) 2006 Kasper Weibel Nielsen-Refs, Thomas Lockney, Jens Krämer
3 # Permission is hereby granted, free of charge, to any person obtaining a copy
4 # of this software and associated documentation files (the "Software"), to deal
5 # in the Software without restriction, including without limitation the rights
6 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 # copies of the Software, and to permit persons to whom the Software is
8 # furnished to do so, subject to the following conditions:
10 # The above copyright notice and this permission notice shall be included in all
11 # copies or substantial portions of the Software.
13 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 # SOFTWARE.
21 require 'multi_index'
22 require 'more_like_this'
23 require 'class_methods'
24 require 'instance_methods'
26 # 0.10 problems
27 # Ferret::Search::Similarity, Ferret::Search::Similarity.default missing
28 # IndexReader#latest? segfaults when used on multiple indexes
31 # The Rails ActiveRecord Ferret Mixin.
33 # This mixin adds full text search capabilities to any Rails model.
35 # The current version emerged from on the original acts_as_ferret plugin done by
36 # Kasper Weibel and a modified version done by Thomas Lockney, which  both can be 
37 # found on the Ferret Wiki: http://ferret.davebalmain.com/trac/wiki/FerretOnRails.
39 # basic usage:
40 # include the following in your model class (specifiying the fields you want to get indexed):
41 # acts_as_ferret :fields => [ 'title', 'description' ]
43 # now you can use ModelClass.find_by_contents(query) to find instances of your model
44 # whose indexed fields match a given query. All query terms are required by default, but 
45 # explicit OR queries are possible. This differs from the ferret default, but imho is the more
46 # often needed/expected behaviour (more query terms result in less results).
48 # Released under the MIT license.
50 # Authors: 
51 # Kasper Weibel Nielsen-Refs (original author)
52 # Jens Kraemer <jk@jkraemer.net> (active maintainer)
54 module FerretMixin
55   module Acts #:nodoc:
56     module ARFerret #:nodoc:
58       # decorator that adds a total_hits accessor to search result arrays
59       class SearchResults
60         attr_reader :total_hits
61         def initialize(results, total_hits)
62           @results = results
63           @total_hits = total_hits
64         end
65         def method_missing(symbol, *args, &block)
66           @results.send(symbol, *args, &block)
67         end
68         def respond_to?(name)
69           self.methods.include?(name) || @results.respond_to?(name)
70         end
71       end
72       
73       def self.ensure_directory(dir)
74         FileUtils.mkdir_p dir unless File.directory? dir
75       end
76       
77       # make sure the default index base dir exists. by default, all indexes are created
78       # under RAILS_ROOT/index/RAILS_ENV
79       def self.init_index_basedir
80         index_base = "#{RAILS_ROOT}/index"
81         ensure_directory index_base
82         @@index_dir = "#{index_base}/#{RAILS_ENV}"
83         ensure_directory @@index_dir
84       end
85       
86       mattr_accessor :index_dir
87       init_index_basedir
88       
89       def self.append_features(base)
90         super
91         base.extend(ClassMethods)
92       end
94       
95       
96     end
97   end
98 end
100 # reopen ActiveRecord and include all the above to make
101 # them available to all our models if they want it
102 ActiveRecord::Base.class_eval do
103   include FerretMixin::Acts::ARFerret
107 class Ferret::Index::MultiReader
108   def latest?
109     # TODO: Exception handling added to resolve ticket #6. 
110     # It should be clarified wether this is a bug in Ferret
111     # in which case a bug report should be posted on the Ferret Trac. 
112     begin
113       @sub_readers.each { |r| return false unless r.latest? }
114     rescue
115       return false
116     end
117     true
118   end
121 # END acts_as_ferret.rb