predicate 2.5.0 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4bd1cc5bc76250463f8dd68f07852df3838d8e9e553da27b188a87d968f83e5d
4
- data.tar.gz: eab52fff1970e5a74f21170e6486ec8082065be352053206b819fec2a2da3075
3
+ metadata.gz: 4d0149b8d39635ed0f27c39362d1c4aec0dc5f2ccc1290580ed67edf18414e5b
4
+ data.tar.gz: a623594513754521196f1a98f5d2f682650a3ec1b02b02b4dfa703600039faa1
5
5
  SHA512:
6
- metadata.gz: b3b4f2354d525a6c7a80de4fe6edba8459270ab34a2a5f15e17f233d485761b2c8e2f4c86c93349b2ffc06380cd37a4621da0df6ffa14672d1b43fa24ae9f428
7
- data.tar.gz: af95ddb5a971f2f7631046ed59e05982a5ff5309cbb1ac1a892c949ac9ed7305f4188f40616efce485978854561a756b3a722c0db192abb0b42e925beed42834
6
+ metadata.gz: dfc8fdb19e1d61171a4c91e893bfc6b6b91d559d8402f3a47dbede8d09dcb2f702f697cbd9e8b6db688e896d1831f837ace44d8c78b8c0e110d767ac0f99db05
7
+ data.tar.gz: 21ffbda2c7831051ac8ffba6a5c84d029735ce953e3fc969ae252945b0417ea28bc05f865e0e4e29771b542ca2993ec3720389a7be012b96b378536fb0743602
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Predicate
2
2
 
3
+ ![](https://travis-ci.com/enspirit/predicate.svg?branch=master)
4
+
3
5
  Boolean (truth-value) expressions that can be evaluated, manipulated,
4
6
  optimized, translated to code, etc.
5
7
 
@@ -160,6 +160,14 @@ class Predicate
160
160
 
161
161
  public # Low-level
162
162
 
163
+ # Factors a predicate from a mapping between variables
164
+ # and values. This typically generates a AND(EQ)
165
+ # predicate, but a value can be an Array (IN) or a
166
+ # Regexp (MATCH).
167
+ def h(h)
168
+ from_hash(h, :eq)
169
+ end
170
+
163
171
  # Factors a predicate for a ruby Proc that returns
164
172
  # truth-value for a single argument.
165
173
  def native(arg)
@@ -182,10 +190,10 @@ class Predicate
182
190
  tautology
183
191
  else
184
192
  terms = h.to_a.map{|(k,v)|
185
- if v.is_a?(Array)
186
- [:in, sexpr(k), sexpr(v)]
187
- else
188
- [op, sexpr(k), sexpr(v)]
193
+ case v
194
+ when Array then [:in, sexpr(k), sexpr(v)]
195
+ when Regexp then [:match, sexpr(k), sexpr(v) ]
196
+ else [op, sexpr(k), sexpr(v)]
189
197
  end
190
198
  }
191
199
  terms = terms.size == 1 ? terms.first : terms.unshift(:and)
@@ -1,7 +1,7 @@
1
1
  class Predicate
2
2
  module Version
3
3
  MAJOR = 2
4
- MINOR = 5
4
+ MINOR = 6
5
5
  TINY = 0
6
6
  end
7
7
  VERSION = "#{Version::MAJOR}.#{Version::MINOR}.#{Version::TINY}"
@@ -10,7 +10,15 @@ class Predicate
10
10
  it{ should eq(Factory.tautology) }
11
11
  end
12
12
 
13
- context "when the hash is singleton" do
13
+ context "when the hash is a singelton" do
14
+ let(:h){ {:x => 12} }
15
+
16
+ it_should_behave_like "a predicate AST node"
17
+ it{ should be_a(Eq) }
18
+ it{ should eq([:eq, [:identifier, :x], [:literal, 12]]) }
19
+ end
20
+
21
+ context "when the hash is not singleton" do
14
22
  let(:h){ {:x => 12, :y => :z} }
15
23
  let(:expected){
16
24
  [:and,
@@ -23,12 +31,27 @@ class Predicate
23
31
  it{ should eq(expected) }
24
32
  end
25
33
 
26
- context "when the hash is not singelton" do
27
- let(:h){ {:x => 12} }
34
+ context "when the value is a Regexp" do
35
+ let(:rx){ /[a-z]+/ }
36
+ let(:h){ {:x => /[a-z]+/} }
28
37
 
29
38
  it_should_behave_like "a predicate AST node"
30
- it{ should be_a(Eq) }
31
- it{ should eq([:eq, [:identifier, :x], [:literal, 12]]) }
39
+ it{ should be_a(Match) }
40
+ it{ should eq([:match, [:identifier, :x], [:literal, rx]]) }
41
+ end
42
+
43
+ context "when the hash mixes value types" do
44
+ let(:rx){ /[a-z]+/ }
45
+ let(:h){ {:x => 12, :y => rx} }
46
+ let(:expected){
47
+ [:and,
48
+ [:eq, [:identifier, :x], [:literal, 12]],
49
+ [:match, [:identifier, :y], [:literal, rx]]]
50
+ }
51
+
52
+ it_should_behave_like "a predicate AST node"
53
+ it{ should be_a(And) }
54
+ it{ should eq(expected) }
32
55
  end
33
56
 
34
57
  end
@@ -140,6 +140,15 @@ class Predicate
140
140
  end
141
141
  end
142
142
 
143
+ context 'nary and' do
144
+ let(:predicate) { Predicate.eq(:name, "Bob") & Predicate.eq(:price, 10.0) & Predicate.eq(:city, "London") }
145
+
146
+ it 'works as expected' do
147
+ puts predicate.sexpr.inspect
148
+ expect(subject).to eql("SELECT * FROM `items` WHERE ((`name` = 'Bob') AND (`price` = 10.0) AND (`city` = 'London'))")
149
+ end
150
+ end
151
+
143
152
  context 'or' do
144
153
  let(:predicate) { Predicate.eq(:name, "Bob") | Predicate.lt(:price, 10.0) }
145
154
 
@@ -18,6 +18,16 @@ describe "Predicate.comp" do
18
18
  it_should_behave_like "a predicate"
19
19
  end
20
20
 
21
+ describe "Predicate.h" do
22
+ subject{ Predicate.h(:x => 2) }
23
+
24
+ it_should_behave_like "a predicate"
25
+
26
+ it 'should be a eq on x' do
27
+ expect(subject).to eql(Predicate.eq(:x => 2))
28
+ end
29
+ end
30
+
21
31
  describe "Predicate.in, with a list" do
22
32
  subject{ Predicate.in(:x, [2, 3]) }
23
33
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: predicate
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.0
4
+ version: 2.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bernard Lambeau
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-12-30 00:00:00.000000000 Z
11
+ date: 2021-12-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sexpr
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.6.0
19
+ version: '1.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.6.0
26
+ version: '1.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement