Sunspot::Railsが提供するClassMethodsとInstanceMethods周り

後で絶対ハマると思ったので書いておく。

Sunspot::Railsを使うとSunspot::Rails::Searchable::ClassMethodsとSunspot::Rails::Searchable::MethodsがActiveRecordにそれぞれextend,includeされる。

Model.indexとModel#indexの動作が違い過ぎて結構びっくりしてしまった。

SunspotのREADMEに下記のように書いてあって破壊的メソッドがautocommitなんだなと思っていたんだが

# On a class itself
Person.reindex
Sunspot.commit

# On mixed objects
Sunspot.index [post1, item2]
Sunspot.index person3
Sunspot.commit

# With autocommit
Sunspot.index! [post1, item2, person3]

クラスメソッドの方はそんなことなくてあれ。
sunspot_rails-1.3.3/lib/sunspot/rails/searchable.rb

クラスメソッド

201         #
202         # Add/update all existing records in the Solr index. The
203         # +batch_size+ argument specifies how many records to load out of the
204         # database at a time. The default batch size is 50; if nil is passed,
205         # records will not be indexed in batches. By default, a commit is issued
206         # after each batch; passing +false+ for +batch_commit+ will disable
207         # this, and only issue a commit at the end of the process. If associated
208         # objects need to indexed also, you can specify +include+ in format
209         # accepted by ActiveRecord to improve your sql select performance
210         #
211         # ==== Options (passed as a hash)
212         #
213         # batch_size<Integer>:: Batch size with which to load records. Passing
214         #                       'nil' will skip batches.  Default is 50.
215         # batch_commit<Boolean>:: Flag signalling if a commit should be done after
216         #                         after each batch is indexed, default is 'true'
217         # include<Mixed>:: include option to be passed to the ActiveRecord find,
218         #                  used for including associated objects that need to be
219         #                  indexed with the parent object, accepts all formats
220         #                  ActiveRecord::Base.find does
221         # first_id:: The lowest possible ID for this class. Defaults to 0, which
222         #            is fine for integer IDs; string primary keys will need to
223         #            specify something reasonable here.
224         #
225         # ==== Examples
226         #
227         #   # index in batches of 50, commit after each
228         #   Post.index
229         #
230         #   # index all rows at once, then commit
231         #   Post.index(:batch_size => nil)
232         #
233         #   # index in batches of 50, commit when all batches complete
234         #   Post.index(:batch_commit => false)
235         #
236         #   # include the associated +author+ object when loading to index
237         #   Post.index(:include => :author)
238         #
239         def solr_index(opts={})
240           options = {
241             :batch_size => 50,
242             :batch_commit => true,
243             :include => self.sunspot_options[:include],
244             :start => opts.delete(:first_id) || 0
245           }.merge(opts)
246           find_in_batch_options = {
247             :include => options[:include],
248             :batch_size => options[:batch_size],
249             :start => options[:first_id]
250           }
251           progress_bar = options[:progress_bar]
252           if options[:batch_size]
253             batch_counter = 0
254             find_in_batches(find_in_batch_options) do |records|
255               solr_benchmark options[:batch_size], batch_counter do
256                 Sunspot.index(records.select { |model| model.indexable? })
257                 Sunspot.commit if options[:batch_commit]
258               end
259               # track progress
260               progress_bar.increment!(records.length) if progress_bar
261               batch_counter += 1
262             end
263           else
264             records = all(:include => options[:include]).select { |model| model.indexable? }
265             Sunspot.index!(records)
266           end
267           # perform a final commit if not committing in batches
268           Sunspot.commit unless options[:batch_commit]
269         end

インスタンスメソッド

363         #
364         # Index the model in Solr. If the model is already indexed, it will be
365         # updated. Using the defaults, you will usually not need to call this
366         # method, as models are indexed automatically when they are created or
367         # updated. If you have disabled automatic indexing (see
368         # ClassMethods#searchable), this method allows you to manage indexing
369         # manually.
370         #
371         def solr_index
372           Sunspot.index(self)
373         end