dry-logic 1.0.3 → 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6a09361d1d78293fe7254b7c92dd29b26df899630db88cf5aa9c8a99b369eb38
4
- data.tar.gz: 8aa9c03d77c492207dbef23a8b06d10f698e0f54def07e356847e4116eb9ca69
3
+ metadata.gz: 2eaa5ac48636ac8735eb5acfd455b0a6cc23887730500a3738a0e6b79b105187
4
+ data.tar.gz: 98d6ba8d611d80f4a1eb0ef3aa52dfcf976ef46ceabe92040f9090caaa98a4cb
5
5
  SHA512:
6
- metadata.gz: 5780b5badd5db51a5bd8f8c275cf114a786d0860be4c949a88327b243476a779a020d4e3323e2561fa96ba87382e64b63cdc473b10ce346d13ea533fc67b1936
7
- data.tar.gz: 649e7727b08808abf58378ffaa191796945070e45f2bf5c502b560f7c1a33506d5e17d55cef52c52827431d145bb1907bbc81622ff64870428cfdbd0afec3bdb
6
+ metadata.gz: 9de80f29b7ee5b3d8303a6834a94f20442ac3c78d9c90b634c91a7d6d7e620a5c96eea6d7142fbe361561d5076261f8ec54d0cfd6ebbdd05926a4b59d77b1919
7
+ data.tar.gz: 56ed2dc66cd66fd80d7437c5f75adee53dcfbb8e721b1d83a87d1e6fca35fab3dd8bb04f7cdb00c35c64d70f8d0685bed2900b2835bc7f710cacda8e034aa0f0
@@ -1,9 +1,6 @@
1
- version: "2"
1
+ # this file is managed by dry-rb/devtools project
2
2
 
3
- prepare:
4
- fetch:
5
- - url: "https://raw.githubusercontent.com/dry-rb/devtools/master/.rubocop.yml"
6
- path: ".rubocop.yml"
3
+ version: "2"
7
4
 
8
5
  exclude_patterns:
9
6
  - "benchmarks/"
