dry-logic 0.1.4 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|