scoped_search 4.1.12 → 4.1.13

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0fe5811549cf2e222ac16ea429293269abdd0734793b9e83611e76527acd905b
4
- data.tar.gz: 22463f4c28a03919dc7e42cd4942dcc3d66c0291bcb087fa5ad1688492726efd
3
+ metadata.gz: fbd1e857e3b248d6d585ac7c41679b536949dc945f4c7e067b2b16e86ce325b2
4
+ data.tar.gz: b4c1dc92102ff1d56b1f23406b16cf0523c6bdc17ab336ee92300993de5fd7f9
5
5
  SHA512:
6
- metadata.gz: 3e36707917762b0f2759da997bceb96b2f91b91bcbdb920d03a1738e408bc72a545e380f55bd5c35b9448d2916ac7ddb5dcc0ec623b6a36726d464ac818e15cb
7
- data.tar.gz: 1b0e4c026cffd08a3851a5929dd8ee7244c041c27d282789bac19fb7af77e2b0641e8d80cf52fcf8f8318190f15c647bcdf76ac98b3576c537a65a5250ec7784
6
+ metadata.gz: 1fe965444b5640251c4ca34c5fc1fca34857f2c8cc96a8f759096165391490ca7deb7f5b3f9d8ed8c9219a5ddfa82716660e2739adb5d7dfdb2d61ca95a968a7
7
+ data.tar.gz: f9ce7c87b95ceec5f3f5d1cc46f6401ef121870bf58a8cffe1b07cb7de597b8bcd3bcd1069e98ef52007df2209b26998f3f1c05a9719eefe17351d1f6da1eebf
@@ -31,7 +31,7 @@ module ScopedSearch::QueryLanguage::Parser
31
31
  next_token if !root_node && peek_token == :lparen # skip starting :lparen
32
32
  expressions << parse_logical_expression until peek_token.nil? || peek_token == :rparen
33
33
  next_token if !root_node && peek_token == :rparen # skip final :rparen
34
-
34
+
35
35
  return ScopedSearch::QueryLanguage::AST::LogicalOperatorNode.new(DEFAULT_SEQUENCE_OPERATOR, expressions, root_node)
36
36
  end
37
37
 
@@ -42,18 +42,23 @@ module ScopedSearch::QueryLanguage::Parser
42
42
  when :lparen; parse_expression_sequence
43
43
  when :not; parse_logical_not_expression
44
44
  when :null, :notnull; parse_null_expression
45
+ when *LOGICAL_INFIX_OPERATORS; parse_logical_infix_expression
45
46
  else; parse_comparison
46
47
  end
47
48
 
48
49
  if LOGICAL_INFIX_OPERATORS.include?(peek_token)
49
- operator = next_token
50
- rhs = parse_logical_expression
51
- ScopedSearch::QueryLanguage::AST::LogicalOperatorNode.new(operator, [lhs, rhs])
50
+ parse_logical_infix_expression([lhs])
52
51
  else
53
52
  lhs
54
53
  end
55
54
  end
56
55
 
56
+ def parse_logical_infix_expression(previous = [])
57
+ operator = next_token
58
+ rhs = parse_logical_expression
59
+ ScopedSearch::QueryLanguage::AST::LogicalOperatorNode.new(operator, previous + [rhs])
60
+ end
61
+
57
62
  # Parses a NOT expression
58
63
  def parse_logical_not_expression
59
64
  next_token # = skip NOT operator
@@ -80,7 +85,24 @@ module ScopedSearch::QueryLanguage::Parser
80
85
 
81
86
  # Parses a prefix comparison, i.e. without an explicit field: <operator> <value>
82
87
  def parse_prefix_comparison
83
- return ScopedSearch::QueryLanguage::AST::OperatorNode.new(next_token, [parse_value])
88
+ token = next_token
89
+ case token
90
+ when :in
91
+ parse_prefix_in(true)
92
+ when :notin
93
+ parse_prefix_in(false)
94
+ else
95
+ ScopedSearch::QueryLanguage::AST::OperatorNode.new(token, [parse_value])
96
+ end
97
+ end
98
+
99
+ def parse_prefix_in(inclusion)
100
+ cmp, log = inclusion ? [:eq, :or] : [:ne, :and]
101
+ leaves = parse_multiple_values.map do |x|
102
+ leaf = ScopedSearch::QueryLanguage::AST::LeafNode.new(x)
103
+ ScopedSearch::QueryLanguage::AST::OperatorNode.new(cmp, [leaf])
104
+ end
105
+ ScopedSearch::QueryLanguage::AST::LogicalOperatorNode.new(log, leaves)
84
106
  end
