diff --git a/elastic_searchable.gemspec b/elastic_searchable.gemspec index d401bff..bb8c9af 100644 --- a/elastic_searchable.gemspec +++ b/elastic_searchable.gemspec @@ -28,4 +28,5 @@ Gem::Specification.new do |s| s.add_development_dependency(%q, ["0.9.6.2"]) s.add_development_dependency(%q, ["2.11.3"]) s.add_development_dependency(%q, ["0.10.0"]) + s.add_development_dependency(%q, ["0.9.9.3"]) end diff --git a/lib/elastic_searchable/active_record_extensions.rb b/lib/elastic_searchable/active_record_extensions.rb index 3d9bc9c..914f962 100644 --- a/lib/elastic_searchable/active_record_extensions.rb +++ b/lib/elastic_searchable/active_record_extensions.rb @@ -7,73 +7,82 @@ module ElasticSearchable module ActiveRecordExtensions - # Valid options: - # :type (optional) configue type to store data in. default to model table name - # :mapping (optional) configure field properties for this model (ex: skip analyzer for field) - # :if (optional) reference symbol/proc condition to only index when condition is true - # :unless (optional) reference symbol/proc condition to skip indexing when condition is true - # :json (optional) configure the json document to be indexed (see http://api.rubyonrails.org/classes/ActiveModel/Serializers/JSON.html#method-i-as_json for available options) - # - # Available callbacks: - # after_index - # called after the object is indexed in elasticsearch - # (optional) :on => :create/:update can be used to only fire callback when object is created or updated - # - # after_percolate - # called after object is indexed in elasticsearch - # only fires if the update index call returns a non-empty set of registered percolations - # use the "percolations" instance method from within callback to inspect what percolations were returned - def elastic_searchable(options = {}) - cattr_accessor :elastic_options - self.elastic_options = options.symbolize_keys.merge(:unless => Array.wrap(options[:unless]).push(:elasticsearch_offline?)) + extend ActiveSupport::Concern - if self.elastic_options[:index_options] - ActiveSupport::Deprecation.warn ":index_options has been deprecated. Use ElasticSearchable.index_settings instead.", caller - end - if self.elastic_options[:index] - ActiveSupport::Deprecation.warn ":index has been deprecated. Use ElasticSearchable.index_name instead.", caller - end + included do + define_model_callbacks :index, :percolate, :only => :after + end - extend ElasticSearchable::Indexing::ClassMethods - extend ElasticSearchable::Queries + module ClassMethods + # Valid options: + # :type (optional) configue type to store data in. default to model table name + # :mapping (optional) configure field properties for this model (ex: skip analyzer for field) + # :if (optional) reference symbol/proc condition to only index when condition is true + # :unless (optional) reference symbol/proc condition to skip indexing when condition is true + # :json (optional) configure the json document to be indexed (see http://api.rubyonrails.org/classes/ActiveModel/Serializers/JSON.html#method-i-as_json for available options) + # + # after_percolate + # called after object is indexed in elasticsearch + # only fires if the update index call returns a non-empty set of registered percolations + # use the "percolations" instance method from within callback to inspect what percolations were returned + def elastic_searchable(options = {}) + cattr_accessor :elastic_options + self.elastic_options = options.symbolize_keys.merge(:unless => Array.wrap(options[:unless]).push(:elasticsearch_offline?)) + attr_reader :hit + attr_accessor :index_lifecycle - include ElasticSearchable::Indexing::InstanceMethods - include ElasticSearchable::Callbacks::InstanceMethods + if self.elastic_options[:index_options] + ActiveSupport::Deprecation.warn ":index_options has been deprecated. Use ElasticSearchable.index_settings instead.", caller + end + if self.elastic_options[:index] + ActiveSupport::Deprecation.warn ":index has been deprecated. Use ElasticSearchable.index_name instead.", caller + end - backgrounded :update_index_on_create => ElasticSearchable::Callbacks.backgrounded_options, :update_index_on_update => ElasticSearchable::Callbacks.backgrounded_options - class << self - backgrounded :delete_id_from_index => ElasticSearchable::Callbacks.backgrounded_options - end + extend ElasticSearchable::Indexing::ClassMethods + extend ElasticSearchable::Queries - attr_reader :hit # the hit json for this result - attr_accessor :index_lifecycle, :percolations - define_model_callbacks :index, :percolate, :only => :after - after_commit :update_index_on_create_backgrounded, :if => :should_index?, :on => :create - after_commit :update_index_on_update_backgrounded, :if => :should_index?, :on => :update - after_commit :delete_from_index, :unless => :elasticsearch_offline?, :on => :destroy + include ElasticSearchable::Indexing::InstanceMethods + include ElasticSearchable::Callbacks::InstanceMethods - class_eval do - # retuns list of percolation matches found during indexing - def percolations - @percolations || [] - end + include ElasticSearchable::ActiveRecordExtensions::LocalMethods + backgrounded :update_index_on_create => ElasticSearchable::Callbacks.backgrounded_options, :update_index_on_update => ElasticSearchable::Callbacks.backgrounded_options class << self - # override default after_index callback definition to support :on option - # see ActiveRecord::Transactions::ClassMethods#after_commit for example - def after_index(*args, &block) - options = args.last - if options.is_a?(Hash) && options[:on] - options[:if] = Array.wrap(options[:if]) - options[:if] << "self.index_lifecycle == :#{options[:on]}" - end - set_callback(:index, :after, *args, &block) - end + backgrounded :delete_id_from_index => ElasticSearchable::Callbacks.backgrounded_options + end + + after_commit :update_index_on_create_backgrounded, :if => :should_index?, :on => :create + after_commit :update_index_on_update_backgrounded, :if => :should_index?, :on => :update + after_commit :delete_from_index, :unless => :elasticsearch_offline?, :on => :destroy + end + end + module LocalMethods + extend ActiveSupport::Concern + + module ClassMethods + # Available callback method after indexing is complete + # called after the object is indexed in elasticsearch + # (optional) :on => :create/:update can be used to only fire callback when object is created or updated + # override default after_index callback definition to support :on option + # see ActiveRecord::Transactions::ClassMethods#after_commit for example + def after_index(*args, &block) + options = args.last + if options.is_a?(Hash) && options[:on] + options[:if] = Array.wrap(options[:if]) + options[:if] << "self.index_lifecycle == :#{options[:on]}" + end + set_callback(:index, :after, *args, &block) end end + + # retuns list of percolation matches found during indexing + # usable when the model is configured with an :after_index callback + def percolations + @percolations || [] + end end end end -ActiveRecord::Base.send(:extend, ElasticSearchable::ActiveRecordExtensions) +ActiveRecord::Base.send(:include, ElasticSearchable::ActiveRecordExtensions) diff --git a/lib/elastic_searchable/index.rb b/lib/elastic_searchable/index.rb index 176f5f1..2c5c69c 100644 --- a/lib/elastic_searchable/index.rb +++ b/lib/elastic_searchable/index.rb @@ -85,8 +85,8 @@ def reindex(lifecycle = nil) self.index_lifecycle = lifecycle ? lifecycle.to_sym : nil _run_index_callbacks - self.percolations = response['matches'] || [] - _run_percolate_callbacks if self.percolations.any? + @percolations = response['matches'] || [] + _run_percolate_callbacks if @percolations.any? end # document to index in elasticsearch def as_json_for_index @@ -108,8 +108,7 @@ def percolate(percolator_query = nil) body = {:doc => self.as_json_for_index} body[:query] = percolator_query if percolator_query response = ElasticSearchable.request :get, self.class.index_mapping_path('_percolate'), :json_body => body - self.percolations = response['matches'] || [] - self.percolations + @percolations = response['matches'] || [] end private diff --git a/test/test_elastic_searchable.rb b/test/test_elastic_searchable.rb index 8c930b9..78f2560 100644 --- a/test/test_elastic_searchable.rb +++ b/test/test_elastic_searchable.rb @@ -388,6 +388,7 @@ def percolated end context "when index has configured percolation" do setup do + ElasticSearchable.request :delete, '/_percolator' ElasticSearchable.request :put, '/_percolator/elastic_searchable/myfilter', :json_body => {:query => {:query_string => {:query => 'foo' }}} ElasticSearchable.request :post, '/_percolator/_refresh' end @@ -416,6 +417,7 @@ def percolated end context "with multiple percolators" do setup do + ElasticSearchable.request :delete, '/_percolator' ElasticSearchable.request :put, '/_percolator/elastic_searchable/greenfilter', :json_body => { :color => 'green', :query => {:query_string => {:query => 'foo' }}} ElasticSearchable.request :put, '/_percolator/elastic_searchable/bluefilter', :json_body => { :color => 'blue', :query => {:query_string => {:query => 'foo' }}} ElasticSearchable.request :post, '/_percolator/_refresh'