dry-logic 0.4.0 → 0.4.2
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/.codeclimate.yml +23 -0
- data/.travis.yml +11 -7
- data/CHANGELOG.md +34 -9
- data/CONTRIBUTING.md +29 -0
- data/Gemfile +2 -1
- data/README.md +4 -27
- data/dry-logic.gemspec +2 -3
- data/examples/basic.rb +5 -10
- data/lib/dry/logic/predicates.rb +24 -10
- data/lib/dry/logic/rule.rb +2 -2
- data/lib/dry/logic/version.rb +1 -1
- data/spec/shared/predicates.rb +4 -0
- data/spec/spec_helper.rb +12 -7
- data/spec/unit/predicates/case_spec.rb +33 -0
- data/spec/unit/predicates/eql_spec.rb +1 -1
- data/spec/unit/predicates/includes_spec.rb +14 -46
- data/spec/unit/rule_spec.rb +52 -5
- metadata +10 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 554db40a47bc9eaa08659c38fd706fd15317f703
|
|
4
|
+
data.tar.gz: cdf04c815e657c282eef1c0d28d8923ba6b4dc12
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fa2ff6136f6407d523dcb8f5dee97c7f01da3aa71ebde81ce05ac92ab1408db9909d9e997cf81b46ad2bb8120000cdbe84c456b3866f22d37259674883445721
|
|
7
|
+
data.tar.gz: 3b6148d888eb2fb6ab6c8e87f3dedbee81feb13a310c7256abc06de9e8643555bf671b9d215045fc00db5c8a09e1b35f6ac1e57e57a6f91d09ca509eee14aa7a
|
data/.codeclimate.yml
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
engines:
|
|
2
|
+
rubocop:
|
|
3
|
+
enabled: true
|
|
4
|
+
checks:
|
|
5
|
+
Rubocop/Metrics/LineLength:
|
|
6
|
+
enabled: true
|
|
7
|
+
max: 100
|
|
8
|
+
Rubocop/Style/Documentation:
|
|
9
|
+
enabled: false
|
|
10
|
+
Rubocop/Lint/HandleExceptions:
|
|
11
|
+
enabled: true
|
|
12
|
+
exclude:
|
|
13
|
+
- rakelib/*.rake
|
|
14
|
+
Rubocop/Style/FileName:
|
|
15
|
+
enabled: true
|
|
16
|
+
exclude:
|
|
17
|
+
- 'lib/dry-logic.rb'
|
|
18
|
+
ratings:
|
|
19
|
+
paths:
|
|
20
|
+
- lib/**/*.rb
|
|
21
|
+
exclude_paths:
|
|
22
|
+
- spec/**/*
|
|
23
|
+
- examples/**/*
|
data/.travis.yml
CHANGED
|
@@ -1,22 +1,26 @@
|
|
|
1
1
|
language: ruby
|
|
2
|
+
dist: trusty
|
|
2
3
|
sudo: false
|
|
3
4
|
cache: bundler
|
|
4
5
|
bundler_args: --without console tools
|
|
5
6
|
script:
|
|
6
7
|
- bundle exec rake spec
|
|
8
|
+
after_success:
|
|
9
|
+
- '[ -d coverage ] && bundle exec codeclimate-test-reporter'
|
|
7
10
|
rvm:
|
|
8
|
-
- 2.1
|
|
9
|
-
- 2.2
|
|
10
|
-
- 2.3.
|
|
11
|
-
-
|
|
12
|
-
- jruby-
|
|
11
|
+
- 2.1.10
|
|
12
|
+
- 2.2.7
|
|
13
|
+
- 2.3.4
|
|
14
|
+
- 2.4.1
|
|
15
|
+
- jruby-9.1.10.0
|
|
16
|
+
- ruby-head
|
|
13
17
|
env:
|
|
14
18
|
global:
|
|
15
19
|
- JRUBY_OPTS='--dev -J-Xmx1024M'
|
|
20
|
+
- COVERAGE=true
|
|
16
21
|
matrix:
|
|
17
22
|
allow_failures:
|
|
18
|
-
- rvm:
|
|
19
|
-
- rvm: rbx-2
|
|
23
|
+
- rvm: ruby-head
|
|
20
24
|
notifications:
|
|
21
25
|
email: false
|
|
22
26
|
webhooks:
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,28 @@
|
|
|
1
|
+
# v0.4.2 2017-09-15
|
|
2
|
+
|
|
3
|
+
### Added
|
|
4
|
+
|
|
5
|
+
* New `:case?` predicate matches a value against the given object with `#===` (flash-gordon)
|
|
6
|
+
* New `:is?` predicate checks objects identity (using `#equal?`) (flash-gordon)
|
|
7
|
+
|
|
8
|
+
### Fixed
|
|
9
|
+
|
|
10
|
+
* A bug with using custom predicates within a standalone module in `dry-validation` (flash-gordon)
|
|
11
|
+
|
|
12
|
+
[Compare v0.4.1...v0.4.2(https://github.com/dry-rb/dry-logic/compare/v0.4.1...v0.4.2)
|
|
13
|
+
|
|
14
|
+
# v0.4.1 2017-01-23
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
* Predicates simply reuse other predicate methods instead of referring to them via `#[]` (georgemillo)
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
* Warnings on MRI 2.4.0 are gone (jtippett)
|
|
23
|
+
|
|
24
|
+
[Compare v0.4.0...v0.4.1](https://github.com/dry-rb/dry-logic/compare/v0.4.0...v0.4.1)
|
|
25
|
+
|
|
1
26
|
# v0.4.0 2016-09-21
|
|
2
27
|
|
|
3
28
|
This is a partial rewrite focused on internal clean up and major performance improvements. This is also the beginning of the work to make this library first-class rather than "just" a rule backend for dry-validation and dry-types.
|
|
@@ -24,7 +49,7 @@ This is a partial rewrite focused on internal clean up and major performance imp
|
|
|
24
49
|
* [BREAKING] `Rule#name` is now `Rule#id` (solnic)
|
|
25
50
|
* `Rule#parameters` is public now (solnic)
|
|
26
51
|
|
|
27
|
-
[Compare v0.3.0...v0.4.0](https://github.com/
|
|
52
|
+
[Compare v0.3.0...v0.4.0](https://github.com/dry-rb/dry-logic/compare/v0.3.0...v0.4.0)
|
|
28
53
|
|
|
29
54
|
# v0.3.0 2016-07-01
|
|
30
55
|
|
|
@@ -39,7 +64,7 @@ This is a partial rewrite focused on internal clean up and major performance imp
|
|
|
39
64
|
* Predicates raise errors when they are called with invalid arity (fran-worley + solnic)
|
|
40
65
|
* Rules no longer evaluate input twice when building result objects (solnic)
|
|
41
66
|
|
|
42
|
-
[Compare v0.2.3...v0.3.0](https://github.com/
|
|
67
|
+
[Compare v0.2.3...v0.3.0](https://github.com/dry-rb/dry-logic/compare/v0.2.3...v0.3.0)
|
|
43
68
|
|
|
44
69
|
# v0.2.3 2016-05-11
|
|
45
70
|
|
|
@@ -52,7 +77,7 @@ This is a partial rewrite focused on internal clean up and major performance imp
|
|
|
52
77
|
* Renamed `inclusion?` to `included_in?` and deprecated `inclusion?` (fran-worley)
|
|
53
78
|
* Renamed `exclusion?` to `excluded_from?` and deprecated `exclusion?` (fran-worley)
|
|
54
79
|
|
|
55
|
-
[Compare v0.2.2...v0.2.3](https://github.com/
|
|
80
|
+
[Compare v0.2.2...v0.2.3](https://github.com/dry-rb/dry-logic/compare/v0.2.2...v0.2.3)
|
|
56
81
|
|
|
57
82
|
# v0.2.2 2016-03-30
|
|
58
83
|
|
|
@@ -60,7 +85,7 @@ This is a partial rewrite focused on internal clean up and major performance imp
|
|
|
60
85
|
|
|
61
86
|
* `number?`, `odd?`, `even?` predicates (fran-worley)
|
|
62
87
|
|
|
63
|
-
[Compare v0.2.1...v0.2.2](https://github.com/
|
|
88
|
+
[Compare v0.2.1...v0.2.2](https://github.com/dry-rb/dry-logic/compare/v0.2.1...v0.2.2)
|
|
64
89
|
|
|
65
90
|
# v0.2.1 2016-03-20
|
|
66
91
|
|
|
@@ -74,7 +99,7 @@ This is a partial rewrite focused on internal clean up and major performance imp
|
|
|
74
99
|
|
|
75
100
|
* Entire AST has been redefined (solnic)
|
|
76
101
|
|
|
77
|
-
[Compare v0.1.4...v0.2.0](https://github.com/
|
|
102
|
+
[Compare v0.1.4...v0.2.0](https://github.com/dry-rb/dry-logic/compare/v0.1.4...v0.2.0)
|
|
78
103
|
|
|
79
104
|
# v0.1.4 2016-01-27
|
|
80
105
|
|
|
@@ -83,7 +108,7 @@ This is a partial rewrite focused on internal clean up and major performance imp
|
|
|
83
108
|
* Support for hash-names in `Check` and `Result` which can properly resolve input
|
|
84
109
|
from nested results (solnic)
|
|
85
110
|
|
|
86
|
-
[Compare v0.1.3...v0.1.4](https://github.com/
|
|
111
|
+
[Compare v0.1.3...v0.1.4](https://github.com/dry-rb/dry-logic/compare/v0.1.3...v0.1.4)
|
|
87
112
|
|
|
88
113
|
# v0.1.3 2016-01-27
|
|
89
114
|
|
|
@@ -95,7 +120,7 @@ This is a partial rewrite focused on internal clean up and major performance imp
|
|
|
95
120
|
|
|
96
121
|
* `Check` and `Result` carry original input(s) (solnic)
|
|
97
122
|
|
|
98
|
-
[Compare v0.1.2...v0.1.3](https://github.com/
|
|
123
|
+
[Compare v0.1.2...v0.1.3](https://github.com/dry-rb/dry-logic/compare/v0.1.2...v0.1.3)
|
|
99
124
|
|
|
100
125
|
# v0.1.2 2016-01-19
|
|
101
126
|
|
|
@@ -103,7 +128,7 @@ This is a partial rewrite focused on internal clean up and major performance imp
|
|
|
103
128
|
|
|
104
129
|
* `xor` returns wrapped results when used against another result-rule (solnic)
|
|
105
130
|
|
|
106
|
-
[Compare v0.1.1...v0.1.2](https://github.com/
|
|
131
|
+
[Compare v0.1.1...v0.1.2](https://github.com/dry-rb/dry-logic/compare/v0.1.1...v0.1.2)
|
|
107
132
|
|
|
108
133
|
# v0.1.1 2016-01-18
|
|
109
134
|
|
|
@@ -113,7 +138,7 @@ This is a partial rewrite focused on internal clean up and major performance imp
|
|
|
113
138
|
* `Rule::Result` which can be applied to a result object (solnic)
|
|
114
139
|
* `true?` and `false?` predicates (solnic)
|
|
115
140
|
|
|
116
|
-
[Compare v0.1.0...v0.1.1](https://github.com/
|
|
141
|
+
[Compare v0.1.0...v0.1.1](https://github.com/dry-rb/dry-logic/compare/v0.1.0...v0.1.1)
|
|
117
142
|
|
|
118
143
|
# v0.1.0 2016-01-11
|
|
119
144
|
|
data/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Issue Guidelines
|
|
2
|
+
|
|
3
|
+
## Reporting bugs
|
|
4
|
+
|
|
5
|
+
If you found a bug, report an issue and describe what's the expected behavior versus what actually happens. If the bug causes a crash, attach a full backtrace. If possible, a reproduction script showing the problem is highly appreciated.
|
|
6
|
+
|
|
7
|
+
## Reporting feature requests
|
|
8
|
+
|
|
9
|
+
Report a feature request **only after discussing it first on [discuss.dry-rb.org](https://discuss.dry-rb.org)** where it was accepted. Please provide a concise description of the feature, don't link to a discussion thread, and instead summarize what was discussed.
|
|
10
|
+
|
|
11
|
+
## Reporting questions, support requests, ideas, concerns etc.
|
|
12
|
+
|
|
13
|
+
**PLEASE DON'T** - use [discuss.dry-rb.org](http://discuss.dry-rb.org) instead.
|
|
14
|
+
|
|
15
|
+
# Pull Request Guidelines
|
|
16
|
+
|
|
17
|
+
A Pull Request will only be accepted if it addresses a specific issue that was reported previously, or fixes typos, mistakes in documentation etc.
|
|
18
|
+
|
|
19
|
+
Other requirements:
|
|
20
|
+
|
|
21
|
+
1) Do not open a pull request if you can't provide tests along with it. If you have problems writing tests, ask for help in the related issue.
|
|
22
|
+
2) Follow the style conventions of the surrounding code. In most cases, this is standard ruby style.
|
|
23
|
+
3) Add API documentation if it's a new feature
|
|
24
|
+
4) Update API documentation if it changes an existing feature
|
|
25
|
+
5) Bonus points for sending a PR to [github.com/dry-rb/dry-rb.org](github.com/dry-rb/dry-rb.org) which updates user documentation and guides
|
|
26
|
+
|
|
27
|
+
# Asking for help
|
|
28
|
+
|
|
29
|
+
If these guidelines aren't helpful, and you're stuck, please post a message on [discuss.dry-rb.org](https://discuss.dry-rb.org).
|
data/Gemfile
CHANGED
|
@@ -4,11 +4,12 @@ gemspec
|
|
|
4
4
|
|
|
5
5
|
group :test do
|
|
6
6
|
gem 'codeclimate-test-reporter', platform: :mri
|
|
7
|
+
gem 'simplecov', require: false, platform: :mri
|
|
7
8
|
end
|
|
8
9
|
|
|
9
10
|
group :tools do
|
|
11
|
+
gem 'rubocop'
|
|
10
12
|
gem 'byebug', platform: :mri
|
|
11
|
-
gem 'simplecov', platforms: :mri
|
|
12
13
|
|
|
13
14
|
unless ENV['TRAVIS']
|
|
14
15
|
gem 'mutant', github: 'mbj/mutant'
|
data/README.md
CHANGED
|
@@ -20,36 +20,13 @@ Predicate logic and rule composition used by:
|
|
|
20
20
|
* [dry-validation](https://github.com/dry-rb/dry-validation) for composing validation rules
|
|
21
21
|
* your project...?
|
|
22
22
|
|
|
23
|
-
##
|
|
23
|
+
## Links
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
require 'dry/logic'
|
|
27
|
-
require 'dry/logic/predicates'
|
|
25
|
+
* [Documentation](http://dry-rb.org/gems/dry-logic)
|
|
28
26
|
|
|
29
|
-
|
|
27
|
+
## Contributing
|
|
30
28
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
has_min_age = Rule::Key.new(Predicates[:int?], name: [:user, :age])
|
|
34
|
-
& Rule::Key.new(Predicates[:gt?].curry(18), name: [:user, :age])
|
|
35
|
-
|
|
36
|
-
user_rule = user_present & has_min_age
|
|
37
|
-
|
|
38
|
-
user_rule.(user: { age: 19 })
|
|
39
|
-
# #<Dry::Logic::Result::Named success?=true input={:user=>{:age=>19}} rule=#<Dry::Logic::Rule::Key predicate=#<Dry::Logic::Predicate id=:gt? args=[18, 19]> options={:evaluator=>#<Dry::Logic::Evaluator::Key path=[:user, :age]>, :name=>[:user, :age]}>>
|
|
40
|
-
|
|
41
|
-
user_rule.(user: { age: 18 })
|
|
42
|
-
# #<Dry::Logic::Result::Named success?=false input={:user=>{:age=>18}} rule=#<Dry::Logic::Rule::Key predicate=#<Dry::Logic::Predicate id=:gt? args=[18, 18]> options={:evaluator=>#<Dry::Logic::Evaluator::Key path=[:user, :age]>, :name=>[:user, :age]}>>
|
|
43
|
-
|
|
44
|
-
user_rule.(user: { age: 'seventeen' }).inspect
|
|
45
|
-
#<Dry::Logic::Result::Named success?=false input={:user=>{:age=>"seventeen"}} rule=#<Dry::Logic::Rule::Key predicate=#<Dry::Logic::Predicate id=:int? args=["seventeen"]> options={:evaluator=>#<Dry::Logic::Evaluator::Key path=[:user, :age]>, :name=>[:user, :age]}>>
|
|
46
|
-
|
|
47
|
-
user_rule.(user: { }).inspect
|
|
48
|
-
#<Dry::Logic::Result::Named success?=false input={:user=>{}} rule=#<Dry::Logic::Rule::Key predicate=#<Dry::Logic::Predicate id=:filled? args=[{}]> options={:evaluator=>#<Dry::Logic::Evaluator::Key path=[:user]>, :name=>:user}>>
|
|
49
|
-
|
|
50
|
-
puts user_rule.({}).inspect
|
|
51
|
-
#<Dry::Logic::Result::Named success?=false input={} rule=#<Dry::Logic::Rule::Key predicate=#<Dry::Logic::Predicate id=:filled? args=[nil]> options={:evaluator=>#<Dry::Logic::Evaluator::Key path=[:user]>, :name=>:user}>>
|
|
52
|
-
```
|
|
29
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/dry-rb/dry-logic.
|
|
53
30
|
|
|
54
31
|
## License
|
|
55
32
|
|
data/dry-logic.gemspec
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# coding: utf-8
|
|
2
1
|
require File.expand_path('../lib/dry/logic/version', __FILE__)
|
|
3
2
|
|
|
4
3
|
Gem::Specification.new do |spec|
|
|
@@ -7,7 +6,7 @@ Gem::Specification.new do |spec|
|
|
|
7
6
|
spec.authors = ['Piotr Solnica']
|
|
8
7
|
spec.email = ['piotr.solnica@gmail.com']
|
|
9
8
|
spec.summary = 'Predicate logic with rule composition'
|
|
10
|
-
spec.homepage = 'https://github.com/
|
|
9
|
+
spec.homepage = 'https://github.com/dry-rb/dry-logic'
|
|
11
10
|
spec.license = 'MIT'
|
|
12
11
|
|
|
13
12
|
spec.files = `git ls-files -z`.split("\x0")
|
|
@@ -15,7 +14,7 @@ Gem::Specification.new do |spec|
|
|
|
15
14
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
16
15
|
spec.require_paths = ['lib']
|
|
17
16
|
|
|
18
|
-
spec.add_runtime_dependency 'dry-core', '~> 0.
|
|
17
|
+
spec.add_runtime_dependency 'dry-core', '~> 0.2'
|
|
19
18
|
spec.add_runtime_dependency 'dry-container', '~> 0.2', '>= 0.2.6'
|
|
20
19
|
spec.add_runtime_dependency 'dry-equalizer', '~> 0.2'
|
|
21
20
|
|
data/examples/basic.rb
CHANGED
|
@@ -3,17 +3,12 @@ require 'dry/logic/predicates'
|
|
|
3
3
|
|
|
4
4
|
include Dry::Logic
|
|
5
5
|
|
|
6
|
-
user_present = Rule::
|
|
7
|
-
has_min_age = Rule::Key.new(Predicates[:int?], name: [:user, :age]) & Rule::Key.new(Predicates[:gt?].curry(18), name: [:user, :age])
|
|
6
|
+
user_present = Rule::Predicate.new(Predicates[:key?]).curry(:user)
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
puts user_rule.(user: { age: 19 }).inspect
|
|
8
|
+
has_min_age = Operations::Key.new(Rule::Predicate.new(Predicates[:gt?]).curry(18), name: [:user, :age])
|
|
12
9
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
puts user_rule.(user: { age: 'seventeen' }).inspect
|
|
10
|
+
user_rule = user_present & has_min_age
|
|
16
11
|
|
|
17
|
-
puts user_rule.(user: { }).
|
|
12
|
+
puts user_rule.(user: { age: 19 }).success?
|
|
18
13
|
|
|
19
|
-
puts user_rule.({}).
|
|
14
|
+
puts user_rule.(user: { age: 18 }).success?
|
data/lib/dry/logic/predicates.rb
CHANGED
|
@@ -36,7 +36,7 @@ module Dry
|
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
def filled?(input)
|
|
39
|
-
!
|
|
39
|
+
!empty?(input)
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
def bool?(input)
|
|
@@ -64,7 +64,7 @@ module Dry
|
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
def int?(input)
|
|
67
|
-
input.is_a?(
|
|
67
|
+
input.is_a?(Integer)
|
|
68
68
|
end
|
|
69
69
|
|
|
70
70
|
def float?(input)
|
|
@@ -104,16 +104,16 @@ module Dry
|
|
|
104
104
|
end
|
|
105
105
|
|
|
106
106
|
def lteq?(num, input)
|
|
107
|
-
!
|
|
107
|
+
!gt?(num, input)
|
|
108
108
|
end
|
|
109
109
|
|
|
110
110
|
def gteq?(num, input)
|
|
111
|
-
!
|
|
111
|
+
!lt?(num, input)
|
|
112
112
|
end
|
|
113
113
|
|
|
114
114
|
def size?(size, input)
|
|
115
115
|
case size
|
|
116
|
-
when
|
|
116
|
+
when Integer then size == input.size
|
|
117
117
|
when Range, Array then size.include?(input.size)
|
|
118
118
|
else
|
|
119
119
|
raise ArgumentError, "+#{size}+ is not supported type for size? predicate."
|
|
@@ -130,12 +130,12 @@ module Dry
|
|
|
130
130
|
|
|
131
131
|
def inclusion?(list, input)
|
|
132
132
|
::Kernel.warn 'inclusion is deprecated - use included_in instead.'
|
|
133
|
-
|
|
133
|
+
included_in?(list, input)
|
|
134
134
|
end
|
|
135
135
|
|
|
136
136
|
def exclusion?(list, input)
|
|
137
137
|
::Kernel.warn 'exclusion is deprecated - use excluded_from instead.'
|
|
138
|
-
|
|
138
|
+
excluded_from?(list, input)
|
|
139
139
|
end
|
|
140
140
|
|
|
141
141
|
def included_in?(list, input)
|
|
@@ -159,13 +159,17 @@ module Dry
|
|
|
159
159
|
end
|
|
160
160
|
|
|
161
161
|
def excludes?(value, input)
|
|
162
|
-
!
|
|
162
|
+
!includes?(value, input)
|
|
163
163
|
end
|
|
164
164
|
|
|
165
165
|
def eql?(left, right)
|
|
166
166
|
left.eql?(right)
|
|
167
167
|
end
|
|
168
168
|
|
|
169
|
+
def is?(left, right)
|
|
170
|
+
left.equal?(right)
|
|
171
|
+
end
|
|
172
|
+
|
|
169
173
|
def not_eql?(left, right)
|
|
170
174
|
!left.eql?(right)
|
|
171
175
|
end
|
|
@@ -178,8 +182,18 @@ module Dry
|
|
|
178
182
|
value.equal?(false)
|
|
179
183
|
end
|
|
180
184
|
|
|
181
|
-
|
|
182
|
-
|
|
185
|
+
if RUBY_VERSION < '2.4'
|
|
186
|
+
def format?(regex, input)
|
|
187
|
+
!regex.match(input).nil?
|
|
188
|
+
end
|
|
189
|
+
else
|
|
190
|
+
def format?(regex, input)
|
|
191
|
+
regex.match?(input)
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def case?(pattern, input)
|
|
196
|
+
pattern === input
|
|
183
197
|
end
|
|
184
198
|
|
|
185
199
|
def predicate(name, &block)
|
data/lib/dry/logic/rule.rb
CHANGED
|
@@ -62,7 +62,7 @@ module Dry
|
|
|
62
62
|
end
|
|
63
63
|
|
|
64
64
|
def bind(object)
|
|
65
|
-
if predicate
|
|
65
|
+
if UnboundMethod === predicate
|
|
66
66
|
self.class.new(predicate.bind(object), options)
|
|
67
67
|
else
|
|
68
68
|
self.class.new(
|
|
@@ -73,7 +73,7 @@ module Dry
|
|
|
73
73
|
end
|
|
74
74
|
|
|
75
75
|
def eval_args(object)
|
|
76
|
-
with(args: args.map { |arg|
|
|
76
|
+
with(args: args.map { |arg| UnboundMethod === arg ? arg.bind(object).() : arg })
|
|
77
77
|
end
|
|
78
78
|
|
|
79
79
|
def with(new_opts)
|
data/lib/dry/logic/version.rb
CHANGED
data/spec/shared/predicates.rb
CHANGED
|
@@ -30,6 +30,10 @@ RSpec.shared_examples 'predicates' do
|
|
|
30
30
|
let(:eql?) { Dry::Logic::Predicates[:eql?] }
|
|
31
31
|
|
|
32
32
|
let(:size?) { Dry::Logic::Predicates[:size?] }
|
|
33
|
+
|
|
34
|
+
let(:case?) { Dry::Logic::Predicates[:case?] }
|
|
35
|
+
|
|
36
|
+
let(:equal?) { Dry::Logic::Predicates[:equal?] }
|
|
33
37
|
end
|
|
34
38
|
|
|
35
39
|
RSpec.shared_examples 'a passing predicate' do
|
data/spec/spec_helper.rb
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
if RUBY_ENGINE == 'ruby' &&
|
|
2
|
-
require
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
if RUBY_ENGINE == 'ruby' && ENV['COVERAGE'] == 'true'
|
|
2
|
+
require 'yaml'
|
|
3
|
+
rubies = YAML.load(File.read(File.join(__dir__, '..', '.travis.yml')))['rvm']
|
|
4
|
+
latest_mri = rubies.select { |v| v =~ /\A\d+\.\d+.\d+\z/ }.max
|
|
5
5
|
|
|
6
|
-
if
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
if RUBY_VERSION == latest_mri
|
|
7
|
+
require 'simplecov'
|
|
8
|
+
SimpleCov.start do
|
|
9
|
+
add_filter '/spec/'
|
|
10
|
+
end
|
|
11
|
+
end
|
|
9
12
|
end
|
|
10
13
|
|
|
11
14
|
begin
|
|
@@ -26,4 +29,6 @@ include Dry::Core::Constants
|
|
|
26
29
|
|
|
27
30
|
RSpec.configure do |config|
|
|
28
31
|
config.disable_monkey_patching!
|
|
32
|
+
|
|
33
|
+
config.warnings = true
|
|
29
34
|
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require 'dry/logic/predicates'
|
|
2
|
+
|
|
3
|
+
RSpec.describe Dry::Logic::Predicates do
|
|
4
|
+
describe '#case?' do
|
|
5
|
+
let(:predicate_name) { :case? }
|
|
6
|
+
|
|
7
|
+
context 'when the value matches the pattern' do
|
|
8
|
+
let(:arguments_list) do
|
|
9
|
+
[
|
|
10
|
+
[11, 11],
|
|
11
|
+
[:odd?.to_proc, 11],
|
|
12
|
+
[/\Af/, 'foo'],
|
|
13
|
+
[Integer, 11]
|
|
14
|
+
]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it_behaves_like 'a passing predicate'
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
context "when the value doesn't match the pattern" do
|
|
21
|
+
let(:arguments_list) do
|
|
22
|
+
[
|
|
23
|
+
[13, 14],
|
|
24
|
+
[:odd?.to_proc, 12],
|
|
25
|
+
[/\Af/, 'bar'],
|
|
26
|
+
[String, 11]
|
|
27
|
+
]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it_behaves_like 'a failing predicate'
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -1,56 +1,24 @@
|
|
|
1
1
|
require 'dry/logic/predicates'
|
|
2
2
|
|
|
3
|
-
RSpec.describe Dry::Logic::Predicates do
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
RSpec.describe Dry::Logic::Predicates, '#is?' do
|
|
4
|
+
let(:predicate_name) { :is? }
|
|
5
|
+
let(:one) { Object.new }
|
|
6
|
+
let(:two) { Object.new }
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
['Jill', ['Jill', 'John']],
|
|
11
|
-
['John', ['Jill', 'John']],
|
|
12
|
-
[1, 1..2],
|
|
13
|
-
[2, 1..2],
|
|
14
|
-
['Hello', 'Hello World'],
|
|
15
|
-
['World', 'Hello World'],
|
|
16
|
-
[:bar, { bar: 0 }],
|
|
17
|
-
[nil, [nil, false]],
|
|
18
|
-
[false, [nil, false]]
|
|
19
|
-
]
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
it_behaves_like 'a passing predicate'
|
|
8
|
+
context 'when value is equal to the arg' do
|
|
9
|
+
let(:arguments_list) do
|
|
10
|
+
[[one, one], [:one, :one]]
|
|
23
11
|
end
|
|
24
12
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
[
|
|
28
|
-
[2, 1],
|
|
29
|
-
[1, nil],
|
|
30
|
-
["foo", 1],
|
|
31
|
-
[1, "foo"],
|
|
32
|
-
[1..2, "foo"],
|
|
33
|
-
["foo", 1..2],
|
|
34
|
-
[:key, "foo"]
|
|
35
|
-
]
|
|
36
|
-
end
|
|
13
|
+
it_behaves_like 'a passing predicate'
|
|
14
|
+
end
|
|
37
15
|
|
|
38
|
-
|
|
16
|
+
context 'with value is not equal to the arg' do
|
|
17
|
+
let(:arguments_list) do
|
|
18
|
+
# Strings are not equal. Yet
|
|
19
|
+
[[one, two], ['one', 'one']]
|
|
39
20
|
end
|
|
40
21
|
|
|
41
|
-
|
|
42
|
-
let(:arguments_list) do
|
|
43
|
-
[
|
|
44
|
-
['Jack', ['Jill', 'John']],
|
|
45
|
-
[0, 1..2],
|
|
46
|
-
[3, 1..2],
|
|
47
|
-
['foo', 'Hello World'],
|
|
48
|
-
[:foo, { bar: 0 }],
|
|
49
|
-
[true, [nil, false]]
|
|
50
|
-
]
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
it_behaves_like 'a failing predicate'
|
|
54
|
-
end
|
|
22
|
+
it_behaves_like 'a failing predicate'
|
|
55
23
|
end
|
|
56
24
|
end
|
data/spec/unit/rule_spec.rb
CHANGED
|
@@ -4,6 +4,32 @@ RSpec.describe Dry::Logic::Rule do
|
|
|
4
4
|
let(:predicate) { -> { true } }
|
|
5
5
|
let(:options) { {} }
|
|
6
6
|
|
|
7
|
+
let(:schema) do
|
|
8
|
+
Class.new(BasicObject) do
|
|
9
|
+
define_method(:class, Kernel.instance_method(:class))
|
|
10
|
+
|
|
11
|
+
def method_missing(m, *)
|
|
12
|
+
if m.to_s.end_with?('?')
|
|
13
|
+
self.class.new
|
|
14
|
+
else
|
|
15
|
+
super
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def to_proc
|
|
20
|
+
-> value { value }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def arity
|
|
24
|
+
1
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def parameters
|
|
28
|
+
[[:req, :value]]
|
|
29
|
+
end
|
|
30
|
+
end.new
|
|
31
|
+
end
|
|
32
|
+
|
|
7
33
|
it_behaves_like Dry::Logic::Rule
|
|
8
34
|
|
|
9
35
|
describe '.new' do
|
|
@@ -80,15 +106,36 @@ RSpec.describe Dry::Logic::Rule do
|
|
|
80
106
|
expect(bound.options[:parameters]).to eql(rule.parameters)
|
|
81
107
|
end
|
|
82
108
|
end
|
|
109
|
+
|
|
110
|
+
context 'with a schema instance' do
|
|
111
|
+
let(:object) { schema }
|
|
112
|
+
let(:predicate) { schema }
|
|
113
|
+
|
|
114
|
+
it 'returns a new with its predicate executed in the context of the provided object' do
|
|
115
|
+
expect(bound.(true)).to be_success
|
|
116
|
+
expect(bound.(false)).to be_failure
|
|
117
|
+
end
|
|
118
|
+
end
|
|
83
119
|
end
|
|
84
120
|
|
|
85
121
|
describe '#eval_args' do
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
122
|
+
context 'with an unbound method' do
|
|
123
|
+
let(:options) { { args: [1, klass.instance_method(:num), :foo] } }
|
|
124
|
+
let(:klass) { Class.new { def num; 7; end } }
|
|
125
|
+
let(:object) { klass.new }
|
|
89
126
|
|
|
90
|
-
|
|
91
|
-
|
|
127
|
+
it 'evaluates args in the context of the provided object' do
|
|
128
|
+
expect(rule.eval_args(object).args).to eql([1, 7, :foo])
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
context 'with a schema instance' do
|
|
133
|
+
let(:options) { { args: [1, schema, :foo] } }
|
|
134
|
+
let(:object) { Object.new }
|
|
135
|
+
|
|
136
|
+
it 'returns a new with its predicate executed in the context of the provided object' do
|
|
137
|
+
expect(rule.eval_args(object).args).to eql([1, schema, :foo])
|
|
138
|
+
end
|
|
92
139
|
end
|
|
93
140
|
end
|
|
94
141
|
end
|
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.4.
|
|
4
|
+
version: 0.4.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Piotr Solnica
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2017-09-15 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: dry-core
|
|
@@ -16,14 +16,14 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '0.
|
|
19
|
+
version: '0.2'
|
|
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.
|
|
26
|
+
version: '0.2'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: dry-container
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -107,12 +107,14 @@ executables: []
|
|
|
107
107
|
extensions: []
|
|
108
108
|
extra_rdoc_files: []
|
|
109
109
|
files:
|
|
110
|
+
- ".codeclimate.yml"
|
|
110
111
|
- ".gitignore"
|
|
111
112
|
- ".rspec"
|
|
112
113
|
- ".rubocop.yml"
|
|
113
114
|
- ".rubocop_todo.yml"
|
|
114
115
|
- ".travis.yml"
|
|
115
116
|
- CHANGELOG.md
|
|
117
|
+
- CONTRIBUTING.md
|
|
116
118
|
- Gemfile
|
|
117
119
|
- LICENSE
|
|
118
120
|
- README.md
|
|
@@ -163,6 +165,7 @@ files:
|
|
|
163
165
|
- spec/unit/predicates/array_spec.rb
|
|
164
166
|
- spec/unit/predicates/attr_spec.rb
|
|
165
167
|
- spec/unit/predicates/bool_spec.rb
|
|
168
|
+
- spec/unit/predicates/case_spec.rb
|
|
166
169
|
- spec/unit/predicates/date_spec.rb
|
|
167
170
|
- spec/unit/predicates/date_time_spec.rb
|
|
168
171
|
- spec/unit/predicates/decimal_spec.rb
|
|
@@ -198,7 +201,7 @@ files:
|
|
|
198
201
|
- spec/unit/rule/predicate_spec.rb
|
|
199
202
|
- spec/unit/rule_compiler_spec.rb
|
|
200
203
|
- spec/unit/rule_spec.rb
|
|
201
|
-
homepage: https://github.com/
|
|
204
|
+
homepage: https://github.com/dry-rb/dry-logic
|
|
202
205
|
licenses:
|
|
203
206
|
- MIT
|
|
204
207
|
metadata: {}
|
|
@@ -218,7 +221,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
218
221
|
version: '0'
|
|
219
222
|
requirements: []
|
|
220
223
|
rubyforge_project:
|
|
221
|
-
rubygems_version: 2.
|
|
224
|
+
rubygems_version: 2.6.11
|
|
222
225
|
signing_key:
|
|
223
226
|
specification_version: 4
|
|
224
227
|
summary: Predicate logic with rule composition
|
|
@@ -242,6 +245,7 @@ test_files:
|
|
|
242
245
|
- spec/unit/predicates/array_spec.rb
|
|
243
246
|
- spec/unit/predicates/attr_spec.rb
|
|
244
247
|
- spec/unit/predicates/bool_spec.rb
|
|
248
|
+
- spec/unit/predicates/case_spec.rb
|
|
245
249
|
- spec/unit/predicates/date_spec.rb
|
|
246
250
|
- spec/unit/predicates/date_time_spec.rb
|
|
247
251
|
- spec/unit/predicates/decimal_spec.rb
|