@@ -0,0 +1,10 @@
1
+ ---
2
+ name: "⚠️ Please don't ask for support via issues"
3
+ about: See CONTRIBUTING.md for more information
4
+ title: ''
5
+ labels: ''
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+
@@ -0,0 +1,34 @@
1
+ ---
2
+ name: "\U0001F41B Bug report"
3
+ about: See CONTRIBUTING.md for more information
4
+ title: ''
5
+ labels: bug
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ **Before you submit this: WE ONLY ACCEPT BUG REPORTS AND FEATURE REQUESTS**
11
+
12
+ For more information see [our contribution guidelines](https://github.com/rom-rb/rom/blob/master/CONTRIBUTING.md)
13
+
14
+ **Before you report**
15
+
16
+ :warning: If you have a problem related to a schema, please **report it under [dry-schema issues](https://github.com/dry-rb/dry-schema/issues/new?assignees=&labels=bug&template=---bug-report.md&title=)** instead.
17
+
18
+ **Describe the bug**
19
+
20
+ A clear and concise description of what the bug is.
21
+
22
+ **To Reproduce**
23
+
24
+ Provide detailed steps to reproduce, an executable script would be best.
25
+
26
+ **Expected behavior**
27
+
28
+ A clear and concise description of what you expected to happen.
29
+
30
+ **Your environment**
31
+
32
+ - Affects my production application: **YES/NO**
33
+ - Ruby version: ...
34
+ - OS: ...
@@ -0,0 +1,18 @@
1
+ ---
2
+ name: "\U0001F6E0 Feature request"
3
+ about: See CONTRIBUTING.md for more information
4
+ title: ''
5
+ labels: feature
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ Summary of what the feature is supposed to do.
11
+
12
+ ## Examples
13
+
14
+ Code examples showing how the feature could be used.
15
+
16
+ ## Resources
17
+
18
+ Additional information, like a link to the discussion forum thread where the feature was discussed etc.
@@ -0,0 +1,70 @@
1
+ name: ci
2
+
3
+ on:
4
+ push:
5
+ paths:
6
+ - .github/workflows/ci.yml
7
+ - lib/**
8
+ - spec/**
9
+
10
+ jobs:
11
+ tests-mri:
12
+ runs-on: ubuntu-latest
13
+ strategy:
14
+ fail-fast: false
15
+ matrix:
16
+ ruby: ["2.6.x", "2.5.x", "2.4.x"]
17
+ include:
18
+ - ruby: "2.6.x"
19
+ coverage: "true"
20
+ steps:
21
+ - uses: actions/checkout@v1
22
+ - name: Set up Ruby
23
+ uses: actions/setup-ruby@v1
24
+ with:
25
+ ruby-version: ${{matrix.ruby}}
26
+ - name: Download test reporter
27
+ if: "matrix.coverage == 'true'"
28
+ run: |
29
+ mkdir -p tmp/
30
+ curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./tmp/cc-test-reporter
31
+ chmod +x ./tmp/cc-test-reporter
32
+ ./tmp/cc-test-reporter before-build
33
+ - name: Run all tests
34
+ env:
35
+ COVERAGE: ${{matrix.coverage}}
36
+ run: |
37
+ gem install bundler
38
+ bundle install --jobs 4 --retry 3 --without tools docs
39
+ bundle exec rake
40
+ - name: Send coverage results
41
+ if: "matrix.coverage == 'true'"
42
+ env:
43
+ CC_TEST_REPORTER_ID: ${{secrets.CC_TEST_REPORTER_ID}}
44
+ GIT_COMMIT_SHA: ${{github.sha}}
45
+ GIT_BRANCH: ${{github.ref}}
46
+ GIT_COMMITTED_AT: ${{github.event.head_commit.timestamp}}
47
+ run: |
48
+ GIT_BRANCH=`ruby -e "puts ENV['GITHUB_REF'].split('/', 3).last"` \
49
+ GIT_COMMITTED_AT=`ruby -r time -e "puts Time.iso8601(ENV['GIT_COMMITTED_AT']).to_i"` \
50
+ ./tmp/cc-test-reporter after-build
51
+
52
+ tests-others:
53
+ runs-on: ubuntu-latest
54
+ strategy:
55
+ fail-fast: false
56
+ matrix:
57
+ image: ["jruby:9.2.8", "ruby:rc"]
58
+ container:
59
+ image: ${{matrix.image}}
60
+ steps:
61
+ - uses: actions/checkout@v1
62
+ - name: Install git
63
+ run: |
64
+ apt-get update
65
+ apt-get install -y --no-install-recommends git
66
+ - name: Run all tests
67
+ run: |
68
+ gem install bundler
69
+ bundle install --jobs 4 --retry 3 --without tools docs
70
+ bundle exec rspec
@@ -0,0 +1,34 @@
1
+ # this file is managed by dry-rb/devtools project
2
+
3
+ name: docsite
4
+
5
+ on:
6
+ push:
7
+ paths:
8
+ - docsite/**
9
+ - .github/workflows/docsite.yml
10
+ branches:
11
+ - master
12
+ - release-**
13
+ tags:
14
+
15
+ jobs:
16
+ update-docs:
17
+ runs-on: ubuntu-latest
18
+ steps:
19
+ - uses: actions/checkout@v1
20
+ - name: Set up Ruby
21
+ uses: actions/setup-ruby@v1
22
+ with:
23
+ ruby-version: "2.6.x"
24
+ - name: Install dependencies
25
+ run: |
26
+ gem install bundler
27
+ bundle install --jobs 4 --retry 3 --without benchmarks sql
28
+ - name: Symlink ossy
29
+ run: mkdir -p bin && ln -sf "$(bundle show ossy)/bin/ossy" bin/ossy
30
+ - name: Trigger dry-rb.org deploy
31
+ env:
32
+ GITHUB_LOGIN: dry-bot
33
+ GITHUB_TOKEN: ${{ secrets.GH_PAT }}
34
+ run: bin/ossy github workflow dry-rb/dry-rb.org ci
@@ -0,0 +1,34 @@
1
+ # this file is managed by dry-rb/devtools project
2
+
3
+ name: sync_configs
4
+
5
+ on:
6
+ repository_dispatch:
7
+
8
+ jobs:
9
+ sync-configs:
10
+ runs-on: ubuntu-latest
11
+ if: github.event.action == 'sync_configs'
12
+ steps:
13
+ - uses: actions/checkout@v1
14
+ - name: Update configuration files from devtools
15
+ env:
16
+ GITHUB_LOGIN: dry-bot
17
+ GITHUB_TOKEN: ${{ secrets.GH_PAT }}
18
+ run: |
19
+ git clone https://github.com/dry-rb/devtools.git tmp/devtools
20
+
21
+ if [ -f ".github/workflows/custom_ci.yml" ]; then
22
+ rsync -av --exclude '.github/workflows/ci.yml' tmp/devtools/shared/ . ;
23
+ else
24
+ rsync -av tmp/devtools/shared/ . ;
25
+ fi
26
+
27
+ git config --local user.email "dry-bot@dry-rb.org"
28
+ git config --local user.name "dry-bot"
29
+ git add -A
30
+ git commit -m "[devtools] config sync" || echo "nothing changed"
31
+ - name: Push changes
32
+ uses: ad-m/github-push-action@master
33
+ with:
34
+ github_token: ${{ secrets.GH_PAT }}
data/.gitignore CHANGED
@@ -6,4 +6,4 @@ tmp/
6
6
  pkg/
7
7
  .idea/
8
8
  Gemfile.lock
9
- .rubocop.yml
9
+
data/.rspec CHANGED
@@ -1,3 +1,4 @@
1
1
  --color
2
2
  --require spec_helper
3
3
  --order random
4
+
@@ -0,0 +1,89 @@
1
+ # this file is managed by dry-rb/devtools project
2
+
3
+ AllCops:
4
+ TargetRubyVersion: 2.4
5
+
6
+ Style/EachWithObject:
7
+ Enabled: false
8
+
9
+ Style/StringLiterals:
10
+ Enabled: true
11
+ EnforcedStyle: single_quotes
12
+
13
+ Style/Alias:
14
+ Enabled: false
15
+
16
+ Style/LambdaCall:
17
+ Enabled: false
18
+
19
+ Style/StabbyLambdaParentheses:
20
+ Enabled: false
21
+
22
+ Style/FormatString:
23
+ Enabled: false
24
+
25
+ Style/Documentation:
26
+ Enabled: false
27
+
28
+ Layout/SpaceInLambdaLiteral:
29
+ Enabled: false
30
+
31
+ Layout/MultilineMethodCallIndentation:
32
+ Enabled: true
33
+ EnforcedStyle: indented
34
+
35
+ Metrics/LineLength:
36
+ Max: 100
37
+
38
+ Metrics/MethodLength:
39
+ Max: 22
40
+
41
+ Metrics/ClassLength:
42
+ Max: 150
43
+
44
+ Metrics/AbcSize:
45
+ Max: 20
46
+
47
+ Metrics/BlockLength:
48
+ Enabled: false
49
+
50
+ Metrics/CyclomaticComplexity:
51
+ Enabled: true
52
+ Max: 10
53
+
54
+ Lint/BooleanSymbol:
55
+ Enabled: false
56
+
57
+ Style/AccessModifierDeclarations:
58
+ Enabled: false
59
+
60
+ Style/BlockDelimiters:
61
+ Enabled: false
62
+
63
+ Layout/IndentFirstArrayElement:
64
+ EnforcedStyle: consistent
65
+
66
+ Style/ClassAndModuleChildren:
67
+ Exclude:
68
+ - "spec/**/*_spec.rb"
69
+
70
+ Lint/HandleExceptions:
71
+ Exclude:
72
+ - "spec/spec_helper.rb"
73
+
74
+ Naming/FileName:
75
+ Exclude:
76
+ - "lib/dry-*.rb"
77
+
78
+ Style/SymbolArray:
79
+ Exclude:
80
+ - "spec/**/*_spec.rb"
81
+
82
+ Style/ConditionalAssignment:
83
+ Enabled: false
84
+
85
+ Naming/MethodName:
86
+ Enabled: false
87
+
88
+ Style/AsciiComments:
89
+ Enabled: false
@@ -1,14 +1,26 @@
1
+ # v1.0.5 2019-11-07
2
+
3
+ - Make `format?` tolerant to `nil` values. It already worked like that before, but starting Ruby 2.7 it would produce warnings. Now it won't. Don't rely on this behavior, it's only added to make tests pass in dry-schema. Use explicit type checks instead (@flash-gordon)
4
+
5
+ [Compare v1.0.4...v1.0.5](https://github.com/dry-rb/dry-logic/compare/v1.0.4...v1.0.5)
6
+
7
+ # v1.0.4 2019-11-06
8
+
9
+ - Fix keyword warnings (@flash-gordon)
10
+
11
+ [Compare v1.0.3...v1.0.4](https://github.com/dry-rb/dry-logic/compare/v1.0.3...v1.0.4)
12
+
1
13
  # v1.0.3 2019-08-01
2
14
 
3
15
  ### Added
4
16
 
5
- * `bytesize?` predicate (@bmalinconico)
6
- * `min_bytesize?` predicate (@bmalinconico)
7
- * `max_bytesize? predicate (@bmalinconico)
17
+ - `bytesize?` predicate (@bmalinconico)
18
+ - `min_bytesize?` predicate (@bmalinconico)
19
+ - `max_bytesize? predicate (@bmalinconico)
8
20
 
9
21
  ### Changed
10
22
 
11
- * Min ruby version was set to `>= 2.4.0` (@flash-gordon)
23
+ - Min ruby version was set to `>= 2.4.0` (@flash-gordon)
12
24
 
13
25
  [Compare v1.0.2...v1.0.3](https://github.com/dry-rb/dry-logic/compare/v1.0.2...v1.0.3)
14
26
 
@@ -31,13 +43,13 @@ This release was removed from rubygems because it broke dry-schema.
31
43
 
32
44
  # v1.0.0 2019-04-23
33
45
 
34
- * Version bump to `1.0.0` (flash-gordon)
46
+ - Version bump to `1.0.0` (flash-gordon)
35
47
 
36
48
  [Compare v0.6.1...v1.0.0](https://github.com/dry-rb/dry-logic/compare/v0.6.1...v1.0.0)
37
49
 
38
50
  # v0.6.1 2019-04-18
39
51
 
40
- * Fix a regression in dry-validation 0.x for argument-less predicates (flash-gordon)
52
+ - Fix a regression in dry-validation 0.x for argument-less predicates (flash-gordon)
41
53
 
42
54
  [Compare v0.6.0...v0.6.1](https://github.com/dry-rb/dry-logic/compare/v0.6.0...v0.6.1)
43
55
 
@@ -45,11 +57,11 @@ This release was removed from rubygems because it broke dry-schema.
45
57
 
46
58
  ### Added
47
59
 
48
- * Generating hints can be disabled by building `Operations::And` with `hints: false` option set (solnic)
60
+ - Generating hints can be disabled by building `Operations::And` with `hints: false` option set (solnic)
49
61
 
50
62
  ### Changed
51
63
 
52
- * `Rule` construction has been optimized so that currying and application is multiple-times faster (flash-gordon)
64
+ - `Rule` construction has been optimized so that currying and application is multiple-times faster (flash-gordon)
53
65
 
54
66
  [Compare v0.5.0...v0.6.0](https://github.com/dry-rb/dry-logic/compare/v0.5.0...v0.6.0)
55
67
 
@@ -0,0 +1,13 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
4
+
5
+ We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion.
6
+
7
+ Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
8
+
9
+ Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
10
+
11
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
12
+
13
+ This Code of Conduct is adapted from the [Contributor Covenant](http:contributor-covenant.org), version 1.4.0, available at [https://www.contributor-covenant.org/version/1/4/code-of-conduct](https://www.contributor-covenant.org/version/1/4/code-of-conduct)
@@ -10,7 +10,7 @@ Report a feature request **only after discussing it first on [discourse.dry-rb.o
10
10
 
11
11
  ## Reporting questions, support requests, ideas, concerns etc.
12
12
 
13
- **PLEASE DON'T** - use [discourse.dry-rb.org](https://discourse.dry-rb.org) instead.
13
+ **PLEASE DON'T** - use [discourse.dry-rb.org](http://discourse.dry-rb.org) instead.
14
14
 
15
15
  # Pull Request Guidelines
16
16
 
@@ -26,4 +26,4 @@ Other requirements:
26
26
 
27
27
  # Asking for help
28
28
 
29
- If these guidelines aren't helpful, and you're stuck, please post a message on [discourse.dry-rb.org](https://discourse.dry-rb.org).
29
+ If these guidelines aren't helpful, and you're stuck, please post a message on [discourse.dry-rb.org](https://discourse.dry-rb.org) or join [our chat](https://dry-rb.zulipchat.com).
data/Gemfile CHANGED
@@ -12,4 +12,5 @@ group :tools do
12
12
  gem 'pry-byebug', platform: :mri
13
13
  gem 'benchmark-ips', platform: :mri
14
14
  gem 'hotch', platform: :mri
15
+ gem 'ossy', git: 'https://github.com/solnic/ossy.git', branch: 'master'
15
16
  end
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2014 Ruby Object Mapper
3
+ Copyright (c) 2015-2019 dry-rb team
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy of
6
6
  this software and associated documentation files (the "Software"), to deal in
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  [gem]: https://rubygems.org/gems/dry-logic
2
- [travis]: https://travis-ci.com/dry-rb/dry-logic
2
+ [ci]: https://github.com/dry-rb/dry-logic/actions?query=workflow%3Aci
3
3
  [codeclimate]: https://codeclimate.com/github/dry-rb/dry-logic
4
4
  [chat]: https://dry-rb.zulipchat.com
5
5
  [inchpages]: http://inch-ci.org/github/dry-rb/dry-logic
@@ -7,20 +7,20 @@
7
7
  # dry-logic [![Join the chat at https://dry-rb.zulipchat.com](https://img.shields.io/badge/dry--rb-join%20chat-%23346b7a.svg)][chat]
8
8
 
9
9
  [![Gem Version](https://badge.fury.io/rb/dry-logic.svg)][gem]
10
- [![Build Status](https://travis-ci.com/dry-rb/dry-logic.svg?branch=master)][travis]
10
+ [![Build Status](https://github.com/dry-rb/dry-logic/workflows/ci/badge.svg)][ci]
11
11
  [![Code Climate](https://codeclimate.com/github/dry-rb/dry-logic/badges/gpa.svg)][codeclimate]
12
12
  [![Test Coverage](https://codeclimate.com/github/dry-rb/dry-logic/badges/coverage.svg)][codeclimate]
13
13
  [![Inline docs](http://inch-ci.org/github/dry-rb/dry-logic.svg?branch=master)][inchpages]
14
14
 
15
15
  Predicate logic and rule composition used by:
16
16
 
17
- * [dry-types](https://github.com/dry-rb/dry-types) for constrained types
18
- * [dry-schema](https://github.com/dry-rb/dry-schema) and [dry-validation](https://github.com/dry-rb/dry-validation) for composing validation rules
19
- * your project...?
17
+ - [dry-types](https://github.com/dry-rb/dry-types) for constrained types
18
+ - [dry-schema](https://github.com/dry-rb/dry-schema) and [dry-validation](https://github.com/dry-rb/dry-validation) for composing validation rules
19
+ - your project...?
20
20
 
21
21
  ## Links
22
22
 
23
- * [Documentation](http://dry-rb.org/gems/dry-logic)
23
+ - [Documentation](http://dry-rb.org/gems/dry-logic)
24
24
 
25
25
  ## Contributing
26
26
 
@@ -0,0 +1,54 @@
1
+ ---
2
+ title: Introduction
3
+ description: Predicate logic with composable rules
4
+ layout: gem-single
5
+ type: gem
6
+ name: dry-logic
7
+ sections:
8
+ - predicates
9
+ - operations
10
+ ---
11
+
12
+ Predicate logic and rule composition used by:
13
+
14
+ * [dry-types](https://github.com/dry-rb/dry-types) for constrained types
15
+ * [dry-validation](https://github.com/dry-rb/dry-validation) for composing validation rules
16
+ * your project...?
17
+
18
+ ## Synopsis
19
+
20
+ ``` ruby
21
+ require 'dry/logic'
22
+ require 'dry/logic/predicates'
23
+
24
+ include Dry::Logic
25
+
26
+ # Rule::Predicate will only apply its predicate to its input, that’s all
27
+
28
+ # require input to have the key :user
29
+ user_present = Rule::Predicate.new(Predicates[:key?]).curry(:user)
30
+ # curry allows us to prepare predicates with args, without the input
31
+
32
+ # require value to be greater than 18
33
+ min_18 = Rule::Predicate.new(Predicates[:gt?]).curry(18)
34
+
35
+ # use the min_18 predicate on the the value of user[:age]
36
+ has_min_age = Operations::Key.new(min_18, name: [:user, :age])
37
+
38
+ user_rule = user_present & has_min_age
39
+
40
+ user_rule.(user: { age: 19 }).success?
41
+ # => true
42
+
43
+ user_rule.(user: { age: 18 }).success?
44
+ # => false
45
+
46
+ user_rule.(user: { age: 'seventeen' })
47
+ # => ArgumentError: comparison of String with 18 failed
48
+
49
+ user_rule.(user: { })
50
+ # => NoMethodError: undefined method `>' for nil:NilClass
51
+
52
+ user_rule.({}).success?
53
+ # => false
54
+ ```
@@ -0,0 +1,62 @@
1
+ ---
2
+ title: Operations
3
+ layout: gem-single
4
+ name: dry-logic
5
+ ---
6
+
7
+ Dry-logic uses operations to interact with the input passed to the different rules.
8
+
9
+ ``` ruby
10
+ require 'dry/logic'
11
+ require 'dry/logic/predicates'
12
+
13
+ include Dry::Logic
14
+
15
+ user_present = Rule::Predicate.new(Predicates[:key?]).curry(:user)
16
+
17
+ min_18 = Rule::Predicate.new(Predicates[:gt?]).curry(18)
18
+
19
+ # Here Operations::Key and Rule::Predicate are use to compose and logic based on the value of a given key e.g [:user, :age]
20
+ has_min_age = Operations::Key.new(min_18, name: [:user, :age])
21
+ # => #<Dry::Logic::Operations::Key rules=[#<Dry::Logic::Rule::Predicate predicate=#<Method: Module(Dry::Logic::Predicates::Methods)#gt?> options={:args=>[18]}>] options={:name=>[:user, :age], :evaluator=>#<Dry::Logic::Evaluator::Key path=[:user, :age]>, :path=>[:user, :age]}>
22
+
23
+ # Thanks to the composable structure of the library we can use multiple Rules and Operations to create custom logic
24
+ user_rule = user_present & has_min_age
25
+
26
+ user_rule.(user: { age: 19 }).success?
27
+ # => true
28
+ ```
29
+
30
+ * Built-in:
31
+ - `and`
32
+ - `or`
33
+ - `key`
34
+ - `attr`
35
+ - `binary`
36
+ - `check`
37
+ - `each`
38
+ - `implication`
39
+ - `negation`
40
+ - `set`
41
+ - `xor`
42
+
43
+ Another example, lets create the `all?` method from the `Enumerable` module.
44
+
45
+ ``` ruby
46
+ require 'dry/logic'
47
+ require 'dry/logic/predicates'
48
+
49
+ include Dry::Logic
50
+
51
+ def all?(value)
52
+ Operations::Each.new(Rule::Predicate.new(Predicates[:gt?]).curry(value))
53
+ end
54
+
55
+ all_6 = all?(6)
56
+
57
+ all_6.([6,7,8,9]).success?
58
+ # => true
59
+
60
+ all_6.([1,2,3,4]).success?
61
+ # => false
62
+ ```
@@ -0,0 +1,102 @@
1
+ ---
2
+ title: Predicates
3
+ layout: gem-single
4
+ name: dry-logic
5
+ ---
6
+
7
+ Dry-logic comes with a lot predicates to compose multiple rules:
8
+
9
+ ``` ruby
10
+ require 'dry/logic'
11
+ require 'dry/logic/predicates'
12
+
13
+ include Dry::Logic
14
+ ```
15
+
16
+ Now you can access all built-in predicates:
17
+
18
+ ``` ruby
19
+ Predicates[:key?]
20
+ # => #<Method: Module(Dry::Logic::Predicates::Methods)#key?>
21
+ ```
22
+
23
+ In the end predicates return true or false.
24
+
25
+ ```ruby
26
+ Predicates[:key?].(:name, {name: 'John'})
27
+ # => true
28
+ ```
29
+
30
+ * Built-in:
31
+ - `type?`
32
+ - `none?`
33
+ - `key?`
34
+ - `attr?`
35
+ - `empty?`
36
+ - `filled?`
37
+ - `bool?`
38
+ - `date?`
39
+ - `date_time?`
40
+ - `time?`
41
+ - `number?`
42
+ - `int?`
43
+ - `float?`
44
+ - `decimal?`
45
+ - `str?`
46
+ - `hash?`
47
+ - `array?`
48
+ - `odd?`
49
+ - `even?`
50
+ - `lt?`
51
+ - `gt?`
52
+ - `lteq?`
53
+ - `gteq?`
54
+ - `size?`
55
+ - `min_size?`
56
+ - `max_size?`
57
+ - `bytesize?`
58
+ - `min_bytesize?`
59
+ - `max_bytesize?`
60
+ - `inclusion?`
61
+ - `exclusion?`
62
+ - `included_in?`
63
+ - `excluded_from?`
64
+ - `includes?`
65
+ - `excludes?`
66
+ - `eql?`
67
+ - `not_eql?`
68
+ - `is?`
69
+ - `case?`
70
+ - `true?`
71
+ - `false?`
72
+ - `format?`
73
+ - `respond_to?`
74
+ - `predicate`
75
+ - `uuid_v4?`
76
+
77
+ With predicates you can build more composable and complex operations:
78
+ For example, let's say we want to check that a given input is a hash and has a specify key.
79
+
80
+ ``` ruby
81
+ require 'dry/logic'
82
+ require 'dry/logic/predicates'
83
+
84
+ include Dry::Logic
85
+
86
+ is_hash = Rule::Predicate.new(Predicates[:type?]).curry(Hash)
87
+ # => #<Dry::Logic::Rule::Predicate predicate=#<Method: Module(Dry::Logic::Predicates::Methods)#type?> options={:args=>[:hash]}>
88
+ name_key = Rule::Predicate.new(Predicates[:key?]).curry(:name)
89
+ # => #<Dry::Logic::Rule::Predicate predicate=#<Method: Module(Dry::Logic::Predicates::Methods)#key?> options={:args=>[:name]}>
90
+
91
+ hash_with_key = is_hash & name_key
92
+ # => #<Dry::Logic::Operations::And rules=[#<Dry::Logic::Rule::Predicate predicate=#<Method: Module(Dry::Logic::Predicates::Methods)#type?> options={:args=>[:hash]}>, #<Dry::Logic::Rule::Predicate predicate=#<Method: Module(Dry::Logic::Predicates::Methods)#key?> options={:args=>[:name]}>] options={}>
93
+
94
+ hash_with_key.(name: 'John').success?
95
+ # => true
96
+
97
+ hash_with_key.(not_valid: 'John').success?
98
+ # => false
99
+
100
+ hash_with_key.([1,2]).success?
101
+ # => false
102
+ ```
@@ -15,6 +15,11 @@ Gem::Specification.new do |spec|
15
15
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
16
16
  spec.require_paths = ['lib']
17
17
  spec.required_ruby_version = '>= 2.4.0'
18
+
19
+ spec.metadata = {
20
+ 'source_code_uri' => 'https://github.com/dry-rb/dry-logic',
21
+ 'changelog_uri' => 'https://github.com/dry-rb/dry-logic/blob/master/CHANGELOG.md'
22
+ }
18
23
 
19
24
  spec.add_runtime_dependency 'concurrent-ruby', '~> 1.0'
20
25
  spec.add_runtime_dependency 'dry-core', '~> 0.2'
@@ -26,15 +26,15 @@ module Dry
26
26
  end
27
27
 
28
28
  def curry(*args)
29
- new(rules.map { |rule| rule.curry(*args) }, options)
29
+ new(rules.map { |rule| rule.curry(*args) }, **options)
30
30
  end
31
31
 
32
32
  def new(rules, **new_options)
33
- self.class.new(*rules, options.merge(new_options))
33
+ self.class.new(*rules, **options, **new_options)
34
34
  end
35
35
 
36
36
  def with(new_options)
37
- new(rules, options.merge(new_options))
37
+ new(rules, **options, **new_options)
38
38
  end
39
39
 
40
40
  def to_ast
@@ -9,7 +9,7 @@ module Dry
9
9
  class And < Binary
10
10
  attr_reader :hints
11
11
 
12
- def initialize(*)
12
+ def initialize(*, **)
13
13
  super
14
14
  @hints = options.fetch(:hints, true)
15
15
  end
@@ -17,7 +17,7 @@ module Dry
17
17
  keys = options.fetch(:keys)
18
18
  evaluator = Evaluator::Set.new(keys)
19
19
 
20
- super(rule, options.merge(evaluator: evaluator))
20
+ super(rule, **options, evaluator: evaluator)
21
21
  end
22
22
  end
23
23
 
@@ -12,13 +12,13 @@ module Dry
12
12
 
13
13
  attr_reader :path
14
14
 
15
- def self.new(rules, options)
15
+ def self.new(rules, **options)
16
16
  if options[:evaluator]
17
17
  super
18
18
  else
19
19
  name = options.fetch(:name)
20
20
  eval = options.fetch(:evaluator, evaluator(name))
21
- super(rules, options.merge(evaluator: eval, path: name))
21
+ super(rules, **options, evaluator: eval, path: name)
22
22
  end
23
23
  end
24
24
 
@@ -199,7 +199,7 @@ module Dry
199
199
  end
200
200
 
201
201
  def format?(regex, input)
202
- regex.match?(input)
202
+ !input.nil? && regex.match?(input)
203
203
  end
204
204
 
205
205
  def case?(pattern, input)
@@ -68,11 +68,11 @@ module Dry
68
68
 
69
69
  def bind(object)
70
70
  if predicate.respond_to?(:bind)
71
- self.class.build(predicate.bind(object), options)
71
+ self.class.build(predicate.bind(object), **options)
72
72
  else
73
73
  self.class.build(
74
74
  -> *args { object.instance_exec(*args, &predicate) },
75
- options.merge(arity: arity, parameters: parameters)
75
+ **options, arity: arity, parameters: parameters
76
76
  )
77
77
  end
78
78
  end
@@ -82,7 +82,7 @@ module Dry
82
82
  end
83
83
 
84
84
  def with(new_opts)
85
- self.class.build(predicate, options.merge(new_opts))
85
+ self.class.build(predicate, **options, **new_opts)
86
86
  end
87
87
 
88
88
  def parameters
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Dry
4
4
  module Logic
5
- VERSION = '1.0.3'.freeze
5
+ VERSION = '1.0.5'
6
6
  end
7
7
  end
@@ -1,15 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- if RUBY_ENGINE == 'ruby' && ENV['COVERAGE'] == 'true'
4
- require 'yaml'
5
- rubies = YAML.load(File.read(File.join(__dir__, '..', '.travis.yml')))['rvm']
6
- latest_mri = rubies.select { |v| v =~ /\A\d+\.\d+.\d+\z/ }.max
7
-
8
- if RUBY_VERSION == latest_mri
9
- require 'simplecov'
10
- SimpleCov.start do
11
- add_filter '/spec/'
12
- end
3
+ if ENV['COVERAGE'] == 'true'
4
+ require 'simplecov'
5
+ SimpleCov.start do
6
+ add_filter '/spec/'
13
7
  end
14
8
  end
15
9
 
@@ -7,7 +7,7 @@ RSpec.describe Dry::Logic::Predicates, '#format?' do
7
7
 
8
8
  context 'when value matches provided regexp' do
9
9
  let(:arguments_list) do
10
- [['Foo', /^F/]]
10
+ [[/^F/, 'Foo']]
11
11
  end
12
12
 
13
13
  it_behaves_like 'a passing predicate'
@@ -15,7 +15,15 @@ RSpec.describe Dry::Logic::Predicates, '#format?' do
15
15
 
16
16
  context 'when value does not match provided regexp' do
17
17
  let(:arguments_list) do
18
- [['Bar', /^F/]]
18
+ [[/^F/, 'Bar']]
19
+ end
20
+
21
+ it_behaves_like 'a failing predicate'
22
+ end
23
+
24
+ context 'when input is nil' do
25
+ let(:arguments_list) do
26
+ [[/^F/, nil]]
19
27
  end
20
28
 
21
29
  it_behaves_like 'a failing predicate'
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  RSpec.describe Dry::Logic::Rule do
4
- subject(:rule) { Rule.build(predicate, options) }
4
+ subject(:rule) { Rule.build(predicate, **options) }
5
5
 
6
6
  let(:predicate) { -> { true } }
7
7
  let(:options) { {} }
@@ -204,7 +204,7 @@ RSpec.describe Dry::Logic::Rule do
204
204
  describe 'constants' do
205
205
  let(:options) { { args: [], arity: 0 } }
206
206
 
207
- fit 'accepts variable number of arguments' do
207
+ it 'accepts variable number of arguments' do
208
208
  expect(rule.method(:call).arity).to be(-1)
209
209
  expect(rule.method(:[]).arity).to be(-1)
210
210
  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: 1.0.3
4
+ version: 1.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Solnica
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-01 00:00:00.000000000 Z
11
+ date: 2019-11-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -102,10 +102,17 @@ extensions: []
102
102
  extra_rdoc_files: []
103
103
  files:
104
104
  - ".codeclimate.yml"
105
+ - ".github/ISSUE_TEMPLATE/----please-don-t-ask-for-support-via-issues.md"
106
+ - ".github/ISSUE_TEMPLATE/---bug-report.md"
107
+ - ".github/ISSUE_TEMPLATE/---feature-request.md"
108
+ - ".github/workflows/ci.yml"
109
+ - ".github/workflows/docsite.yml"
110
+ - ".github/workflows/sync_configs.yml"
105
111
  - ".gitignore"
106
112
  - ".rspec"
107
- - ".travis.yml"
113
+ - ".rubocop.yml"
108
114
  - CHANGELOG.md
115
+ - CODE_OF_CONDUCT.md
109
116
  - CONTRIBUTING.md
110
117
  - Gemfile
111
118
  - LICENSE
@@ -114,6 +121,9 @@ files:
114
121
  - benchmarks/rule_application.rb
115
122
  - benchmarks/setup.rb
116
123
  - bin/console
124
+ - docsite/source/index.html.md
125
+ - docsite/source/operations.html.md
126
+ - docsite/source/predicates.html.md
117
127
  - dry-logic.gemspec
118
128
  - examples/basic.rb
119
129
  - lib/dry-logic.rb
@@ -206,7 +216,9 @@ files:
206
216
  homepage: https://github.com/dry-rb/dry-logic
207
217
  licenses:
208
218
  - MIT
209
- metadata: {}
219
+ metadata:
220
+ source_code_uri: https://github.com/dry-rb/dry-logic
221
+ changelog_uri: https://github.com/dry-rb/dry-logic/blob/master/CHANGELOG.md
210
222
  post_install_message:
211
223
  rdoc_options: []
212
224
  require_paths:
@@ -222,7 +234,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
222
234
  - !ruby/object:Gem::Version
223
235
  version: '0'
224
236
  requirements: []
225
- rubygems_version: 3.0.3
237
+ rubygems_version: 3.0.6
226
238
  signing_key:
227
239
  specification_version: 4
228
240
  summary: Predicate logic with rule composition
@@ -1,31 +0,0 @@
1
- language: ruby
2
- cache: bundler
3
- bundler_args: --without benchmarks tools
4
- before_script:
5
- - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
6
- - chmod +x ./cc-test-reporter
7
- - ./cc-test-reporter before-build
8
- after_script:
9
- - "[ -d coverage ] && ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT"
10
- script:
11
- - bundle exec rake
12
- rvm:
13
- - 2.6.3
14
- - 2.5.5
15
- - 2.4.6
16
- - jruby-9.2.7.0
17
- - truffleruby
18
- env:
19
- global:
20
- - COVERAGE=true
21
- matrix:
22
- allow_failures:
23
- - rvm: truffleruby
24
- notifications:
25
- email: false
26
- webhooks:
27
- urls:
28
- - https://dry-rb.zulipchat.com/api/v1/external/travis?api_key=SY8LLz6fShd4TJeLDXEdT0eBEgRqT2lv&stream=notifications&topic=ci
29
- on_success: change # options: [always|never|change] default: always
30
- on_failure: always # options: [always|never|change] default: always
31
- on_start: false # default: false