85
107
 
86
108
  # Parses an infix expression, i.e. <field> <operator> <value>
@@ -109,7 +131,7 @@ module ScopedSearch::QueryLanguage::Parser
109
131
  value = []
110
132
  value << current_token if String === next_token until peek_token.nil? || peek_token == :rparen
111
133
  next_token if peek_token == :rparen # consume the :rparen
112
- value.join(',')
134
+ value
113
135
  end
114
136
 
115
137
  # This can either be a constant value or a field name.
@@ -117,7 +139,7 @@ module ScopedSearch::QueryLanguage::Parser
117
139
  if String === peek_token
118
140
  ScopedSearch::QueryLanguage::AST::LeafNode.new(next_token)
119
141
  elsif ([:in, :notin].include? current_token)
120
- value = parse_multiple_values()
142
+ value = parse_multiple_values().join(',')
121
143
  ScopedSearch::QueryLanguage::AST::LeafNode.new(value)
122
144
  else
123
145
  raise ScopedSearch::QueryNotSupported, "Value expected but found #{peek_token.inspect}"
@@ -1,3 +1,3 @@
1
1
  module ScopedSearch
2
- VERSION = "4.1.12"
2
+ VERSION = "4.1.13"
3
3
  end
@@ -102,7 +102,27 @@ describe ScopedSearch::QueryLanguage::Parser do
102
102
  'set? a b null? c'.should parse_to([:and, [:notnull, 'a'], 'b', [:null, 'c']])
103
103
  end
104
104
 
105
+ it 'should parse logical operators with a single argument' do
106
+ '& a'.should parse_to('a')
107
+ '& & & & a & b & & &'.should parse_to([:and, 'a', 'b'])
108
+ end
109
+
110
+ it 'should parse in and not in operators with no lhs' do
111
+ '^ a'.should parse_to([:eq, 'a'])
112
+ '^ a b'.should parse_to([:or, [:eq, 'a'], [:eq, 'b']])
113
+ '^ a,b'.should parse_to([:or, [:eq, 'a'], [:eq, 'b']])
114
+
115
+ '^ (a b)'.should parse_to([:or, [:eq, 'a'], [:eq, 'b']])
116
+ '^ (a,b)'.should parse_to([:or, [:eq, 'a'], [:eq, 'b']])
117
+
118
+ '!^ a'.should parse_to([:ne, 'a'])
119
+ '!^ a b'.should parse_to([:and, [:ne, 'a'], [:ne, 'b']])
120
+ '!^ a,b'.should parse_to([:and, [:ne, 'a'], [:ne, 'b']])
121
+ '!^ (a b)'.should parse_to([:and, [:ne, 'a'], [:ne, 'b']])
122
+ '!^ (a,b)'.should parse_to([:and, [:ne, 'a'], [:ne, 'b']])
123
+ end
124
+
105
125
  it "should refuse to parse an empty not expression" do
106
126
  lambda { ScopedSearch::QueryLanguage::Compiler.parse('!()|*') }.should raise_error(ScopedSearch::QueryNotSupported)
107
- end
127
+ end
108
128
  end
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scoped_search
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.1.12
4
+ version: 4.1.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Amos Benari
8
8
  - Willem van Bergen
9
9
  - Wes Hays
10
- autorequire:
10
+ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2023-10-26 00:00:00.000000000 Z
13
+ date: 2024-12-03 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord
@@ -144,7 +144,7 @@ homepage: https://github.com/wvanbergen/scoped_search/wiki
144
144
  licenses:
145
145
  - MIT
146
146
  metadata: {}
147
- post_install_message:
147
+ post_install_message:
148
148
  rdoc_options:
149
149
  - "--title"
150
150
  - scoped_search
@@ -165,8 +165,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
165
165
  - !ruby/object:Gem::Version
166
166
  version: '0'
167
167
  requirements: []
168
- rubygems_version: 3.1.6
169
- signing_key:
168
+ rubygems_version: 3.3.27
169
+ signing_key:
170
170
  specification_version: 4
171
171
  summary: Easily search you ActiveRecord models with a simple query language using
172
172
  a named scope