diff --git a/lib/chewy.rb b/lib/chewy.rb index cac44772..e83bcc27 100644 --- a/lib/chewy.rb +++ b/lib/chewy.rb @@ -49,6 +49,7 @@ def try_require(path) require 'chewy/fields/root' require 'chewy/journal' require 'chewy/railtie' if defined?(Rails::Railtie) +require 'chewy/elastic_client' ActiveSupport.on_load(:active_record) do include Chewy::Index::Observe::ActiveRecordMethods @@ -97,12 +98,7 @@ def derive_name(index_name) # Main elasticsearch-ruby client instance # def client - Chewy.current[:chewy_client] ||= begin - client_configuration = configuration.deep_dup - client_configuration.delete(:prefix) # used by Chewy, not relevant to Elasticsearch::Client - block = client_configuration[:transport_options].try(:delete, :proc) - ::Elasticsearch::Client.new(client_configuration, &block) - end + Chewy.current[:chewy_client] ||= Chewy::ElasticClient.new(Chewy.current[:chewy_client]) end # Sends wait_for_status request to ElasticSearch with status diff --git a/lib/chewy/config.rb b/lib/chewy/config.rb index 3836034f..65c60b36 100644 --- a/lib/chewy/config.rb +++ b/lib/chewy/config.rb @@ -40,7 +40,7 @@ class Config # Default field type for any field in any Chewy type. Defaults to 'text'. :default_field_type, # Callback called on each search request to be done into ES - :before_search_request_filter + :before_es_request_filter attr_reader :transport_logger, :transport_tracer, # Chewy search request DSL base class, used by every index. diff --git a/lib/chewy/elastic_client.rb b/lib/chewy/elastic_client.rb new file mode 100644 index 00000000..e370cec0 --- /dev/null +++ b/lib/chewy/elastic_client.rb @@ -0,0 +1,29 @@ +module Chewy + # Replacement for Chewy.client + class ElasticClient + def self.build_es_client(configuration = Chewy.configuration) + client_configuration = configuration.deep_dup + client_configuration.delete(:prefix) # used by Chewy, not relevant to Elasticsearch::Client + block = client_configuration[:transport_options].try(:delete, :proc) + ::Elasticsearch::Client.new(client_configuration, &block) + end + + def initialize(elastic_client) + @elastic_client = elastic_client || self.class.build_es_client + end + + def method_missing(name, *args, **kwargs, &block) + inspect_payload(name, args, kwargs) + + @elastic_client.__send__(name, *args, **kwargs, &block) + end + + def respond_to_missing?(name, _include_private = false) + @elastic_client.respond_to?(name) || super + end + + def inspect_payload(name, args, kwargs) + Chewy.config.before_es_request_filter&.call(name, args, kwargs) + end + end +end diff --git a/lib/chewy/search/request.rb b/lib/chewy/search/request.rb index 1d0608be..f3b1031b 100644 --- a/lib/chewy/search/request.rb +++ b/lib/chewy/search/request.rb @@ -13,7 +13,7 @@ module Search # # => ["places"], :body=>{:size=>20}}> # scope.order(:name).offset(10) # # => ["places"], :body=>{:sort=>["name"], :from=>10}}> - class Request # rubocop:disable Metrics/ClassLength + class Request include Enumerable include Scoping include Scrolling @@ -1034,7 +1034,6 @@ def reset def perform(additional = {}) request_body = render.merge(additional) ActiveSupport::Notifications.instrument 'search_query.chewy', notification_payload(request: request_body) do - Chewy.config.before_search_request_filter&.call(request_body) Chewy.client.search(request_body) rescue Elasticsearch::Transport::Transport::Errors::NotFound {} diff --git a/spec/chewy/before_search_request_filter_spec.rb b/spec/chewy/before_search_request_filter_spec.rb new file mode 100644 index 00000000..4526f9ac --- /dev/null +++ b/spec/chewy/before_search_request_filter_spec.rb @@ -0,0 +1,19 @@ +require 'spec_helper' + +describe 'Before search request filter' do + let(:filter) { instance_double('Proc') } + let!(:filter_previous_value) { Chewy.before_es_request_filter } + + before do + Chewy.before_es_request_filter = filter + end + + after do + Chewy.before_es_request_filter = filter_previous_value + end + + it 'call filter with the request body' do + expect(filter).to receive(:call).with(:search, [{body: {size: 0}, index: ['products']}], {}) + Chewy.client.search({index: ['products'], body: {size: 0}}).to_a + end +end diff --git a/spec/chewy/search/request_spec.rb b/spec/chewy/search/request_spec.rb index e433ee05..414de49a 100644 --- a/spec/chewy/search/request_spec.rb +++ b/spec/chewy/search/request_spec.rb @@ -878,25 +878,5 @@ end.to change(query, :performed?).from(false).to(true) end end - - describe 'before_search_request_filter' do - let(:query) { ProductsIndex.limit(0) } - let(:raw_response) { Chewy.client.search(query.render) } - let(:filter) { instance_double('Proc') } - let!(:filter_previous_value) { Chewy.before_search_request_filter } - - before do - Chewy.before_search_request_filter = filter - end - - after do - Chewy.before_search_request_filter = filter_previous_value - end - - it 'call filter with the request body' do - expect(filter).to receive(:call).with({body: {size: 0}, index: ['products']}) - query.response - end - end end end diff --git a/spec/chewy_spec.rb b/spec/chewy_spec.rb index 3023b71e..0c3e0d0e 100644 --- a/spec/chewy_spec.rb +++ b/spec/chewy_spec.rb @@ -57,18 +57,21 @@ before do Chewy.current[:chewy_client] = nil - allow(Chewy).to receive_messages(configuration: {transport_options: {proc: faraday_block}}) + end + + specify do + expect(Chewy).to receive_messages(configuration: {transport_options: {proc: faraday_block}}) - allow(Elasticsearch::Client).to receive(:new).with(expected_client_config) do |*_args, &passed_block| + expect(Elasticsearch::Client).to receive(:new).with(expected_client_config) do |*_args, &passed_block| # RSpec's `with(..., &block)` was used previously, but doesn't actually do # any verification of the passed block (even of its presence). expect(passed_block.source_location).to eq(faraday_block.source_location) mock_client end - end - its(:client) { is_expected.to eq(mock_client) } + expect(Chewy.client).to be_a(Chewy::ElasticClient) + end after { Chewy.current[:chewy_client] = initial_client } end