Skip to content
This repository has been archived by the owner on Oct 5, 2023. It is now read-only.

Commit

Permalink
move methods into active record extension
Browse files Browse the repository at this point in the history
  • Loading branch information
Ryan Sonnek committed Apr 23, 2012
1 parent fe3368d commit 08db46a
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 59 deletions.
1 change: 1 addition & 0 deletions elastic_searchable.gemspec
Expand Up @@ -28,4 +28,5 @@ Gem::Specification.new do |s|
s.add_development_dependency(%q<pry>, ["0.9.6.2"])
s.add_development_dependency(%q<shoulda>, ["2.11.3"])
s.add_development_dependency(%q<mocha>, ["0.10.0"])
s.add_development_dependency(%q<pry>, ["0.9.9.3"])
end
119 changes: 64 additions & 55 deletions lib/elastic_searchable/active_record_extensions.rb
Expand Up @@ -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)
7 changes: 3 additions & 4 deletions lib/elastic_searchable/index.rb
Expand Up @@ -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
Expand All @@ -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
Expand Down
2 changes: 2 additions & 0 deletions test/test_elastic_searchable.rb
Expand Up @@ -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
Expand Down Expand Up @@ -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'
Expand Down

0 comments on commit 08db46a

Please sign in to comment.