require 'MeCab' module ActiveRecord module Acts module Mecabulltext def self.included(klass) klass.extend ClassMethods end module ClassMethods ALLOW_SEARCH_OPTIONS = [:conditions, :count, :order, :group, :limit, :offset, :include, :select, :readonly] def acts_as_mecabulltext(options = {}) include ActiveRecord::Acts::Mecabulltext::PluginMethods cattr_accessor :fulltext_columns self.fulltext_columns = options[:fulltext_columns] || {} class_eval do before_create :update_fulltext_index before_update :update_fulltext_index end end def find_all_with_fulltext(query, options = {}) options.reject{|opt,val|!ALLOW_SEARCH_OPTIONS.include? opt} with_scope(:find => {:conditions => options[:conditions]}) do options[:conditions] = [fulltext_condition, to_fulltext_query(query)] if options[:count] options.delete :count count(options) else find(:all, options) end end end def count_with_fulltext(query, options = {}) find_all_with_fulltext(query, options.update({:count => true})) end def fulltext_condition columns = self.fulltext_columns.values.map{|c|"#{table_name}.`#{c}`"} "MATCH(#{columns.join(',')}) AGAINST(? IN BOOLEAN MODE)" end def to_fulltext_index(content) mecab content end def to_fulltext_query(content) to_fulltext_index(content).split(' ').map{|chunk|"+#{chunk}"}.join(' ') end private def mecab(content) @@mecab ||= MeCab::Tagger.new('-Owakati') @@mecab.parse(content.delete("\r\n")).gsub(/^\s*|\s*$/, '') end end #ActiveRecord::Acts::Mecabulltext::ClassMethods module PluginMethods def update_fulltext_index return if self.class.fulltext_columns.empty? self.class.fulltext_columns.each do |field, index| __send__ "#{index}=", self.class.to_fulltext_index(__send__(field)) end end end #ActiveRecord::Acts::Mecabulltext::PluginMethods end #ActiveRecord::Acts::Mecabulltext end # ActiveRecord::Acts end # ActiveRecord ActiveRecord::Base.send :include, ActiveRecord::Acts::Mecabulltext