acts_as_indexed 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ rdoc
2
+ test/test.log
3
+ coverage
4
+ index
5
+ pkg
@@ -0,0 +1,90 @@
1
+ ===0.6.2 [11th June 2010]
2
+ - Now available as a Gem as well as the original plugin. [parndt - Thanks for doing most of the hard work.]
3
+
4
+ ===0.6.0 [10th June 2010]
5
+ - Now supports Rails 3.x.x as well as Rails 2.x.x.
6
+ - Added global configuration options.
7
+ - Now recommending using with_query scope for searching.
8
+ - Deprecated find_with_index and will_paginate_search methods.
9
+
10
+ ===0.5.3 [6th June 2010]
11
+ - Now supports non-standard table names automatically. [nandalopes]
12
+
13
+ ===0.5.2 [3rd May 2010]
14
+ - Fix for Errno::ERANGE error related to certain Math.log calculations. [parndt]
15
+ - Improved index detection in a shared-directory environment. [bob-p]
16
+
17
+ ===0.5.1 [11 June 2009]
18
+ - Fixed Ruby 1.8.6 compatibility.
19
+
20
+ ===0.5.0 [24 April 2009]
21
+ - Ruby 1.9 and Rails 2.3 compatibility.
22
+ - Index location can now be set. Provides Heroku compatibility.
23
+ - Better errors on bad options.
24
+ - ActiveRecord order argument overrides ranking returned by find_by_index.
25
+ - Various test environment improvements
26
+ - Various Bugfixes
27
+
28
+ ===0.4.6 [10 August 2008]
29
+ - Rolled in pagination.
30
+
31
+ ===0.4.5 [04 February 2008]
32
+ - Fixed a bug where the find_options :limit would be added to the :offset, which caused incorrectly sized collections to be returned.
33
+ - Fixed an 'ambiguous column' error when using the :includes find_options key.
34
+
35
+ ===0.4.4 [29 November 2007]
36
+ - Fixed a bug causing the weighting section of the code to error out.
37
+
38
+ ===0.4.3 [27 September 2007]
39
+ - Fixed a bug causing records to be deleted from index during record updates.
40
+
41
+ ===0.4.2 [27 September 2007]
42
+ - Fixed a bug causing identically ranked records to be lost.
43
+
44
+ ===0.4.1 [22 September 2007]
45
+ - Fixed a bug in the main search method.
46
+
47
+ ===0.4.0 [22 September 2007]
48
+ - Search results now ranked by relevance.
49
+
50
+ ===0.3.3 [20 September 2007]
51
+ - Fixed index update bug where deleted atoms were not removed from index.
52
+ - Improved performance of quoted queries.
53
+ - Improved performance of index updates.
54
+ - When building a full index, records are retrieved and indexed in batches to reduce memory consumption.
55
+
56
+ ===0.3.2 [19 September 2007]
57
+ - Fixed index update bug.
58
+
59
+ ===0.3.1 [18 September 2007]
60
+ - Added RDoc documentation comments.
61
+
62
+ ===0.3.0 [18 September 2007]
63
+ - Minor bug fixes.
64
+ - min_word_size now works properly, with quieries containing small words in
65
+ quotes or being preceded by a '+' symbol are now searched on.
66
+
67
+ ===0.2.2 [06 September 2007]
68
+ - Search now caches query results within a session. Call the search twice in an
69
+ action? Only runs once!
70
+
71
+ ===0.2.1 [05 September 2007]
72
+ - AR find options can now be passed to the search to allow finer control of
73
+ returned Model Objects.
74
+
75
+ ===0.2.0 [04 September 2007]
76
+ - Major performance improvements.
77
+ - Index segmentation can now be tuned.
78
+
79
+ ===0.1.1 [31 August 2007]
80
+ - Added a full set of tests.
81
+ - Fixed various set-manipulation based errors.
82
+ - Fixed a bug when searching for quoted phrases.
83
+
84
+ ===0.1.01 [31 August 2007]
85
+
86
+ - Fixed a casting bug occurring when adding non-string fields to the index.
87
+
88
+ ===0.1 [31 August 2007]
89
+
90
+ - Initial release.
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2007 - 2010 Douglas Shearer
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,137 @@
1
+ = acts_as_indexed
2
+
3
+ If you find this plugin useful, please consider a donation to show your
4
+ support!
5
+
6
+ http://www.paypal.com/cgi-bin/webscr?cmd=_send-money
7
+
8
+ Paypal address: mailto:dougal.s@gmail.com
9
+
10
+
11
+ == Instructions
12
+
13
+ This plugin allows boolean-queried fulltext search to be added to any Rails
14
+ app with no dependencies and minimal setup.
15
+
16
+
17
+ == Resources
18
+
19
+ === Install
20
+
21
+ == Rails 2.x.x
22
+ ./script/plugin install git://github.com/dougal/acts_as_indexed.git
23
+
24
+ == Rails 3.x.x
25
+ rails plugin install git://github.com/dougal/acts_as_indexed.git
26
+
27
+ === As a Gem
28
+ Despite this being slightly against the the original ethos of the project,
29
+ acts_as_indexed is now available as a Gem as several people have requested it.
30
+
31
+ gem install acts_as_indexed
32
+
33
+ Make sure to specify the Gem in your environment.rb file (Rails 2.x.x), or the Gemfile (Rails 3.x.x).
34
+
35
+ If you don't have git installed, you can download the plugin from the GitHub
36
+ page (http://github.com/dougal/acts_as_indexed) and unpack it into the
37
+ <tt>vendor/plugins</tt> directory of your rails app.
38
+
39
+ == Usage
40
+
41
+
42
+ === Setup
43
+
44
+ Add +acts_as_indexed+ to the top of any models you want to index, along with a
45
+ list of the fields you wish to be indexed.
46
+
47
+ class Post < ActiveRecord::Base
48
+ acts_as_indexed :fields => [:title, :body]
49
+
50
+ ...
51
+ end
52
+
53
+ The fields are not limited to model fields, but can be any instance method of
54
+ the current model.
55
+
56
+ class User < ActiveRecord::Base
57
+ acts_as_indexed :fields => [:address, :fullname]
58
+
59
+ def fullname
60
+ self.firstname + ' ' + self.lastname
61
+ end
62
+
63
+ ...
64
+ end
65
+
66
+ Any of the configuration options in the Further Configuration section can be added as to the acts_as_indexed method call. These will override any defaults or global configuration.
67
+
68
+
69
+ === Searching
70
+
71
+ To search, call the +with_query+ named scope on your model, passing a query as
72
+ an argument.
73
+
74
+ # Returns array of Post objects.
75
+ my_search_results = Post.with_query('my search query')
76
+
77
+ # Chain it with any number of ActiveRecord methods and named_scopes.
78
+ my_search_results = Post.public.with_query('my search query').find(:all, :limit => 10) # return the first 10 matches which are public.
79
+
80
+
81
+ === Query Options
82
+
83
+ The following query operators are supported:
84
+
85
+ * AND:: This is the default option. 'cat dog' will find records matching 'cat' AND 'dog'.
86
+ * NOT:: 'cat -dog' will find records matching 'cat' AND NOT 'dog'
87
+ * INCLUDE:: 'cat +me' will find records matching 'cat' and 'me', even if 'me' is smaller than the +min_word_size+
88
+ * "":: Quoted terms are matched as phrases. '"cat dog"' will find records matching the whole phrase. Quoted terms can be preceded by the NOT operator; 'cat -"big dog"' etc. Quoted terms can include words shorter than the +min_word_size+.
89
+
90
+ === Pagination
91
+
92
+ Since +with_query+ is a named scope, WillPaginate can be used in the normal
93
+ fashion.
94
+
95
+ @images = Image.with_query('girl').paginate(:page => 1, :per_page => 5)
96
+
97
+ === Further Configuration
98
+
99
+ A config block can be provided in your environment files or initializers.
100
+ Example showing defaults:
101
+
102
+ ActsAsIndexed.configure do |config|
103
+ config.index_file = [RAILS_ROOT,'index']
104
+ config.index_file_depth = 3
105
+ config.min_word_size = 3
106
+ end
107
+
108
+ A full rundown of the available configuration options can be found in
109
+ <tt>lib/acts_as_indexed/configuration.rb</tt>
110
+
111
+ == RDoc Documentation
112
+
113
+ To generate the RDoc documentation, run the <tt>rake rdoc</tt> task in the
114
+ acts_as_indexed plugin folder. Then point your web browser at
115
+ <tt>vendor/plugins/acts_as_indexed/rdoc/index.html</tt>.
116
+
117
+ Alternatively, you can view the rdoc documentation
118
+ online[http://rdoc.info/projects/dougal/acts_as_indexed/].
119
+
120
+ == Problems, Comments, Suggestions?
121
+
122
+ All of the above are most welcome. mailto:dougal.s@gmail.com
123
+
124
+
125
+ == Credits
126
+
127
+ Douglas F Shearer - http:douglasfshearer.com
128
+
129
+
130
+ == Future Releases
131
+
132
+ Future releases will be looking to add the following features:
133
+ * Optional html scrubbing during indexing.
134
+ * Ranking affected by field weightings.
135
+ * Support for DataMapper, Sequel and the various MongoDB ORMs.
136
+ * UTF-8 support. See the current solution here:
137
+ https://gist.github.com/193903bb4e0d6e5debe1
@@ -0,0 +1,50 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Test the acts_as_indexed plugin.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.pattern = 'test/**/*_test.rb'
12
+ t.verbose = true
13
+ end
14
+
15
+ desc 'Generate documentation for the acts_as_indexed plugin.'
16
+ Rake::RDocTask.new(:rdoc) do |rdoc|
17
+ rdoc.rdoc_dir = 'rdoc'
18
+ rdoc.title = 'ActsAsIndexed'
19
+ rdoc.options << '--line-numbers' << '--inline-source'
20
+ rdoc.rdoc_files.include('README.rdoc')
21
+ rdoc.rdoc_files.include('CHANGELOG')
22
+ rdoc.rdoc_files.include('lib/**/*.rb')
23
+ end
24
+
25
+ namespace :rcov do
26
+ desc "Generate a coverage report in coverage/"
27
+ task :gen do
28
+ sh "rcov --output coverage test/*_test.rb"
29
+ end
30
+
31
+ desc "Remove generated coverage files."
32
+ task :clobber do
33
+ sh "rm -rdf coverage"
34
+ end
35
+ end
36
+
37
+ begin
38
+ require 'jeweler'
39
+ Jeweler::Tasks.new do |gemspec|
40
+ gemspec.name = "acts_as_indexed"
41
+ gemspec.summary = "Acts As Indexed is a plugin which provides a pain-free way to add fulltext search to your Ruby on Rails app"
42
+ gemspec.description = gemspec.summary
43
+ gemspec.email = "dougal.s@gmail.com"
44
+ gemspec.homepage = "http://github.com/dougal/acts_as_indexed"
45
+ gemspec.authors = ["Douglas F Shearer"]
46
+ end
47
+ Jeweler::GemcutterTasks.new
48
+ rescue LoadError
49
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
50
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.6.2
@@ -0,0 +1,67 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{acts_as_indexed}
8
+ s.version = "0.6.2"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Douglas F Shearer"]
12
+ s.date = %q{2010-06-11}
13
+ s.description = %q{Acts As Indexed is a plugin which provides a pain-free way to add fulltext search to your Ruby on Rails app}
14
+ s.email = %q{dougal.s@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "README.rdoc"
17
+ ]
18
+ s.files = [
19
+ ".gitignore",
20
+ "CHANGELOG",
21
+ "MIT-LICENSE",
22
+ "README.rdoc",
23
+ "Rakefile",
24
+ "VERSION",
25
+ "acts_as_indexed.gemspec",
26
+ "lib/acts_as_indexed.rb",
27
+ "lib/acts_as_indexed/configuration.rb",
28
+ "lib/acts_as_indexed/search_atom.rb",
29
+ "lib/acts_as_indexed/search_index.rb",
30
+ "lib/will_paginate_search.rb",
31
+ "rails/init.rb",
32
+ "test/abstract_unit.rb",
33
+ "test/acts_as_indexed_test.rb",
34
+ "test/configuration_test.rb",
35
+ "test/database.yml",
36
+ "test/fixtures/post.rb",
37
+ "test/fixtures/posts.yml",
38
+ "test/schema.rb",
39
+ "test/search_atom_test.rb",
40
+ "test/search_index_test.rb"
41
+ ]
42
+ s.homepage = %q{http://github.com/dougal/acts_as_indexed}
43
+ s.rdoc_options = ["--charset=UTF-8"]
44
+ s.require_paths = ["lib"]
45
+ s.rubygems_version = %q{1.3.7}
46
+ s.summary = %q{Acts As Indexed is a plugin which provides a pain-free way to add fulltext search to your Ruby on Rails app}
47
+ s.test_files = [
48
+ "test/abstract_unit.rb",
49
+ "test/acts_as_indexed_test.rb",
50
+ "test/configuration_test.rb",
51
+ "test/fixtures/post.rb",
52
+ "test/schema.rb",
53
+ "test/search_atom_test.rb",
54
+ "test/search_index_test.rb"
55
+ ]
56
+
57
+ if s.respond_to? :specification_version then
58
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
59
+ s.specification_version = 3
60
+
61
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
62
+ else
63
+ end
64
+ else
65
+ end
66
+ end
67
+
@@ -0,0 +1,248 @@
1
+ # ActsAsIndexed
2
+ # Copyright (c) 2007 - 2010 Douglas F Shearer.
3
+ # http://douglasfshearer.com
4
+ # Distributed under the MIT license as included with this plugin.
5
+
6
+ require 'active_record'
7
+
8
+ require 'acts_as_indexed/configuration'
9
+ require 'acts_as_indexed/search_index'
10
+ require 'acts_as_indexed/search_atom'
11
+
12
+ module ActsAsIndexed #:nodoc:
13
+
14
+ # Holds the default configuration for acts_as_indexed.
15
+
16
+ @configuration = Configuration.new
17
+
18
+ # Returns the current configuration for acts_as_indexed.
19
+
20
+ def self.configuration
21
+ @configuration
22
+ end
23
+
24
+ # Call this method to modify defaults in your initializers.
25
+ #
26
+ # Example showing defaults:
27
+ # ActsAsIndexed.configure do |config|
28
+ # config.index_file = [Rails.root,'index']
29
+ # config.index_file_depth = 3
30
+ # config.min_word_size = 3
31
+ # end
32
+
33
+ def self.configure
34
+ self.configuration ||= Configuration.new
35
+ yield(configuration)
36
+ end
37
+
38
+ def self.included(mod)
39
+ mod.extend(ClassMethods)
40
+ end
41
+
42
+ module ClassMethods
43
+
44
+ # Declares a class as searchable.
45
+ #
46
+ # ====options:
47
+ # fields:: Names of fields to include in the index. Symbols pointing to
48
+ # instance methods of your model may also be given here.
49
+ # index_file_depth:: Tuning value for the index partitioning. Larger
50
+ # values result in quicker searches, but slower
51
+ # indexing. Default is 3.
52
+ # min_word_size:: Sets the minimum length for a word in a query. Words
53
+ # shorter than this value are ignored in searches
54
+ # unless preceded by the '+' operator. Default is 3.
55
+ # index_file:: Sets the location for the index. By default this is
56
+ # RAILS_ROOT/index. Specify as an array. Heroku, for
57
+ # example would use RAILS_ROOT/tmp/index, which would be
58
+ # set as [Rails.root,'tmp','index]
59
+
60
+ def acts_as_indexed(options = {})
61
+ class_eval do
62
+ extend ActsAsIndexed::SingletonMethods
63
+ end
64
+ include ActsAsIndexed::InstanceMethods
65
+
66
+ after_create :add_to_index
67
+ before_update :update_index
68
+ after_destroy :remove_from_index
69
+
70
+ # scope for Rails 3.x, named_scope for Rails 2.x.
71
+ if self.respond_to?(:where)
72
+ scope :with_query, lambda { |query| where("#{table_name}.id IN (?)", search_index(query, {}, {:ids_only => true})) }
73
+ else
74
+ named_scope :with_query, lambda { |query| { :conditions => ["#{table_name}.id IN (?)", search_index(query, {}, {:ids_only => true}) ] } }
75
+ end
76
+
77
+ cattr_accessor :aai_config, :aai_fields
78
+
79
+ self.aai_fields = options.delete(:fields)
80
+ raise(ArgumentError, 'no fields specified') if self.aai_fields.nil? || self.aai_fields.empty?
81
+
82
+ self.aai_config = ActsAsIndexed.configuration.dup
83
+ options.each do |k, v|
84
+ self.aai_config.send("#{k}=", v)
85
+ end
86
+ self.aai_config.index_file += [Rails.env, self.name]
87
+ end
88
+
89
+ # Adds the passed +record+ to the index. Index is built if it does not already exist. Clears the query cache.
90
+
91
+ def index_add(record)
92
+ build_index if !File.exists?(File.join(aai_config.index_file))
93
+ index = SearchIndex.new(aai_config.index_file, aai_config.index_file_depth, aai_fields, aai_config.min_word_size)
94
+ index.add_record(record)
95
+ index.save
96
+ @query_cache = {}
97
+ true
98
+ end
99
+
100
+ # Removes the passed +record+ from the index. Clears the query cache.
101
+
102
+ def index_remove(record)
103
+ index = SearchIndex.new(aai_config.index_file, aai_config.index_file_depth, aai_fields, aai_config.min_word_size)
104
+ # record won't be in index if it doesn't exist. Just return true.
105
+ return true if !index.exists?
106
+ index.remove_record(record)
107
+ index.save
108
+ @query_cache = {}
109
+ true
110
+ end
111
+
112
+ # Updates the index.
113
+ # 1. Removes the previous version of the record from the index
114
+ # 2. Adds the new version to the index.
115
+
116
+ def index_update(record)
117
+ build_index if !File.exists?(File.join(aai_config.index_file))
118
+ index = SearchIndex.new(aai_config.index_file, aai_config.index_file_depth, aai_fields, aai_config.min_word_size)
119
+ #index.remove_record(find(record.id))
120
+ #index.add_record(record)
121
+ index.update_record(record,find(record.id))
122
+ index.save
123
+ @query_cache = {}
124
+ true
125
+ end
126
+
127
+ # Finds instances matching the terms passed in +query+. Terms are ANDed by
128
+ # default. Returns an array of model instances or, if +ids_only+ is
129
+ # true, an array of integer IDs.
130
+ #
131
+ # Keeps a cache of matched IDs for the current session to speed up
132
+ # multiple identical searches.
133
+ #
134
+ # ====find_options
135
+ # Same as ActiveRecord#find options hash. An :order key will override
136
+ # the relevance ranking
137
+ #
138
+ # ====options
139
+ # ids_only:: Method returns an array of integer IDs when set to true.
140
+ # no_query_cache:: Turns off the query cache when set to true. Useful for testing.
141
+
142
+ def search_index(query, find_options={}, options={})
143
+ # Clear the query cache off if the key is set.
144
+ @query_cache = {} if (options.has_key?('no_query_cache') || options[:no_query_cache])
145
+ if !@query_cache || !@query_cache[query]
146
+ logger.debug('Query not in cache, running search.')
147
+ build_index if !File.exists?(File.join(aai_config.index_file))
148
+ index = SearchIndex.new(aai_config.index_file, aai_config.index_file_depth, aai_fields, aai_config.min_word_size)
149
+ @query_cache = {} if !@query_cache
150
+ @query_cache[query] = index.search(query)
151
+ else
152
+ logger.debug('Query held in cache.')
153
+ end
154
+ return @query_cache[query].sort.reverse.map(&:first) if options[:ids_only] || @query_cache[query].empty?
155
+
156
+ # slice up the results by offset and limit
157
+ offset = find_options[:offset] || 0
158
+ limit = find_options.include?(:limit) ? find_options[:limit] : @query_cache[query].size
159
+ part_query = @query_cache[query].sort.reverse.slice(offset,limit).map(&:first)
160
+
161
+ # Set these to nil as we are dealing with the pagination by setting
162
+ # exactly what records we want.
163
+ find_options[:offset] = nil
164
+ find_options[:limit] = nil
165
+
166
+ with_scope :find => find_options do
167
+ # Doing the find like this eliminates the possibility of errors occuring
168
+ # on either missing records (out-of-sync) or an empty results array.
169
+ records = find(:all, :conditions => [ "#{table_name}.id IN (?)", part_query])
170
+
171
+ if find_options.include?(:order)
172
+ records # Just return the records without ranking them.
173
+ else
174
+ # Results come back in random order from SQL, so order again.
175
+ ranked_records = {}
176
+ records.each do |r|
177
+ ranked_records[r] = @query_cache[query][r.id]
178
+ end
179
+
180
+ ranked_records.to_a.sort_by{|a| a.last }.reverse.map(&:first)
181
+ end
182
+ end
183
+
184
+ end
185
+
186
+ private
187
+
188
+ # Builds an index from scratch for the current model class.
189
+ def build_index
190
+ increment = 500
191
+ offset = 0
192
+ while (records = find(:all, :limit => increment, :offset => offset)).size > 0
193
+ #p "offset is #{offset}, increment is #{increment}"
194
+ index = SearchIndex.new(aai_config.index_file, aai_config.index_file_depth, aai_fields, aai_config.min_word_size)
195
+ offset += increment
196
+ index.add_records(records)
197
+ index.save
198
+ end
199
+ end
200
+
201
+ end
202
+
203
+ # Adds model class singleton methods.
204
+ module SingletonMethods
205
+
206
+ # DEPRECATED. Use +with_query+ scope instead.
207
+ # Finds instances matching the terms passed in +query+.
208
+ #
209
+ # See ActsAsIndexed::ClassMethods#search_index.
210
+ def find_with_index(query='', find_options = {}, options = {})
211
+ warn "[DEPRECATION] `find_with_index` is deprecated and will be removed in a later release. Use `with_query(query)` instead."
212
+ search_index(query, find_options, options)
213
+ end
214
+
215
+ end
216
+
217
+ # Adds model class instance methods.
218
+ # Methods are called automatically by ActiveRecord on +save+, +destroy+,
219
+ # and +update+ of model instances.
220
+ module InstanceMethods
221
+
222
+ # Adds the current model instance to index.
223
+ # Called by ActiveRecord on +save+.
224
+ def add_to_index
225
+ self.class.index_add(self)
226
+ end
227
+
228
+ # Removes the current model instance to index.
229
+ # Called by ActiveRecord on +destroy+.
230
+ def remove_from_index
231
+ self.class.index_remove(self)
232
+ end
233
+
234
+ # Updates current model instance index.
235
+ # Called by ActiveRecord on +update+.
236
+ def update_index
237
+ self.class.index_update(self)
238
+ end
239
+ end
240
+
241
+ end
242
+
243
+ # reopen ActiveRecord and include all the above to make
244
+ # them available to all our models if they want it
245
+
246
+ ActiveRecord::Base.class_eval do
247
+ include ActsAsIndexed
248
+ end