dry-monads 1.3.1 → 1.3.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 +10 -39
- data/.github/ISSUE_TEMPLATE/----please-don-t-ask-for-support-via-issues.md +10 -0
- data/.github/ISSUE_TEMPLATE/---bug-report.md +34 -0
- data/.github/ISSUE_TEMPLATE/---feature-request.md +18 -0
- data/.github/workflows/ci.yml +74 -0
- data/.github/workflows/docsite.yml +34 -0
- data/.github/workflows/sync_configs.yml +34 -0
- data/.rspec +1 -0
- data/.rubocop.yml +89 -0
- data/CHANGELOG.md +21 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/CONTRIBUTING.md +4 -4
- data/Gemfile +4 -1
- data/LICENSE +17 -17
- data/README.md +2 -2
- data/docsite/source/case-equality.html.md +42 -0
- data/docsite/source/do-notation.html.md +207 -0
- data/docsite/source/getting-started.html.md +142 -0
- data/docsite/source/index.html.md +179 -0
- data/docsite/source/list.html.md +87 -0
- data/docsite/source/maybe.html.md +146 -0
- data/docsite/source/pattern-matching.html.md +68 -0
- data/docsite/source/result.html.md +190 -0
- data/docsite/source/task.html.md +126 -0
- data/docsite/source/tracing-failures.html.md +32 -0
- data/docsite/source/try.html.md +76 -0
- data/docsite/source/unit.html.md +36 -0
- data/docsite/source/validated.html.md +88 -0
- data/lib/dry/monads.rb +1 -0
- data/lib/dry/monads/{undefined.rb → constants.rb} +3 -1
- data/lib/dry/monads/do.rb +2 -1
- data/lib/dry/monads/do/all.rb +2 -2
- data/lib/dry/monads/do/mixin.rb +2 -3
- data/lib/dry/monads/maybe.rb +2 -4
- data/lib/dry/monads/result.rb +1 -1
- data/lib/dry/monads/right_biased.rb +52 -7
- data/lib/dry/monads/validated.rb +1 -1
- data/lib/dry/monads/version.rb +1 -1
- metadata +25 -5
- data/.travis.yml +0 -38
@@ -0,0 +1,88 @@
|
|
1
|
+
---
|
2
|
+
title: Validated
|
3
|
+
layout: gem-single
|
4
|
+
name: dry-monads
|
5
|
+
---
|
6
|
+
|
7
|
+
Suppose you've got a form to validate. If you are using `Result` combined with `Do` your code might look like this:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
require 'dry/monads'
|
11
|
+
|
12
|
+
class CreateAccount
|
13
|
+
include Dry::Monads[:result, :do]
|
14
|
+
|
15
|
+
def call(form)
|
16
|
+
name = yield validate_name(form)
|
17
|
+
email = yield validate_email(form)
|
18
|
+
password = yield validate_password(form)
|
19
|
+
|
20
|
+
user = repo.create_user(
|
21
|
+
name: name,
|
22
|
+
email: email,
|
23
|
+
password: password
|
24
|
+
)
|
25
|
+
|
26
|
+
Success(user)
|
27
|
+
end
|
28
|
+
|
29
|
+
def validate_name(form)
|
30
|
+
# Success(name) or Failure(:invalid_name)
|
31
|
+
end
|
32
|
+
|
33
|
+
def validate_email(form)
|
34
|
+
# Success(email) or Failure(:invalid_email)
|
35
|
+
end
|
36
|
+
|
37
|
+
def validate_password(form)
|
38
|
+
# Success(password) or Failure(:invalid_password)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
```
|
42
|
+
|
43
|
+
If any of the validation steps fails the user will see an error. The problem is if `name` is not valid the user won't see errors about invalid `email` and `password`, if any. `Validated` circumvents this particular problem.
|
44
|
+
|
45
|
+
`Validated` is actually not a monad but an applicative functor. This means you can't call `bind` on it. Instead, it can accumulate values in combination with `List`:
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
require 'dry/monads'
|
49
|
+
|
50
|
+
class CreateAccount
|
51
|
+
include Dry::Monads[:list, :result, :validated, :do]
|
52
|
+
|
53
|
+
def call(form)
|
54
|
+
name, email, password = yield List::Validated[
|
55
|
+
validate_name(form),
|
56
|
+
validate_email(form),
|
57
|
+
validate_password(form)
|
58
|
+
].traverse.to_result
|
59
|
+
|
60
|
+
user = repo.create_user(
|
61
|
+
name: name,
|
62
|
+
email: email,
|
63
|
+
password: password
|
64
|
+
)
|
65
|
+
|
66
|
+
Success(user)
|
67
|
+
end
|
68
|
+
|
69
|
+
def validate_name(form)
|
70
|
+
# Valid(name) or Invalid(:invalid_name)
|
71
|
+
end
|
72
|
+
|
73
|
+
def validate_email(form)
|
74
|
+
# Valid(email) or Invalid(:invalid_email)
|
75
|
+
end
|
76
|
+
|
77
|
+
def validate_password(form)
|
78
|
+
# Valid(password) or Invalid(:invalid_password)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
```
|
82
|
+
|
83
|
+
Here all validations will be processed at once, if any of them fails the result will be converted to a `Failure` wrapping the `List` of errors:
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
create_account.(form)
|
87
|
+
# => Failure(List[:invalid_name, :invalid_email])
|
88
|
+
```
|
data/lib/dry/monads.rb
CHANGED
data/lib/dry/monads/do.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'dry/monads/list'
|
2
2
|
require 'dry/monads/do/mixin'
|
3
|
+
require 'dry/monads/constants'
|
3
4
|
|
4
5
|
module Dry
|
5
6
|
module Monads
|
@@ -130,7 +131,7 @@ module Dry
|
|
130
131
|
|
131
132
|
# @api private
|
132
133
|
def halt(result)
|
133
|
-
raise Halt.new(result)
|
134
|
+
raise Halt.new(result), EMPTY_STRING, EMPTY_ARRAY
|
134
135
|
end
|
135
136
|
end
|
136
137
|
end
|
data/lib/dry/monads/do/all.rb
CHANGED
@@ -56,7 +56,7 @@ module Dry
|
|
56
56
|
#
|
57
57
|
module All
|
58
58
|
# @private
|
59
|
-
class MethodTracker < Module
|
59
|
+
class MethodTracker < ::Module
|
60
60
|
attr_reader :wrappers
|
61
61
|
|
62
62
|
def initialize(wrappers)
|
@@ -80,7 +80,7 @@ module Dry
|
|
80
80
|
|
81
81
|
def included(base)
|
82
82
|
super
|
83
|
-
|
83
|
+
All.included(base)
|
84
84
|
end
|
85
85
|
end
|
86
86
|
end
|
data/lib/dry/monads/do/mixin.rb
CHANGED
@@ -43,14 +43,13 @@ module Dry
|
|
43
43
|
# @api public
|
44
44
|
def bind(monads)
|
45
45
|
monads = Do.coerce_to_monad(Array(monads))
|
46
|
-
unwrapped = monads.map
|
46
|
+
unwrapped = monads.map do |result|
|
47
47
|
monad = result.to_monad
|
48
48
|
monad.or { Do.halt(monad) }.value!
|
49
|
-
|
49
|
+
end
|
50
50
|
monads.size == 1 ? unwrapped[0] : unwrapped
|
51
51
|
end
|
52
52
|
end
|
53
53
|
end
|
54
54
|
end
|
55
55
|
end
|
56
|
-
|
data/lib/dry/monads/maybe.rb
CHANGED
@@ -1,11 +1,10 @@
|
|
1
1
|
require 'dry/equalizer'
|
2
|
-
require 'dry/core/constants'
|
3
2
|
require 'dry/core/deprecations'
|
4
3
|
|
5
4
|
require 'dry/monads/right_biased'
|
6
5
|
require 'dry/monads/transformer'
|
7
6
|
require 'dry/monads/unit'
|
8
|
-
require 'dry/monads/
|
7
|
+
require 'dry/monads/constants'
|
9
8
|
|
10
9
|
module Dry
|
11
10
|
module Monads
|
@@ -16,7 +15,7 @@ module Dry
|
|
16
15
|
include Transformer
|
17
16
|
|
18
17
|
class << self
|
19
|
-
extend
|
18
|
+
extend Core::Deprecations[:'dry-monads']
|
20
19
|
|
21
20
|
# Wraps the given value with into a Maybe object.
|
22
21
|
#
|
@@ -139,7 +138,6 @@ module Dry
|
|
139
138
|
# @api public
|
140
139
|
class None < Maybe
|
141
140
|
include RightBiased::Left
|
142
|
-
include Core::Constants
|
143
141
|
|
144
142
|
@instance = new.freeze
|
145
143
|
singleton_class.send(:attr_reader, :instance)
|
data/lib/dry/monads/result.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
require 'dry/
|
2
|
-
|
1
|
+
require 'dry/monads/constants'
|
3
2
|
require 'dry/monads/unit'
|
4
3
|
require 'dry/monads/curry'
|
5
4
|
require 'dry/monads/errors'
|
@@ -12,8 +11,6 @@ module Dry
|
|
12
11
|
#
|
13
12
|
# @api public
|
14
13
|
module Right
|
15
|
-
include Dry::Core::Constants
|
16
|
-
|
17
14
|
# @private
|
18
15
|
def self.included(m)
|
19
16
|
super
|
@@ -194,6 +191,7 @@ module Dry
|
|
194
191
|
# in Success(2..100) then ...
|
195
192
|
# in Success(2..200 => code) then ...
|
196
193
|
# end
|
194
|
+
#
|
197
195
|
# @api private
|
198
196
|
def deconstruct
|
199
197
|
if Unit.equal?(@value)
|
@@ -205,11 +203,41 @@ module Dry
|
|
205
203
|
end
|
206
204
|
end
|
207
205
|
|
206
|
+
# Pattern matching hash values
|
207
|
+
#
|
208
|
+
# @example
|
209
|
+
# case Success(x)
|
210
|
+
# in Success(code: 200...300) then :ok
|
211
|
+
# in Success(code: 300...400) then :redirect
|
212
|
+
# in Success(code: 400...500) then :user_error
|
213
|
+
# in Success(code: 500...600) then :server_error
|
214
|
+
# end
|
215
|
+
#
|
216
|
+
# @api private
|
217
|
+
def deconstruct_keys(_)
|
218
|
+
if @value.is_a?(::Hash)
|
219
|
+
@value
|
220
|
+
else
|
221
|
+
EMPTY_HASH
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
208
225
|
private
|
209
226
|
|
210
|
-
|
211
|
-
|
212
|
-
|
227
|
+
if RUBY_VERSION >= '2.7'
|
228
|
+
# @api private
|
229
|
+
def destructure(value)
|
230
|
+
if value.is_a?(::Hash)
|
231
|
+
[EMPTY_ARRAY, value]
|
232
|
+
else
|
233
|
+
[[value], EMPTY_HASH]
|
234
|
+
end
|
235
|
+
end
|
236
|
+
else
|
237
|
+
# @api private
|
238
|
+
def destructure(*args, **kwargs)
|
239
|
+
[args, kwargs]
|
240
|
+
end
|
213
241
|
end
|
214
242
|
|
215
243
|
# @api private
|
@@ -343,6 +371,23 @@ module Dry
|
|
343
371
|
[@value]
|
344
372
|
end
|
345
373
|
end
|
374
|
+
|
375
|
+
# Pattern matching hash values
|
376
|
+
#
|
377
|
+
# @example
|
378
|
+
# case Failure(x)
|
379
|
+
# in Failure(code: 400...500) then :user_error
|
380
|
+
# in Failure(code: 500...600) then :server_error
|
381
|
+
# end
|
382
|
+
#
|
383
|
+
# @api private
|
384
|
+
def deconstruct_keys(_)
|
385
|
+
if @value.is_a?(::Hash)
|
386
|
+
@value
|
387
|
+
else
|
388
|
+
EMPTY_HASH
|
389
|
+
end
|
390
|
+
end
|
346
391
|
end
|
347
392
|
end
|
348
393
|
end
|
data/lib/dry/monads/validated.rb
CHANGED
data/lib/dry/monads/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dry-monads
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nikita Shilnikov
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-11-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dry-equalizer
|
@@ -122,11 +122,18 @@ extensions: []
|
|
122
122
|
extra_rdoc_files: []
|
123
123
|
files:
|
124
124
|
- ".codeclimate.yml"
|
125
|
+
- ".github/ISSUE_TEMPLATE/----please-don-t-ask-for-support-via-issues.md"
|
126
|
+
- ".github/ISSUE_TEMPLATE/---bug-report.md"
|
127
|
+
- ".github/ISSUE_TEMPLATE/---feature-request.md"
|
128
|
+
- ".github/workflows/ci.yml"
|
129
|
+
- ".github/workflows/docsite.yml"
|
130
|
+
- ".github/workflows/sync_configs.yml"
|
125
131
|
- ".gitignore"
|
126
132
|
- ".rspec"
|
127
|
-
- ".
|
133
|
+
- ".rubocop.yml"
|
128
134
|
- ".yardopts"
|
129
135
|
- CHANGELOG.md
|
136
|
+
- CODE_OF_CONDUCT.md
|
130
137
|
- CONTRIBUTING.md
|
131
138
|
- Gemfile
|
132
139
|
- LICENSE
|
@@ -134,10 +141,24 @@ files:
|
|
134
141
|
- Rakefile
|
135
142
|
- bin/console
|
136
143
|
- bin/setup
|
144
|
+
- docsite/source/case-equality.html.md
|
145
|
+
- docsite/source/do-notation.html.md
|
146
|
+
- docsite/source/getting-started.html.md
|
147
|
+
- docsite/source/index.html.md
|
148
|
+
- docsite/source/list.html.md
|
149
|
+
- docsite/source/maybe.html.md
|
150
|
+
- docsite/source/pattern-matching.html.md
|
151
|
+
- docsite/source/result.html.md
|
152
|
+
- docsite/source/task.html.md
|
153
|
+
- docsite/source/tracing-failures.html.md
|
154
|
+
- docsite/source/try.html.md
|
155
|
+
- docsite/source/unit.html.md
|
156
|
+
- docsite/source/validated.html.md
|
137
157
|
- dry-monads.gemspec
|
138
158
|
- lib/dry-monads.rb
|
139
159
|
- lib/dry/monads.rb
|
140
160
|
- lib/dry/monads/all.rb
|
161
|
+
- lib/dry/monads/constants.rb
|
141
162
|
- lib/dry/monads/conversion_stubs.rb
|
142
163
|
- lib/dry/monads/curry.rb
|
143
164
|
- lib/dry/monads/do.rb
|
@@ -156,7 +177,6 @@ files:
|
|
156
177
|
- lib/dry/monads/transformer.rb
|
157
178
|
- lib/dry/monads/traverse.rb
|
158
179
|
- lib/dry/monads/try.rb
|
159
|
-
- lib/dry/monads/undefined.rb
|
160
180
|
- lib/dry/monads/unit.rb
|
161
181
|
- lib/dry/monads/validated.rb
|
162
182
|
- lib/dry/monads/version.rb
|
@@ -182,7 +202,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
182
202
|
- !ruby/object:Gem::Version
|
183
203
|
version: '0'
|
184
204
|
requirements: []
|
185
|
-
rubygems_version: 3.0.
|
205
|
+
rubygems_version: 3.0.6
|
186
206
|
signing_key:
|
187
207
|
specification_version: 4
|
188
208
|
summary: Common monads for Ruby.
|
data/.travis.yml
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
language: ruby
|
2
|
-
dist: trusty
|
3
|
-
cache: bundler
|
4
|
-
bundler_args: --without benchmarks docs
|
5
|
-
script:
|
6
|
-
- bundle exec rspec spec
|
7
|
-
before_install:
|
8
|
-
- gem update --system
|
9
|
-
- gem install bundler
|
10
|
-
after_success:
|
11
|
-
- "[ -d coverage ] && bundle exec codeclimate-test-reporter"
|
12
|
-
rvm:
|
13
|
-
- 2.4.7
|
14
|
-
- 2.5.6
|
15
|
-
- 2.6.4
|
16
|
-
- ruby-head
|
17
|
-
- jruby-9.2.7.0
|
18
|
-
env:
|
19
|
-
global:
|
20
|
-
- JRUBY_OPTS='--dev -J-Xmx1024M'
|
21
|
-
- COVERAGE=true
|
22
|
-
matrix:
|
23
|
-
allow_failures:
|
24
|
-
- rvm: ruby-head
|
25
|
-
|
26
|
-
notifications:
|
27
|
-
email:
|
28
|
-
recipients:
|
29
|
-
- fg@flashgordon.ru
|
30
|
-
on_success: change
|
31
|
-
on_failure: always
|
32
|
-
on_start: false # default: false
|
33
|
-
webhooks:
|
34
|
-
urls:
|
35
|
-
- https://webhooks.gitter.im/e/19098b4253a72c9796db
|
36
|
-
on_success: change # options: [always|never|change] default: always
|
37
|
-
on_failure: always # options: [always|never|change] default: always
|
38
|
-
on_start: false # default: false
|