diff --git a/lib/jay_api/elasticsearch/query_builder/query_clauses.rb b/lib/jay_api/elasticsearch/query_builder/query_clauses.rb index ebdb83c..beeeb12 100644 --- a/lib/jay_api/elasticsearch/query_builder/query_clauses.rb +++ b/lib/jay_api/elasticsearch/query_builder/query_clauses.rb @@ -31,8 +31,11 @@ class QueryClauses # If a block is given then +self+ is returned, if no block is given # then the +bool+ query clause is returned. def bool - clause ||= boolean_clause || ::JayAPI::Elasticsearch::QueryBuilder::QueryClauses::Bool.new - replace_top_level_clause(clause, force: boolean_query?) + clause = if boolean_query? + top_level_clause + else + self.top_level_clause = ::JayAPI::Elasticsearch::QueryBuilder::QueryClauses::Bool.new + end if block_given? yield clause @@ -50,7 +53,8 @@ def bool # @raise [JayAPI::Elasticsearch::QueryBuilder::Errors::QueryBuilderError] # If there is already a top level clause. def <<(query_clause) - replace_top_level_clause(query_clause) + self.top_level_clause = query_clause + self end # @return [Hash] The Hash representation of the Query Clauses set. @@ -125,37 +129,19 @@ def negate private - # Replaces the current top-level clause with the given clause. - # @param [JayAPI::Elasticsearch::QueryBuilder::QueryClauses::QueryClause] - # query_clause The query clause to add. - # @param [Boolean] force Forces the replacement of the top-level clause - # even if there is already a top-level clause in place. - # @return [JayAPI::Elasticsearch::QueryBuilder::QueryClauses] Returns - # itself so that other methods can be chained. - # @raise [JayAPI::Elasticsearch::QueryBuilder::Errors::QueryBuilderError] - # If there is already a top level clause and +force+ is +false+. - def replace_top_level_clause(query_clause, force: false) - single_top_level_clause! unless force - @top_level_clause = query_clause - self - end - - # @return [JayAPI::Elasticsearch::QueryBuilder::QueryClauses::Bool, nil] - # The current top-level clause if it is a Boolean clause, +nil+ - # otherwise. - def boolean_clause - boolean_query? ? top_level_clause : nil - end - + # @param [JayAPI::Elasticsearch::QueryBuilder::QueryClauses::QueryClause] clause + # The new top-level query clause. # @raise [JayAPI::Elasticsearch::QueryBuilder::Errors::QueryBuilderError] - # If there is already a top level clause. - def single_top_level_clause! - return unless top_level_clause + # If a top-level query clause already exists. + def top_level_clause=(clause) + if top_level_clause + raise ::JayAPI::Elasticsearch::QueryBuilder::Errors::QueryBuilderError, + 'Queries can only have one top-level query clause, ' \ + 'to use multiple clauses add a compound query, ' \ + 'for example: `bool`' + end - raise ::JayAPI::Elasticsearch::QueryBuilder::Errors::QueryBuilderError, - 'Queries can only have one top-level query clause, ' \ - 'to use multiple clauses add a compound query, ' \ - 'for example: `bool`' + @top_level_clause = clause end end end diff --git a/spec/jay_api/elasticsearch/query_builder/query_clauses_spec.rb b/spec/jay_api/elasticsearch/query_builder/query_clauses_spec.rb index 81f1cf4..26d1ffd 100644 --- a/spec/jay_api/elasticsearch/query_builder/query_clauses_spec.rb +++ b/spec/jay_api/elasticsearch/query_builder/query_clauses_spec.rb @@ -71,6 +71,10 @@ method_call end + it 'returns the same boolean clause that was created before' do + expect(method_call).to be(bool_clause) + end + it 'does not raise any errors' do expect { method_call }.not_to raise_error end @@ -93,6 +97,16 @@ end end + shared_examples_for '#<< when there a top-level clause already exists' do + it 'raises a JayAPI::Elasticsearch::QueryBuilder::Errors::QueryBuilderError' do + expect { method_call }.to raise_error( + JayAPI::Elasticsearch::QueryBuilder::Errors::QueryBuilderError, + 'Queries can only have one top-level query clause, to use multiple clauses ' \ + 'add a compound query, for example: `bool`' + ) + end + end + describe '#<<' do subject(:method_call) { query_clauses << query_clause } @@ -103,13 +117,13 @@ context 'when another clause has already been added' do before { query_clauses.wildcard(field: 'some_field', value: 'a*value') } - it 'raises a JayAPI::Elasticsearch::QueryBuilder::Errors::QueryBuilderError' do - expect { method_call }.to raise_error( - JayAPI::Elasticsearch::QueryBuilder::Errors::QueryBuilderError, - 'Queries can only have one top-level query clause, to use multiple ' \ - 'clauses add a compound query, for example: `bool`' - ) - end + it_behaves_like '#<< when there a top-level clause already exists' + end + + context 'when a boolean clause has already been added' do + before { query_clauses.bool } + + it_behaves_like '#<< when there a top-level clause already exists' end context 'when no other clause exists yet' do