dry-logic 0.1.4 → 0.2.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 +4 -4
- data/Gemfile +0 -1
- data/README.md +6 -2
- data/lib/dry/logic/evaluator.rb +46 -0
- data/lib/dry/logic/predicate.rb +3 -3
- data/lib/dry/logic/result.rb +26 -126
- data/lib/dry/logic/result/each.rb +10 -0
- data/lib/dry/logic/result/multi.rb +14 -0
- data/lib/dry/logic/result/named.rb +17 -0
- data/lib/dry/logic/result/set.rb +10 -0
- data/lib/dry/logic/result/value.rb +13 -0
- data/lib/dry/logic/rule.rb +14 -36
- data/lib/dry/logic/rule/attr.rb +3 -11
- data/lib/dry/logic/rule/check.rb +23 -22
- data/lib/dry/logic/rule/composite.rb +32 -12
- data/lib/dry/logic/rule/each.rb +3 -3
- data/lib/dry/logic/rule/key.rb +24 -5
- data/lib/dry/logic/rule/negation.rb +15 -0
- data/lib/dry/logic/rule/set.rb +9 -8
- data/lib/dry/logic/rule/value.rb +15 -3
- data/lib/dry/logic/rule_compiler.rb +8 -40
- data/lib/dry/logic/version.rb +1 -1
- data/spec/shared/predicates.rb +2 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/unit/rule/attr_spec.rb +5 -5
- data/spec/unit/rule/check_spec.rb +26 -39
- data/spec/unit/rule/conjunction_spec.rb +4 -4
- data/spec/unit/rule/disjunction_spec.rb +3 -3
- data/spec/unit/rule/each_spec.rb +2 -2
- data/spec/unit/rule/exclusive_disjunction_spec.rb +19 -0
- data/spec/unit/rule/implication_spec.rb +2 -2
- data/spec/unit/rule/key_spec.rb +103 -9
- data/spec/unit/rule/set_spec.rb +7 -9
- data/spec/unit/rule/value_spec.rb +29 -3
- data/spec/unit/rule_compiler_spec.rb +21 -49
- metadata +12 -9
- data/lib/dry/logic/rule/group.rb +0 -21
- data/lib/dry/logic/rule/result.rb +0 -33
- data/rakelib/rubocop.rake +0 -18
- data/spec/unit/rule/group_spec.rb +0 -12
- data/spec/unit/rule/result_spec.rb +0 -102
@@ -1,56 +1,43 @@
|
|
1
1
|
RSpec.describe Rule::Check do
|
2
2
|
include_context 'predicates'
|
3
3
|
|
4
|
-
let(:other) do
|
5
|
-
Rule::Value.new(:name, none?).or(Rule::Value.new(:name, filled?))
|
6
|
-
end
|
7
|
-
|
8
4
|
describe '#call' do
|
9
|
-
|
10
|
-
|
11
|
-
|
5
|
+
context 'with 1-level nesting' do
|
6
|
+
subject(:rule) do
|
7
|
+
Rule::Check.new(eql?.curry(1), name: :compare, keys: [:num])
|
8
|
+
end
|
12
9
|
|
13
|
-
|
14
|
-
|
15
|
-
|
10
|
+
it 'applies predicate to args extracted from the input' do
|
11
|
+
expect(rule.(num: 1)).to be_success
|
12
|
+
expect(rule.(num: 2)).to be_failure
|
16
13
|
|
17
|
-
|
18
|
-
|
14
|
+
expect(rule.(num: 1).to_ast).to eql(
|
15
|
+
[:input, [:compare, [
|
16
|
+
:result, [1, [:check, [:compare, [:predicate, [:eql?, [1]]]]]]]]
|
17
|
+
]
|
18
|
+
)
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
context '
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
it 'returns a failure' do
|
27
|
-
expect(rule.(nil)).to be_failure
|
22
|
+
context 'with 2-levels nesting' do
|
23
|
+
subject(:rule) do
|
24
|
+
Rule::Check.new(eql?, name: :compare, keys: [[:nums, :left], [:nums, :right]])
|
28
25
|
end
|
29
|
-
end
|
30
|
-
end
|
31
26
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
27
|
+
it 'applies predicate to args extracted from the input' do
|
28
|
+
expect(rule.(nums: { left: 1, right: 1 })).to be_success
|
29
|
+
expect(rule.(nums: { left: 1, right: 2 })).to be_failure
|
30
|
+
end
|
36
31
|
|
37
|
-
|
38
|
-
|
39
|
-
let(:input) { { address: 'Earth' } }
|
32
|
+
it 'curries args properly' do
|
33
|
+
result = rule.(nums: { left: 1, right: 2 })
|
40
34
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
:address, { address: 'Earth' },
|
45
|
-
[
|
46
|
-
[:check, [
|
47
|
-
:address, [
|
48
|
-
:input, [:user, { address: 'Earth' }, [
|
49
|
-
[:val, [:user, [:predicate, [:hash?, []]]]]]]]
|
50
|
-
]]
|
35
|
+
expect(result.to_ast).to eql([
|
36
|
+
:input, [:compare, [
|
37
|
+
:result, [1, [:check, [:compare, [:predicate, [:eql?, [2]]]]]]]
|
51
38
|
]
|
52
|
-
]
|
53
|
-
|
39
|
+
])
|
40
|
+
end
|
54
41
|
end
|
55
42
|
end
|
56
43
|
end
|
@@ -3,8 +3,8 @@ RSpec.describe Rule::Composite::Conjunction do
|
|
3
3
|
|
4
4
|
subject(:rule) { Rule::Composite::Conjunction.new(left, right) }
|
5
5
|
|
6
|
-
let(:left) { Rule::Value.new(
|
7
|
-
let(:right) { Rule::Value.new(
|
6
|
+
let(:left) { Rule::Value.new(int?) }
|
7
|
+
let(:right) { Rule::Value.new(gt?.curry(18)) }
|
8
8
|
|
9
9
|
describe '#call' do
|
10
10
|
it 'calls left and right' do
|
@@ -13,7 +13,7 @@ RSpec.describe Rule::Composite::Conjunction do
|
|
13
13
|
end
|
14
14
|
|
15
15
|
describe '#and' do
|
16
|
-
let(:other) { Rule::Value.new(
|
16
|
+
let(:other) { Rule::Value.new(lt?.curry(30)) }
|
17
17
|
|
18
18
|
it 'creates conjunction with the other' do
|
19
19
|
expect(rule.and(other).(31)).to be_failure
|
@@ -21,7 +21,7 @@ RSpec.describe Rule::Composite::Conjunction do
|
|
21
21
|
end
|
22
22
|
|
23
23
|
describe '#or' do
|
24
|
-
let(:other) { Rule::Value.new(
|
24
|
+
let(:other) { Rule::Value.new(lt?.curry(14)) }
|
25
25
|
|
26
26
|
it 'creates disjunction with the other' do
|
27
27
|
expect(rule.or(other).(13)).to be_success
|
@@ -3,11 +3,11 @@ RSpec.describe Rule::Composite::Disjunction do
|
|
3
3
|
|
4
4
|
subject(:rule) { Rule::Composite::Disjunction.new(left, right) }
|
5
5
|
|
6
|
-
let(:left) { Rule::Value.new(
|
7
|
-
let(:right) { Rule::Value.new(
|
6
|
+
let(:left) { Rule::Value.new(none?) }
|
7
|
+
let(:right) { Rule::Value.new(gt?.curry(18)) }
|
8
8
|
|
9
9
|
let(:other) do
|
10
|
-
Rule::Value.new(
|
10
|
+
Rule::Value.new(int?) & Rule::Value.new(lt?.curry(14))
|
11
11
|
end
|
12
12
|
|
13
13
|
describe '#call' do
|
data/spec/unit/rule/each_spec.rb
CHANGED
@@ -4,10 +4,10 @@ RSpec.describe Dry::Logic::Rule::Each do
|
|
4
4
|
include_context 'predicates'
|
5
5
|
|
6
6
|
subject(:address_rule) do
|
7
|
-
Dry::Logic::Rule::Each.new(
|
7
|
+
Dry::Logic::Rule::Each.new(is_string)
|
8
8
|
end
|
9
9
|
|
10
|
-
let(:is_string) { Dry::Logic::Rule::Value.new(
|
10
|
+
let(:is_string) { Dry::Logic::Rule::Value.new(str?) }
|
11
11
|
|
12
12
|
describe '#call' do
|
13
13
|
it 'applies its rules to all elements in the input' do
|
@@ -0,0 +1,19 @@
|
|
1
|
+
RSpec.describe Rule::ExclusiveDisjunction do
|
2
|
+
include_context 'predicates'
|
3
|
+
|
4
|
+
subject(:rule) do
|
5
|
+
Rule::ExclusiveDisjunction.new(left, right)
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:left) { Rule::Key.new(true?, name: :eat_cake) }
|
9
|
+
let(:right) { Rule::Key.new(true?, name: :have_cake) }
|
10
|
+
|
11
|
+
describe '#call' do
|
12
|
+
it 'calls left and right' do
|
13
|
+
expect(rule.(eat_cake: true, have_cake: false)).to be_success
|
14
|
+
expect(rule.(eat_cake: false, have_cake: true)).to be_success
|
15
|
+
expect(rule.(eat_cake: false, have_cake: false)).to be_failure
|
16
|
+
expect(rule.(eat_cake: true, have_cake: true)).to be_failure
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -3,8 +3,8 @@ RSpec.describe Rule::Composite::Implication do
|
|
3
3
|
|
4
4
|
subject(:rule) { Rule::Composite::Implication.new(left, right) }
|
5
5
|
|
6
|
-
let(:left) { Rule::Value.new(
|
7
|
-
let(:right) { Rule::Value.new(
|
6
|
+
let(:left) { Rule::Value.new(int?) }
|
7
|
+
let(:right) { Rule::Value.new(gt?.curry(18)) }
|
8
8
|
|
9
9
|
describe '#call' do
|
10
10
|
it 'calls left and right' do
|
data/spec/unit/rule/key_spec.rb
CHANGED
@@ -1,27 +1,121 @@
|
|
1
1
|
require 'dry/logic/rule'
|
2
2
|
|
3
|
-
RSpec.describe
|
3
|
+
RSpec.describe Rule::Key do
|
4
4
|
include_context 'predicates'
|
5
5
|
|
6
|
-
subject(:rule)
|
6
|
+
subject(:rule) do
|
7
|
+
Rule::Key.new(predicate, name: :user)
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:predicate) do
|
11
|
+
key?.curry(:name)
|
12
|
+
end
|
7
13
|
|
8
14
|
describe '#call' do
|
9
|
-
|
10
|
-
|
11
|
-
|
15
|
+
context 'with a plain predicate' do
|
16
|
+
it 'applies predicate to the value' do
|
17
|
+
expect(rule.(user: { name: 'Jane' })).to be_success
|
18
|
+
expect(rule.(user: {})).to be_failure
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'with a custom predicate' do
|
22
|
+
let(:predicate) { -> input { double(success?: true, to_ast: [:foo]) } }
|
23
|
+
|
24
|
+
let(:result) { rule.(test: true) }
|
25
|
+
|
26
|
+
it 'delegates to_ast to response' do
|
27
|
+
expect(result.to_ast).to eql([:foo])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'with a set rule as predicate' do
|
33
|
+
subject(:rule) do
|
34
|
+
Rule::Key.new(predicate, name: :address)
|
35
|
+
end
|
36
|
+
|
37
|
+
let(:predicate) do
|
38
|
+
Rule::Set.new(
|
39
|
+
[Rule::Value.new(key?.curry(:city)), Rule::Value.new(key?.curry(:zipcode))]
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'applies set rule to the value that passes' do
|
44
|
+
result = rule.(address: { city: 'NYC', zipcode: '123' })
|
45
|
+
|
46
|
+
expect(result).to be_success
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'applies set rule to the value that fails' do
|
50
|
+
result = rule.(address: { city: 'NYC' })
|
51
|
+
|
52
|
+
expect(result).to be_failure
|
53
|
+
|
54
|
+
expect(result.to_ast).to eql([
|
55
|
+
:input, [
|
56
|
+
:address,
|
57
|
+
[:result, [
|
58
|
+
{ city: "NYC" },
|
59
|
+
[:set, [[:result, [{ city: 'NYC' }, [:val, [:predicate, [:key?, [:zipcode]]]]]]]]
|
60
|
+
]]
|
61
|
+
]
|
62
|
+
])
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'with an each rule as predicate' do
|
67
|
+
subject(:rule) do
|
68
|
+
Rule::Key.new(predicate, name: :nums)
|
69
|
+
end
|
70
|
+
|
71
|
+
let(:predicate) do
|
72
|
+
Rule::Each.new(Rule::Value.new(str?))
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'applies each rule to the value that passses' do
|
76
|
+
result = rule.(nums: %w(1 2 3))
|
77
|
+
|
78
|
+
expect(result).to be_success
|
79
|
+
|
80
|
+
expect(result.to_ast).to eql([
|
81
|
+
:input, [:nums, [:result, [%w(1 2 3), [:each, []]]]]
|
82
|
+
])
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'applies each rule to the value that fails' do
|
86
|
+
failure = rule.(nums: [1, '3', 3])
|
87
|
+
|
88
|
+
expect(failure).to be_failure
|
89
|
+
|
90
|
+
expect(failure.to_ast).to eql([
|
91
|
+
:input, [
|
92
|
+
:nums, [
|
93
|
+
:result, [
|
94
|
+
[1, '3', 3],
|
95
|
+
[:each, [
|
96
|
+
[:el, [0, [:result, [1, [:val, [:predicate, [:str?, []]]]]]]],
|
97
|
+
[:el, [2, [:result, [3, [:val, [:predicate, [:str?, []]]]]]]]
|
98
|
+
]]
|
99
|
+
]
|
100
|
+
]
|
101
|
+
]
|
102
|
+
])
|
103
|
+
end
|
12
104
|
end
|
13
105
|
end
|
14
106
|
|
15
107
|
describe '#and' do
|
16
|
-
let(:other)
|
108
|
+
let(:other) do
|
109
|
+
Rule::Key.new(str?, name: [:user, :name])
|
110
|
+
end
|
17
111
|
|
18
112
|
it 'returns conjunction rule where value is passed to the right' do
|
19
113
|
present_and_string = rule.and(other)
|
20
114
|
|
21
|
-
expect(present_and_string.(name: 'Jane')).to be_success
|
115
|
+
expect(present_and_string.(user: { name: 'Jane' })).to be_success
|
22
116
|
|
23
|
-
expect(present_and_string.({})).to be_failure
|
24
|
-
expect(present_and_string.(name: 1)).to be_failure
|
117
|
+
expect(present_and_string.(user: {})).to be_failure
|
118
|
+
expect(present_and_string.(user: { name: 1 })).to be_failure
|
25
119
|
end
|
26
120
|
end
|
27
121
|
end
|
data/spec/unit/rule/set_spec.rb
CHANGED
@@ -4,11 +4,11 @@ RSpec.describe Dry::Logic::Rule::Set do
|
|
4
4
|
include_context 'predicates'
|
5
5
|
|
6
6
|
subject(:rule) do
|
7
|
-
Dry::Logic::Rule::Set.new(
|
7
|
+
Dry::Logic::Rule::Set.new([is_string, min_size.curry(6)])
|
8
8
|
end
|
9
9
|
|
10
|
-
let(:is_string) { Dry::Logic::Rule::Value.new(
|
11
|
-
let(:min_size) { Dry::Logic::Rule::Value.new(
|
10
|
+
let(:is_string) { Dry::Logic::Rule::Value.new(str?) }
|
11
|
+
let(:min_size) { Dry::Logic::Rule::Value.new(min_size?) }
|
12
12
|
|
13
13
|
describe '#call' do
|
14
14
|
it 'applies its rules to the input' do
|
@@ -17,14 +17,12 @@ RSpec.describe Dry::Logic::Rule::Set do
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
describe '#
|
20
|
+
describe '#to_ast' do
|
21
21
|
it 'returns an array representation' do
|
22
|
-
expect(rule).to
|
22
|
+
expect(rule.to_ast).to eql([
|
23
23
|
:set, [
|
24
|
-
:
|
25
|
-
|
26
|
-
[:val, [:name, [:predicate, [:min_size?, [6]]]]]
|
27
|
-
]
|
24
|
+
[:val, [:predicate, [:str?, []]]],
|
25
|
+
[:val, [:predicate, [:min_size?, [6]]]]
|
28
26
|
]
|
29
27
|
])
|
30
28
|
end
|
@@ -3,17 +3,43 @@ require 'dry/logic/rule'
|
|
3
3
|
RSpec.describe Dry::Logic::Rule::Value do
|
4
4
|
include_context 'predicates'
|
5
5
|
|
6
|
-
let(:is_nil) { Dry::Logic::Rule::Value.new(
|
6
|
+
let(:is_nil) { Dry::Logic::Rule::Value.new(none?) }
|
7
7
|
|
8
|
-
let(:is_string) { Dry::Logic::Rule::Value.new(
|
8
|
+
let(:is_string) { Dry::Logic::Rule::Value.new(str?) }
|
9
9
|
|
10
|
-
let(:min_size) { Dry::Logic::Rule::Value.new(
|
10
|
+
let(:min_size) { Dry::Logic::Rule::Value.new(min_size?) }
|
11
11
|
|
12
12
|
describe '#call' do
|
13
13
|
it 'returns result of a predicate' do
|
14
14
|
expect(is_string.(1)).to be_failure
|
15
15
|
expect(is_string.('1')).to be_success
|
16
16
|
end
|
17
|
+
|
18
|
+
context 'with a custom predicate' do
|
19
|
+
subject(:rule) { Dry::Logic::Rule::Value.new(predicate) }
|
20
|
+
|
21
|
+
let(:response) { double(success?: true) }
|
22
|
+
let(:predicate) { -> input { Result.new(response, double, input) } }
|
23
|
+
|
24
|
+
let(:result) { rule.(test: true) }
|
25
|
+
|
26
|
+
it 'calls its predicate returning custom result' do
|
27
|
+
expect(result).to be_success
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'exposes access to nested result' do
|
31
|
+
expect(response).to receive(:[]).with(:foo).and_return(:bar)
|
32
|
+
expect(result[:foo]).to be(:bar)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'returns nil from [] when response does not respond to it' do
|
36
|
+
expect(result[:foo]).to be(nil)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'has no name by default' do
|
40
|
+
expect(result.name).to be(nil)
|
41
|
+
end
|
42
|
+
end
|
17
43
|
end
|
18
44
|
|
19
45
|
describe '#and' do
|
@@ -8,58 +8,44 @@ RSpec.describe Dry::Logic::RuleCompiler, '#call' do
|
|
8
8
|
attr?: predicate,
|
9
9
|
filled?: predicate,
|
10
10
|
gt?: predicate,
|
11
|
-
|
12
|
-
left: res_left_rule,
|
13
|
-
right: double(input: 312) }
|
11
|
+
one: predicate }
|
14
12
|
}
|
15
13
|
|
16
14
|
let(:predicate) { double(:predicate).as_null_object }
|
17
15
|
|
18
|
-
let(:
|
19
|
-
let(:
|
20
|
-
let(:attr_rule) { Rule::Attr.new(:email
|
21
|
-
let(:
|
22
|
-
let(:check_rule) { Rule::Check
|
23
|
-
let(:res_rule) { Rule::Result.new(:email, predicates[:email]) }
|
24
|
-
let(:res_left_rule) { Rule::Result.new(:left, predicate) }
|
16
|
+
let(:val_rule) { Rule::Value.new(predicate) }
|
17
|
+
let(:key_rule) { Rule::Key.new(predicate, name: :email) }
|
18
|
+
let(:attr_rule) { Rule::Attr.new(predicate, name: :email) }
|
19
|
+
let(:not_key_rule) { Rule::Key.new(predicate, name: :email).negation }
|
20
|
+
let(:check_rule) { Rule::Check.new(predicate, name: :email, keys: [:email]) }
|
25
21
|
let(:and_rule) { key_rule & val_rule }
|
26
22
|
let(:or_rule) { key_rule | val_rule }
|
27
23
|
let(:xor_rule) { key_rule ^ val_rule }
|
28
|
-
let(:set_rule) { Rule::Set.new(
|
29
|
-
let(:each_rule) { Rule::Each.new(
|
24
|
+
let(:set_rule) { Rule::Set.new([val_rule]) }
|
25
|
+
let(:each_rule) { Rule::Each.new(val_rule) }
|
30
26
|
|
31
27
|
it 'compiles key rules' do
|
32
|
-
ast = [[:key, [:email, [:predicate, [:
|
28
|
+
ast = [[:key, [:email, [:predicate, [:filled?, []]]]]]
|
33
29
|
|
34
30
|
rules = compiler.(ast)
|
35
31
|
|
36
32
|
expect(rules).to eql([key_rule])
|
37
33
|
end
|
38
34
|
|
39
|
-
it 'compiles
|
40
|
-
ast = [[:
|
41
|
-
|
42
|
-
rules = compiler.(ast)
|
43
|
-
|
44
|
-
expect(rules).to eql([check_rule])
|
45
|
-
end
|
46
|
-
|
47
|
-
it 'compiles result rules' do
|
48
|
-
ast = [[:res, [:email, [:predicate, [:email, [:filled?]]]]]]
|
35
|
+
it 'compiles attr rules' do
|
36
|
+
ast = [[:attr, [:email, [:predicate, [:filled?, []]]]]]
|
49
37
|
|
50
38
|
rules = compiler.(ast)
|
51
39
|
|
52
|
-
expect(rules).to eql([
|
40
|
+
expect(rules).to eql([attr_rule])
|
53
41
|
end
|
54
42
|
|
55
|
-
it 'compiles
|
56
|
-
ast = [[:
|
57
|
-
|
58
|
-
expect(predicate).to receive(:curry).with(312)
|
43
|
+
it 'compiles check rules' do
|
44
|
+
ast = [[:check, [:email, [:predicate, [:filled?, []]]]]]
|
59
45
|
|
60
46
|
rules = compiler.(ast)
|
61
47
|
|
62
|
-
expect(rules).to eql([
|
48
|
+
expect(rules).to eql([check_rule])
|
63
49
|
end
|
64
50
|
|
65
51
|
it 'compiles attr rules' do
|
@@ -71,7 +57,7 @@ RSpec.describe Dry::Logic::RuleCompiler, '#call' do
|
|
71
57
|
end
|
72
58
|
|
73
59
|
it 'compiles negated rules' do
|
74
|
-
ast = [[:not, [:key, [:email, [:predicate, [:
|
60
|
+
ast = [[:not, [:key, [:email, [:predicate, [:filled?, []]]]]]]
|
75
61
|
|
76
62
|
rules = compiler.(ast)
|
77
63
|
|
@@ -83,7 +69,7 @@ RSpec.describe Dry::Logic::RuleCompiler, '#call' do
|
|
83
69
|
[
|
84
70
|
:and, [
|
85
71
|
[:key, [:email, [:predicate, [:key?, []]]]],
|
86
|
-
[:val, [:
|
72
|
+
[:val, [:predicate, [:filled?, []]]]
|
87
73
|
]
|
88
74
|
]
|
89
75
|
]
|
@@ -98,7 +84,7 @@ RSpec.describe Dry::Logic::RuleCompiler, '#call' do
|
|
98
84
|
[
|
99
85
|
:or, [
|
100
86
|
[:key, [:email, [:predicate, [:key?, []]]]],
|
101
|
-
[:val, [:
|
87
|
+
[:val, [:predicate, [:filled?, []]]]
|
102
88
|
]
|
103
89
|
]
|
104
90
|
]
|
@@ -113,7 +99,7 @@ RSpec.describe Dry::Logic::RuleCompiler, '#call' do
|
|
113
99
|
[
|
114
100
|
:xor, [
|
115
101
|
[:key, [:email, [:predicate, [:key?, []]]]],
|
116
|
-
[:val, [:
|
102
|
+
[:val, [:predicate, [:filled?, []]]]
|
117
103
|
]
|
118
104
|
]
|
119
105
|
]
|
@@ -124,15 +110,7 @@ RSpec.describe Dry::Logic::RuleCompiler, '#call' do
|
|
124
110
|
end
|
125
111
|
|
126
112
|
it 'compiles set rules' do
|
127
|
-
ast = [
|
128
|
-
[
|
129
|
-
:set, [
|
130
|
-
:email, [
|
131
|
-
[:val, [:email, [:predicate, [:filled?, []]]]]
|
132
|
-
]
|
133
|
-
]
|
134
|
-
]
|
135
|
-
]
|
113
|
+
ast = [[:set, [[:val, [:predicate, [:filled?, []]]]]]]
|
136
114
|
|
137
115
|
rules = compiler.(ast)
|
138
116
|
|
@@ -140,13 +118,7 @@ RSpec.describe Dry::Logic::RuleCompiler, '#call' do
|
|
140
118
|
end
|
141
119
|
|
142
120
|
it 'compiles each rules' do
|
143
|
-
ast = [
|
144
|
-
[
|
145
|
-
:each, [
|
146
|
-
:email, [:val, [:email, [:predicate, [:filled?, []]]]]
|
147
|
-
]
|
148
|
-
]
|
149
|
-
]
|
121
|
+
ast = [[:each, [:val, [:predicate, [:filled?, []]]]]]
|
150
122
|
|
151
123
|
rules = compiler.(ast)
|
152
124
|
|