dry-logic 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -0
- data/lib/dry/logic/result.rb +24 -24
- data/lib/dry/logic/rule/check.rb +20 -3
- data/lib/dry/logic/rule/composite.rb +1 -1
- data/lib/dry/logic/rule/result.rb +4 -0
- data/lib/dry/logic/rule_compiler.rb +23 -4
- data/lib/dry/logic/version.rb +1 -1
- data/spec/unit/rule/check_spec.rb +7 -5
- data/spec/unit/rule/result_spec.rb +4 -4
- data/spec/unit/rule_compiler_spec.rb +16 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5d49a2ea6e71727f4ae69320aa0619c2ebd96325
|
4
|
+
data.tar.gz: 71414bb0ff667758b7a95fb0379025bd55465b2e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b49f6272d981acc3fe076096ab9beb5c0d8aa57c5956ca88603d6187bd64e0285ec6bda802d4bc9f39b44927b71bc8a095834ea78e91dcee2d2816483bb9c071
|
7
|
+
data.tar.gz: a1f2dbdd21ddf76e986036aacc3949433103335f842ae2ee3bcd603716c744b214800ed47129a0a23aa3564b13a65c914edaab8417dfde1b7046dd3c3127cb9f
|
data/CHANGELOG.md
CHANGED
@@ -1,9 +1,23 @@
|
|
1
|
+
# v0.1.2 2016-01-27
|
2
|
+
|
3
|
+
### Added
|
4
|
+
|
5
|
+
* Support for resolving input from `Rule::Result` (solnic)
|
6
|
+
|
7
|
+
### Changed
|
8
|
+
|
9
|
+
* `Check` and `Result` carry original input(s) (solnic)
|
10
|
+
|
11
|
+
[Compare v0.1.2...v0.1.3](https://github.com/dryrb/dry-logic/compare/v0.1.2...v0.1.3)
|
12
|
+
|
1
13
|
# v0.1.2 2016-01-19
|
2
14
|
|
3
15
|
### Fixed
|
4
16
|
|
5
17
|
* `xor` returns wrapped results when used against another result-rule (solnic)
|
6
18
|
|
19
|
+
[Compare v0.1.1...v0.1.2](https://github.com/dryrb/dry-logic/compare/v0.1.1...v0.1.2)
|
20
|
+
|
7
21
|
# v0.1.1 2016-01-18
|
8
22
|
|
9
23
|
### Added
|
data/lib/dry/logic/result.rb
CHANGED
@@ -23,15 +23,37 @@ module Dry
|
|
23
23
|
|
24
24
|
def to_ary
|
25
25
|
indices = value.map { |v| v.failure? ? value.index(v) : nil }.compact
|
26
|
-
[:input, [
|
26
|
+
[:input, [name, input, value.values_at(*indices).map(&:to_ary)]]
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
30
|
class Result::Value < Result
|
31
|
+
def to_ary
|
32
|
+
[:input, [name, input, [rule.to_ary]]]
|
33
|
+
end
|
34
|
+
alias_method :to_a, :to_ary
|
35
|
+
end
|
36
|
+
|
37
|
+
class Result::LazyValue < Result
|
31
38
|
def to_ary
|
32
39
|
[:input, [rule.name, input, [rule.to_ary]]]
|
33
40
|
end
|
34
41
|
alias_method :to_a, :to_ary
|
42
|
+
|
43
|
+
def input
|
44
|
+
success? ? rule.evaluate_input(@input) : @input
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class Result::Wrapped < Result::Value
|
49
|
+
def to_ary
|
50
|
+
[:input, [rule.name, rule.evaluate_input(input), [rule.to_ary]]]
|
51
|
+
end
|
52
|
+
alias_method :to_a, :to_ary
|
53
|
+
|
54
|
+
def wrapped?
|
55
|
+
true
|
56
|
+
end
|
35
57
|
end
|
36
58
|
|
37
59
|
class Result::Verified < Result
|
@@ -59,28 +81,6 @@ module Dry
|
|
59
81
|
end
|
60
82
|
end
|
61
83
|
|
62
|
-
class Result::LazyValue < Result
|
63
|
-
def to_ary
|
64
|
-
[:input, [rule.name, input, [rule.to_ary]]]
|
65
|
-
end
|
66
|
-
alias_method :to_a, :to_ary
|
67
|
-
|
68
|
-
def input
|
69
|
-
success? ? rule.evaluate_input(@input) : @input
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
class Result::Wrapped < Result
|
74
|
-
def to_ary
|
75
|
-
[:input, [name, nil, [rule.to_ary]]]
|
76
|
-
end
|
77
|
-
alias_method :to_a, :to_ary
|
78
|
-
|
79
|
-
def wrapped?
|
80
|
-
true
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
84
|
def initialize(input, value, rule)
|
85
85
|
@input = input
|
86
86
|
@value = value
|
@@ -104,7 +104,7 @@ module Dry
|
|
104
104
|
self.class.new(input, !value, rule)
|
105
105
|
end
|
106
106
|
|
107
|
-
def
|
107
|
+
def then(other)
|
108
108
|
if success?
|
109
109
|
other.(input)
|
110
110
|
else
|
data/lib/dry/logic/rule/check.rb
CHANGED
@@ -1,10 +1,27 @@
|
|
1
1
|
module Dry
|
2
2
|
module Logic
|
3
3
|
class Rule::Check < Rule
|
4
|
-
|
4
|
+
attr_reader :keys
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
class Unary < Rule::Check
|
7
|
+
def evaluate_input(*)
|
8
|
+
predicate.input
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Binary < Rule::Check
|
13
|
+
def evaluate_input(result)
|
14
|
+
keys.map { |key| result[key].input }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(name, predicate, keys)
|
19
|
+
super(name, predicate)
|
20
|
+
@keys = keys
|
21
|
+
end
|
22
|
+
|
23
|
+
def call(result)
|
24
|
+
Logic.Result(evaluate_input(result), predicate.(result), self)
|
8
25
|
end
|
9
26
|
|
10
27
|
def type
|
@@ -10,7 +10,7 @@ module Dry
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def call(ast)
|
13
|
-
ast.map { |node| visit(node) }
|
13
|
+
ast.to_ary.map { |node| visit(node) }
|
14
14
|
end
|
15
15
|
|
16
16
|
def visit(node)
|
@@ -19,8 +19,10 @@ module Dry
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def visit_check(node)
|
22
|
-
name, predicate = node
|
23
|
-
|
22
|
+
name, predicate, keys = node
|
23
|
+
check_keys = keys ? keys : [name]
|
24
|
+
klass = check_keys.size == 1 ? Rule::Check::Unary : Rule::Check::Binary
|
25
|
+
klass.new(name, visit(predicate), check_keys)
|
24
26
|
end
|
25
27
|
|
26
28
|
def visit_res(node)
|
@@ -28,6 +30,18 @@ module Dry
|
|
28
30
|
Rule::Result.new(name, visit(predicate))
|
29
31
|
end
|
30
32
|
|
33
|
+
def visit_args(nodes)
|
34
|
+
nodes.map { |node| visit(node) }
|
35
|
+
end
|
36
|
+
|
37
|
+
def visit_res_arg(name)
|
38
|
+
predicates[name].input
|
39
|
+
end
|
40
|
+
|
41
|
+
def visit_arg(value)
|
42
|
+
value
|
43
|
+
end
|
44
|
+
|
31
45
|
def visit_not(node)
|
32
46
|
visit(node).negation
|
33
47
|
end
|
@@ -59,7 +73,12 @@ module Dry
|
|
59
73
|
|
60
74
|
def visit_predicate(node)
|
61
75
|
name, args = node
|
62
|
-
|
76
|
+
|
77
|
+
if args[0] == :args
|
78
|
+
predicates[name].curry(*visit(args))
|
79
|
+
else
|
80
|
+
predicates[name].curry(*args)
|
81
|
+
end
|
63
82
|
end
|
64
83
|
|
65
84
|
def visit_and(node)
|
data/lib/dry/logic/version.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
RSpec.describe Rule::Check do
|
2
|
-
subject(:rule)
|
2
|
+
subject(:rule) do
|
3
|
+
Rule::Check::Unary.new(:name, other.(input).curry(predicate), [:name])
|
4
|
+
end
|
3
5
|
|
4
6
|
include_context 'predicates'
|
5
7
|
|
@@ -8,21 +10,21 @@ RSpec.describe Rule::Check do
|
|
8
10
|
end
|
9
11
|
|
10
12
|
describe '#call' do
|
11
|
-
context 'when
|
13
|
+
context 'when then given predicate passed' do
|
12
14
|
let(:input) { 'Jane' }
|
13
15
|
let(:predicate) { :filled? }
|
14
16
|
|
15
17
|
it 'returns a success' do
|
16
|
-
expect(rule.()).to be_success
|
18
|
+
expect(rule.('Jane')).to be_success
|
17
19
|
end
|
18
20
|
end
|
19
21
|
|
20
|
-
context 'when
|
22
|
+
context 'when the given predicate did not pass' do
|
21
23
|
let(:input) { nil }
|
22
24
|
let(:predicate) { :filled? }
|
23
25
|
|
24
26
|
it 'returns a failure' do
|
25
|
-
expect(rule.()).to be_failure
|
27
|
+
expect(rule.(nil)).to be_failure
|
26
28
|
end
|
27
29
|
end
|
28
30
|
end
|
@@ -19,7 +19,7 @@ RSpec.describe Dry::Logic::Rule::Result do
|
|
19
19
|
it 'evaluates successful input for the ast' do
|
20
20
|
expect(rule.(name: is_str.('jane')).to_ary).to eql([
|
21
21
|
:input, [
|
22
|
-
:name,
|
22
|
+
:name, 'jane', [[:res, [:name, [:predicate, [:min_size?, [4]]]]]]
|
23
23
|
]
|
24
24
|
])
|
25
25
|
end
|
@@ -44,7 +44,7 @@ RSpec.describe Dry::Logic::Rule::Result do
|
|
44
44
|
it 'evaluates input for the ast' do
|
45
45
|
expect(conjunction.(name: is_str.('john')).to_ary).to eql([
|
46
46
|
:input, [
|
47
|
-
:name,
|
47
|
+
:name, 'john', [[:res, [:name, [:predicate, [:eql?, ['jane']]]]]]
|
48
48
|
]
|
49
49
|
])
|
50
50
|
end
|
@@ -63,7 +63,7 @@ RSpec.describe Dry::Logic::Rule::Result do
|
|
63
63
|
|
64
64
|
expect(result.to_ary).to eql([
|
65
65
|
:input, [
|
66
|
-
:name,
|
66
|
+
:name, 'john', [[:res, [:name, [:predicate, [:min_size?, [4]]]]]]
|
67
67
|
]
|
68
68
|
])
|
69
69
|
end
|
@@ -83,7 +83,7 @@ RSpec.describe Dry::Logic::Rule::Result do
|
|
83
83
|
|
84
84
|
expect(result.to_ary).to eql([
|
85
85
|
:input, [
|
86
|
-
:name,
|
86
|
+
:name, 'john', [[:res, [:name, [:predicate, [:eql?, ['jane']]]]]]
|
87
87
|
]
|
88
88
|
])
|
89
89
|
end
|
@@ -7,7 +7,10 @@ RSpec.describe Dry::Logic::RuleCompiler, '#call' do
|
|
7
7
|
{ key?: predicate,
|
8
8
|
attr?: predicate,
|
9
9
|
filled?: predicate,
|
10
|
-
|
10
|
+
gt?: predicate,
|
11
|
+
email: val_rule.('email').curry(:filled?),
|
12
|
+
left: res_left_rule,
|
13
|
+
right: double(input: 312) }
|
11
14
|
}
|
12
15
|
|
13
16
|
let(:predicate) { double(:predicate).as_null_object }
|
@@ -16,8 +19,9 @@ RSpec.describe Dry::Logic::RuleCompiler, '#call' do
|
|
16
19
|
let(:not_key_rule) { Rule::Key.new(:email, predicate).negation }
|
17
20
|
let(:attr_rule) { Rule::Attr.new(:email, predicate) }
|
18
21
|
let(:val_rule) { Rule::Value.new(:email, predicate) }
|
19
|
-
let(:check_rule) { Rule::Check.new(:email, predicates[:email]) }
|
22
|
+
let(:check_rule) { Rule::Check::Unary.new(:email, predicates[:email], [:email]) }
|
20
23
|
let(:res_rule) { Rule::Result.new(:email, predicates[:email]) }
|
24
|
+
let(:res_left_rule) { Rule::Result.new(:left, predicate) }
|
21
25
|
let(:and_rule) { key_rule & val_rule }
|
22
26
|
let(:or_rule) { key_rule | val_rule }
|
23
27
|
let(:xor_rule) { key_rule ^ val_rule }
|
@@ -48,6 +52,16 @@ RSpec.describe Dry::Logic::RuleCompiler, '#call' do
|
|
48
52
|
expect(rules).to eql([res_rule])
|
49
53
|
end
|
50
54
|
|
55
|
+
it 'compiles result rules with res args' do
|
56
|
+
ast = [[:res, [:left, [:predicate, [:gt?, [:args, [[:res_arg, :right]]]]]]]]
|
57
|
+
|
58
|
+
expect(predicate).to receive(:curry).with(312)
|
59
|
+
|
60
|
+
rules = compiler.(ast)
|
61
|
+
|
62
|
+
expect(rules).to eql([res_left_rule])
|
63
|
+
end
|
64
|
+
|
51
65
|
it 'compiles attr rules' do
|
52
66
|
ast = [[:attr, [:email, [:predicate, [:attr?, predicate]]]]]
|
53
67
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dry-logic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Piotr Solnica
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-01-
|
11
|
+
date: 2016-01-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dry-container
|