kind 5.2.0 → 5.6.0
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/.travis.sh +2 -0
- data/CHANGELOG.md +196 -28
- data/README.md +14 -12
- data/kind.gemspec +2 -2
- data/lib/kind/__lib__/action_steps.rb +57 -0
- data/lib/kind/__lib__/attributes.rb +1 -1
- data/lib/kind/__lib__/kind.rb +6 -26
- data/lib/kind/__lib__/of.rb +17 -0
- data/lib/kind/__lib__/strict.rb +49 -0
- data/lib/kind/action.rb +36 -1
- data/lib/kind/basic.rb +16 -6
- data/lib/kind/dig.rb +2 -2
- data/lib/kind/either/left.rb +1 -1
- data/lib/kind/function.rb +1 -3
- data/lib/kind/functional.rb +2 -2
- data/lib/kind/functional/action.rb +6 -8
- data/lib/kind/functional/steps.rb +22 -0
- data/lib/kind/immutable_attributes/reader.rb +1 -1
- data/lib/kind/maybe.rb +1 -1
- data/lib/kind/maybe/none.rb +1 -1
- data/lib/kind/maybe/some.rb +5 -5
- data/lib/kind/objects/basic_object.rb +2 -4
- data/lib/kind/objects/not_nil.rb +1 -5
- data/lib/kind/objects/object.rb +1 -1
- data/lib/kind/objects/respond_to.rb +1 -1
- data/lib/kind/objects/union_type.rb +1 -1
- data/lib/kind/presence.rb +1 -1
- data/lib/kind/result/failure.rb +4 -2
- data/lib/kind/result/monad.rb +9 -4
- data/lib/kind/result/success.rb +22 -9
- data/lib/kind/strict/disabled.rb +34 -0
- data/lib/kind/try.rb +2 -2
- data/lib/kind/validator.rb +1 -1
- data/lib/kind/version.rb +1 -1
- metadata +12 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b72fec7c07a6b3178717f30c81ecdbb6375cc1fc625c1a3fa1d39611e4dc3960
|
|
4
|
+
data.tar.gz: efec52f15083b538c99546f8d5e1c6b095c6c5c243379fc21365bae99a176e60
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fad78e10047e8fdd21e4c56ddcc5c8620b1ad6018f3fdfb7af097b84be23bb73c3c549cd519bec3af7980c4df89fbc5b9db2796510c518a4ad9d9b9165ef6e02
|
|
7
|
+
data.tar.gz: 3d0fa5b46405e4a766285c6e3fd95e3568c5bb1875e310941a3dd592cd99372893c7aab6cfe91a321fc6a843c966ab5fb7414e726e903021b16b92dfc03bac1e
|
data/.travis.sh
CHANGED
|
@@ -21,6 +21,8 @@ function run_basic_tests {
|
|
|
21
21
|
eval "KIND_BASIC=t $bundle_cmd exec rake test TEST='test/kind/{functional/*_test,functional_test}.rb'"
|
|
22
22
|
eval "KIND_BASIC=t $bundle_cmd exec rake test TEST='test/kind/either/*_test.rb'"
|
|
23
23
|
eval "KIND_BASIC=t $bundle_cmd exec rake test TEST='test/kind/result/*_test.rb'"
|
|
24
|
+
|
|
25
|
+
eval "KIND_STRICT=t $bundle_cmd exec rake test TEST='test/kind/strict_disabled_test.rb'"
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
function run_with_bundler {
|
data/CHANGELOG.md
CHANGED
|
@@ -3,73 +3,83 @@
|
|
|
3
3
|
This project follows [semver 2.0.0](http://semver.org/spec/v2.0.0.html) and the recommendations of [keepachangelog.com](http://keepachangelog.com/).
|
|
4
4
|
|
|
5
5
|
- [Unreleased](#unreleased)
|
|
6
|
-
- [5.
|
|
6
|
+
- [5.6.0 (2021-05-14)](#560-2021-05-14)
|
|
7
7
|
- [Added](#added)
|
|
8
|
+
- [5.5.0 (2021-04-05)](#550-2021-04-05)
|
|
9
|
+
- [Added](#added-1)
|
|
10
|
+
- [5.4.1 (2021-03-26)](#541-2021-03-26)
|
|
11
|
+
- [Fixed](#fixed)
|
|
12
|
+
- [5.4.0 (2021-03-25)](#540-2021-03-25)
|
|
13
|
+
- [Added](#added-2)
|
|
14
|
+
- [5.3.0 (2021-03-23)](#530-2021-03-23)
|
|
15
|
+
- [Added](#added-3)
|
|
16
|
+
- [5.2.0 (2021-03-17)](#520-2021-03-17)
|
|
17
|
+
- [Added](#added-4)
|
|
8
18
|
- [Deprecated](#deprecated)
|
|
9
19
|
- [Changes](#changes)
|
|
10
20
|
- [5.1.0 (2021-02-23)](#510-2021-02-23)
|
|
11
|
-
- [Added](#added-
|
|
21
|
+
- [Added](#added-5)
|
|
12
22
|
- [Deprecated](#deprecated-1)
|
|
13
23
|
- [5.0.0 (2021-02-22)](#500-2021-02-22)
|
|
14
24
|
- [Breaking Changes](#breaking-changes)
|
|
15
25
|
- [Removed](#removed)
|
|
16
26
|
- [4.1.0 (2021-02-22)](#410-2021-02-22)
|
|
17
|
-
- [Added](#added-
|
|
27
|
+
- [Added](#added-6)
|
|
18
28
|
- [4.0.0 (2021-02-22)](#400-2021-02-22)
|
|
19
|
-
- [Added](#added-
|
|
29
|
+
- [Added](#added-7)
|
|
20
30
|
- [Deprecated](#deprecated-2)
|
|
21
|
-
- [Fixed](#fixed)
|
|
31
|
+
- [Fixed](#fixed-1)
|
|
22
32
|
- [3.1.0 (2020-07-08)](#310-2020-07-08)
|
|
23
|
-
- [Added](#added-
|
|
33
|
+
- [Added](#added-8)
|
|
24
34
|
- [3.0.0 (2020-06-25)](#300-2020-06-25)
|
|
25
35
|
- [Breaking Changes](#breaking-changes-1)
|
|
26
|
-
- [Added](#added-
|
|
36
|
+
- [Added](#added-9)
|
|
27
37
|
- [2.3.0 (2020-06-24)](#230-2020-06-24)
|
|
28
|
-
- [Added](#added-
|
|
38
|
+
- [Added](#added-10)
|
|
29
39
|
- [2.2.0 (2020-06-23)](#220-2020-06-23)
|
|
30
|
-
- [Added](#added-
|
|
40
|
+
- [Added](#added-11)
|
|
31
41
|
- [2.1.0 (2020-05-12)](#210-2020-05-12)
|
|
32
|
-
- [Added](#added-
|
|
42
|
+
- [Added](#added-12)
|
|
33
43
|
- [Breaking Changes](#breaking-changes-2)
|
|
34
44
|
- [2.0.0 (2020-05-07)](#200-2020-05-07)
|
|
35
|
-
- [Added](#added-
|
|
45
|
+
- [Added](#added-13)
|
|
36
46
|
- [Breaking Changes](#breaking-changes-3)
|
|
37
47
|
- [Removed](#removed-1)
|
|
38
48
|
- [1.9.0 (2020-05-06)](#190-2020-05-06)
|
|
39
|
-
- [Added](#added-
|
|
49
|
+
- [Added](#added-14)
|
|
40
50
|
- [1.8.0 (2020-05-03)](#180-2020-05-03)
|
|
41
|
-
- [Added](#added-
|
|
51
|
+
- [Added](#added-15)
|
|
42
52
|
- [1.7.0 (2020-05-03)](#170-2020-05-03)
|
|
43
|
-
- [Fixed](#fixed-
|
|
53
|
+
- [Fixed](#fixed-2)
|
|
44
54
|
- [1.6.0 (2020-04-17)](#160-2020-04-17)
|
|
45
|
-
- [Added](#added-
|
|
55
|
+
- [Added](#added-16)
|
|
46
56
|
- [Changes](#changes-1)
|
|
47
57
|
- [1.5.0 (2020-04-12)](#150-2020-04-12)
|
|
48
|
-
- [Added](#added-
|
|
58
|
+
- [Added](#added-17)
|
|
49
59
|
- [1.4.0 (2020-04-12)](#140-2020-04-12)
|
|
50
|
-
- [Added](#added-
|
|
60
|
+
- [Added](#added-18)
|
|
51
61
|
- [1.3.0 (2020-04-12)](#130-2020-04-12)
|
|
52
|
-
- [Added](#added-
|
|
62
|
+
- [Added](#added-19)
|
|
53
63
|
- [1.2.0 (2020-04-12)](#120-2020-04-12)
|
|
54
|
-
- [Added](#added-
|
|
64
|
+
- [Added](#added-20)
|
|
55
65
|
- [1.1.0 (2020-04-09)](#110-2020-04-09)
|
|
56
|
-
- [Added](#added-
|
|
57
|
-
- [Fixed](#fixed-
|
|
66
|
+
- [Added](#added-21)
|
|
67
|
+
- [Fixed](#fixed-3)
|
|
58
68
|
- [1.0.0 (2020-03-16)](#100-2020-03-16)
|
|
59
|
-
- [Added](#added-
|
|
69
|
+
- [Added](#added-22)
|
|
60
70
|
- [0.6.0 (2020-01-06)](#060-2020-01-06)
|
|
61
|
-
- [Added](#added-
|
|
71
|
+
- [Added](#added-23)
|
|
62
72
|
- [0.5.0 (2020-01-04)](#050-2020-01-04)
|
|
63
|
-
- [Added](#added-
|
|
73
|
+
- [Added](#added-24)
|
|
64
74
|
- [0.4.0 (2020-01-03)](#040-2020-01-03)
|
|
65
|
-
- [Added](#added-
|
|
75
|
+
- [Added](#added-25)
|
|
66
76
|
- [0.3.0 (2020-01-03)](#030-2020-01-03)
|
|
67
|
-
- [Added](#added-
|
|
77
|
+
- [Added](#added-26)
|
|
68
78
|
- [Breaking Changes](#breaking-changes-4)
|
|
69
79
|
- [0.2.0 (2020-01-02)](#020-2020-01-02)
|
|
70
|
-
- [Added](#added-
|
|
80
|
+
- [Added](#added-27)
|
|
71
81
|
- [0.1.0 (2019-12-26)](#010-2019-12-26)
|
|
72
|
-
- [Added](#added-
|
|
82
|
+
- [Added](#added-28)
|
|
73
83
|
|
|
74
84
|
## Unreleased
|
|
75
85
|
|
|
@@ -81,6 +91,162 @@ This project follows [semver 2.0.0](http://semver.org/spec/v2.0.0.html) and the
|
|
|
81
91
|
### Fixed
|
|
82
92
|
-->
|
|
83
93
|
|
|
94
|
+
5.6.0 (2021-05-14)
|
|
95
|
+
------------------
|
|
96
|
+
|
|
97
|
+
### Added
|
|
98
|
+
|
|
99
|
+
* [#57](https://github.com/serradura/kind/pull/57) - Allow the usage of `nil` to define union types.
|
|
100
|
+
```ruby
|
|
101
|
+
(Kind::String | nil) === '' # true
|
|
102
|
+
(Kind::String | nil) === nil # true
|
|
103
|
+
|
|
104
|
+
(Kind::String | nil) === {} # false
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
[⬆️ Back to Top](#changelog-)
|
|
108
|
+
|
|
109
|
+
5.5.0 (2021-04-05)
|
|
110
|
+
------------------
|
|
111
|
+
|
|
112
|
+
### Added
|
|
113
|
+
|
|
114
|
+
* [#56](https://github.com/serradura/kind/pull/56) - Add `Kind.or_nil()`.
|
|
115
|
+
```ruby
|
|
116
|
+
Kind.or_nil(String, 1) # nil
|
|
117
|
+
|
|
118
|
+
Kind.or_nil(String, '') # ""
|
|
119
|
+
|
|
120
|
+
# --
|
|
121
|
+
|
|
122
|
+
filled_string = ->(value) { value.is_a?(String) && !value.empty? }
|
|
123
|
+
|
|
124
|
+
Kind.or_nil(filled_string, 1) # nil
|
|
125
|
+
Kind.or_nil(filled_string, '') # nil
|
|
126
|
+
|
|
127
|
+
Kind.or_nil(filled_string, '1') # "1"
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
[⬆️ Back to Top](#changelog-)
|
|
131
|
+
|
|
132
|
+
5.4.1 (2021-03-26)
|
|
133
|
+
------------------
|
|
134
|
+
|
|
135
|
+
### Fixed
|
|
136
|
+
|
|
137
|
+
* [#55](https://github.com/serradura/kind/pull/55) - Fix `Kind::Either::Left#value_or` and `Kind::Result::Failure#value_or` by allowing them to receive the value of the monad in a call using a block.
|
|
138
|
+
|
|
139
|
+
[⬆️ Back to Top](#changelog-)
|
|
140
|
+
|
|
141
|
+
5.4.0 (2021-03-25)
|
|
142
|
+
------------------
|
|
143
|
+
|
|
144
|
+
### Added
|
|
145
|
+
|
|
146
|
+
* [#54](https://github.com/serradura/kind/pull/54) - Add `Kind::Functional::Steps` to allow the usage of `Step`, `Map`, `Try`, `Tee`, `Check`, `Success` and `Failure` in any kind of object.
|
|
147
|
+
```ruby
|
|
148
|
+
# Usage in classes' instances
|
|
149
|
+
|
|
150
|
+
class BaseJob
|
|
151
|
+
def self.perform_now(input); new.perform(input); end
|
|
152
|
+
|
|
153
|
+
def perform(input); raise NotImplementedError; end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
class CreateUserJob < BaseJob
|
|
157
|
+
include Kind::Functional::Steps
|
|
158
|
+
|
|
159
|
+
def perform(input)
|
|
160
|
+
validate(input) \
|
|
161
|
+
>> Step(:create) \
|
|
162
|
+
>> Step(:welcome_email)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
private
|
|
166
|
+
|
|
167
|
+
def validate(input)
|
|
168
|
+
# Success() or Failure()
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def create(input)
|
|
172
|
+
# Success() or Failure()
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def welcome_email(email)
|
|
176
|
+
# Success() or Failure()
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# Usage in modules (singleton methods)
|
|
181
|
+
|
|
182
|
+
module CreateUser
|
|
183
|
+
extend self, Kind::Functional::Steps
|
|
184
|
+
|
|
185
|
+
def perform(input)
|
|
186
|
+
Step!(:validate, input) \
|
|
187
|
+
>> Step(:create) \
|
|
188
|
+
>> Step(:welcome_email)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
private
|
|
192
|
+
|
|
193
|
+
def validate(input)
|
|
194
|
+
# Success() or Failure()
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def create(input)
|
|
198
|
+
# Success() or Failure()
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def welcome_email(email)
|
|
202
|
+
# Success() or Failure()
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
[⬆️ Back to Top](#changelog-)
|
|
208
|
+
|
|
209
|
+
5.3.0 (2021-03-23)
|
|
210
|
+
------------------
|
|
211
|
+
|
|
212
|
+
### Added
|
|
213
|
+
|
|
214
|
+
* [#53](https://github.com/serradura/kind/pull/53) - Allow `Kind::Result#map` and `Kind::Result#map!` receive a callable as an argument.
|
|
215
|
+
|
|
216
|
+
* [#53](https://github.com/serradura/kind/pull/53) - Add `|` and `>>` as an alias of `Kind::Result#map!`.
|
|
217
|
+
|
|
218
|
+
* [#53](https://github.com/serradura/kind/pull/53) - Add step adapters for `Kind::Action` and `Kind::Functional::Action`. This is the list of methods: `Step`, `Map`, `Try`, `Tee`, `Check`.
|
|
219
|
+
```ruby
|
|
220
|
+
module CreateUser
|
|
221
|
+
extend Kind::Functional::Action
|
|
222
|
+
|
|
223
|
+
def call!(input)
|
|
224
|
+
Step!(:validate, input) \
|
|
225
|
+
| Step(:create)
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
private
|
|
229
|
+
|
|
230
|
+
def validate(input)
|
|
231
|
+
# returns Success(valid_data) or Failure(validation)
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def create(input)
|
|
235
|
+
# returns Success(user)
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
* [#53](https://github.com/serradura/kind/pull/53) - Add `kind/strict/disabled` to turn off all of the strict validations and optimize the runtime. Use case: As strict validation is useful in development, this mechanism could be used to optimize the runtime in production. List of methods that will be disabled:
|
|
241
|
+
* `Kind.of()`
|
|
242
|
+
* `Kind.of_class()`
|
|
243
|
+
* `Kind.of_module()`
|
|
244
|
+
* `Kind.of_module_or_class()`
|
|
245
|
+
* `Kind::<Type>[1]`
|
|
246
|
+
* `Kind::NotNil[1]`
|
|
247
|
+
|
|
248
|
+
[⬆️ Back to Top](#changelog-)
|
|
249
|
+
|
|
84
250
|
5.2.0 (2021-03-17)
|
|
85
251
|
------------------
|
|
86
252
|
|
|
@@ -254,6 +420,8 @@ This project follows [semver 2.0.0](http://semver.org/spec/v2.0.0.html) and the
|
|
|
254
420
|
p number # 0
|
|
255
421
|
```
|
|
256
422
|
|
|
423
|
+
[⬆️ Back to Top](#changelog-)
|
|
424
|
+
|
|
257
425
|
* [#46](https://github.com/serradura/kind/pull/46) - Add `Kind::Either` (either monad). This is basically the same as the `Maybe` monad, but with `Some` called `Right` and `None` called `Left`. But this time, `Left` is also allowed to have an underlying value. This module isn't loaded by default, so you will need to require it.
|
|
258
426
|
```ruby
|
|
259
427
|
require 'kind/either'
|
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<p align="center">
|
|
2
2
|
<h1 align="center">🤷 kind</h1>
|
|
3
|
-
<p align="center"><i>A
|
|
3
|
+
<p align="center"><i>A development toolkit for Ruby with several small/cohesive abstractions to empower your development workflow - It's totally free of dependencies.</i></p>
|
|
4
4
|
</p>
|
|
5
5
|
|
|
6
6
|
<p align="center">
|
|
@@ -31,16 +31,18 @@
|
|
|
31
31
|
|
|
32
32
|
**Motivation:**
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
This project was born to help me with a simple task, create a light and fast type checker (at runtime) for Ruby. The initial idea was to have something to raise an exception when a method or function (procs) received a wrong input.
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
But through time it was natural the addition of more features to improve the development workflow, like monads ([`Kind::Maybe`](#kindmaybe), `Kind::Either` / `Kind::Result`), enums (`Kind::Enum`), immutable objects (`Kind::ImmutableAttributes`), [type validation via ActiveModel::Validation](#kindvalidator-activemodelvalidations), and several abstractions to help the implementation of business logic (`Kind::Functional::Steps`, `Kind::Functional::Action`, `Kind::Action`).
|
|
37
|
+
|
|
38
|
+
So, I invite you to check out these features to see how they could be useful for you. Enjoy!
|
|
37
39
|
|
|
38
40
|
## Documentation <!-- omit in toc -->
|
|
39
41
|
|
|
40
42
|
Version | Documentation
|
|
41
43
|
---------- | -------------
|
|
42
44
|
unreleased | https://github.com/serradura/kind/blob/main/README.md
|
|
43
|
-
5.
|
|
45
|
+
5.6.0 | https://github.com/serradura/kind/blob/v5.x/README.md
|
|
44
46
|
4.1.0 | https://github.com/serradura/kind/blob/v4.x/README.md
|
|
45
47
|
3.1.0 | https://github.com/serradura/kind/blob/v3.x/README.md
|
|
46
48
|
2.3.0 | https://github.com/serradura/kind/blob/v2.x/README.md
|
|
@@ -120,14 +122,14 @@ unreleased | https://github.com/serradura/kind/blob/main/README.md
|
|
|
120
122
|
|
|
121
123
|
## Compatibility
|
|
122
124
|
|
|
123
|
-
| kind | branch | ruby
|
|
124
|
-
| -------------- | ------- |
|
|
125
|
-
| unreleased | main | >= 2.1.0 | >= 3.2,
|
|
126
|
-
| 5.
|
|
127
|
-
| 4.1.0 | v4.x | >= 2.2.0 | >= 3.2,
|
|
128
|
-
| 3.1.0 | v3.x | >= 2.2.0 | >= 3.2,
|
|
129
|
-
| 2.3.0 | v2.x | >= 2.2.0 | >= 3.2, <= 6.0 |
|
|
130
|
-
| 1.9.0 | v1.x | >= 2.2.0 | >= 3.2, <= 6.0 |
|
|
125
|
+
| kind | branch | ruby | activemodel |
|
|
126
|
+
| -------------- | ------- | ------------------ | -------------- |
|
|
127
|
+
| unreleased | main | >= 2.1.0, <= 3.0.0 | >= 3.2, < 7.0 |
|
|
128
|
+
| 5.6.0 | v5.x | >= 2.1.0, <= 3.0.0 | >= 3.2, < 7.0 |
|
|
129
|
+
| 4.1.0 | v4.x | >= 2.2.0, <= 3.0.0 | >= 3.2, < 7.0 |
|
|
130
|
+
| 3.1.0 | v3.x | >= 2.2.0, <= 2.7 | >= 3.2, < 7.0 |
|
|
131
|
+
| 2.3.0 | v2.x | >= 2.2.0, <= 2.7 | >= 3.2, <= 6.0 |
|
|
132
|
+
| 1.9.0 | v1.x | >= 2.2.0, <= 2.7 | >= 3.2, <= 6.0 |
|
|
131
133
|
|
|
132
134
|
> Note: The activemodel is an optional dependency, it is related with the [Kind::Validator](#kindvalidator-activemodelvalidations).
|
|
133
135
|
|
data/kind.gemspec
CHANGED
|
@@ -6,8 +6,8 @@ Gem::Specification.new do |spec|
|
|
|
6
6
|
spec.authors = ['Rodrigo Serradura']
|
|
7
7
|
spec.email = ['rodrigo.serradura@gmail.com']
|
|
8
8
|
|
|
9
|
-
spec.summary = %q{A
|
|
10
|
-
spec.description = %q{A
|
|
9
|
+
spec.summary = %q{A development toolkit for Ruby with several small/cohesive abstractions to empower your development workflow.}
|
|
10
|
+
spec.description = %q{A development toolkit for Ruby with several small/cohesive abstractions (monads, enums, business logic, data validation...) to empower your development workflow - It's totally free of dependencies.}
|
|
11
11
|
spec.homepage = 'https://github.com/serradura/kind'
|
|
12
12
|
spec.license = 'MIT'
|
|
13
13
|
spec.required_ruby_version = Gem::Requirement.new('>= 2.1.0')
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Kind
|
|
4
|
+
module ACTION_STEPS
|
|
5
|
+
private
|
|
6
|
+
|
|
7
|
+
def Check(mthod); ->(value) { __Check(thod, value) }; end
|
|
8
|
+
def Step(mthod); ->(value) { __Step(mthod, value) }; end
|
|
9
|
+
def Map(mthod); ->(value) { __Map(mthod, value) }; end
|
|
10
|
+
def Tee(mthod); ->(value) { __Tee(mthod, value) }; end
|
|
11
|
+
def Try(mthod, opt = Empty::HASH)
|
|
12
|
+
->(value) { __Try(mthod, value, opt) }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def Check!(mthod, value); __Check(mthod, value); end
|
|
16
|
+
def Step!(mthod, value); __Step(mthod, value); end
|
|
17
|
+
def Map!(mthod, value); __Map(mthod, value); end
|
|
18
|
+
def Tee!(mthod, value); __Tee(mthod, value); end
|
|
19
|
+
def Try!(mthod, value, opt = Empty::HASH); __Try(mthod, value, opt); end
|
|
20
|
+
|
|
21
|
+
def __Check(mthod, value) # :nodoc:
|
|
22
|
+
__resolve_step(mthod, value) ? Success(mthod, value) : Failure(mthod, value)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def __Step(mthod, value) # :nodoc:
|
|
26
|
+
__resolve_step(mthod, value)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def __Map(mthod, value) # :nodoc:
|
|
30
|
+
Success(mthod, __resolve_step(mthod, value))
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def __Tee(mthod, value) # :nodoc:
|
|
34
|
+
__resolve_step(mthod, value)
|
|
35
|
+
|
|
36
|
+
Success(mthod, value)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def __Try(mthod, value, opt = Empty::HASH) # :nodoc:
|
|
40
|
+
begin
|
|
41
|
+
Success(mthod, __resolve_step(mthod, value))
|
|
42
|
+
rescue opt.fetch(:catch, StandardError) => e
|
|
43
|
+
Failure(mthod, __map_step_exception(e))
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def __resolve_step(mthod, value) # :nodoc:
|
|
48
|
+
send(mthod, value)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def __map_step_exception(value) # :nodoc:
|
|
52
|
+
value
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
private_constant :ACTION_STEPS
|
|
57
|
+
end
|
data/lib/kind/__lib__/kind.rb
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'kind/__lib__/strict'
|
|
4
|
+
|
|
3
5
|
module Kind
|
|
4
6
|
module KIND
|
|
5
7
|
extend self
|
|
6
8
|
|
|
7
|
-
def
|
|
9
|
+
def nil_or_undefined?(value) # :nodoc:
|
|
8
10
|
value.nil? || Undefined == value
|
|
9
11
|
end
|
|
10
12
|
|
|
@@ -14,28 +16,6 @@ module Kind
|
|
|
14
16
|
values.empty? ? of_kind : values.all?(&of_kind)
|
|
15
17
|
end
|
|
16
18
|
|
|
17
|
-
def of!(kind, value, kind_name = nil) # :nodoc:
|
|
18
|
-
return value if kind === value
|
|
19
|
-
|
|
20
|
-
error!(kind_name || kind.name, value)
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def error!(kind_name, value, label = nil) # :nodoc:
|
|
24
|
-
raise Error.new(kind_name, value, label: label)
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def of_class?(value) # :nodoc:
|
|
28
|
-
value.kind_of?(::Class)
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def of_module?(value) # :nodoc:
|
|
32
|
-
::Module == value || (value.kind_of?(::Module) && !of_class?(value))
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def of_module_or_class!(value) # :nodoc:
|
|
36
|
-
of!(::Module, value, 'Module/Class')
|
|
37
|
-
end
|
|
38
|
-
|
|
39
19
|
def respond_to!(method_name, value) # :nodoc:
|
|
40
20
|
return value if value.respond_to?(method_name)
|
|
41
21
|
|
|
@@ -51,15 +31,15 @@ module Kind
|
|
|
51
31
|
end
|
|
52
32
|
|
|
53
33
|
def is?(expected, value) # :nodoc:
|
|
54
|
-
is(
|
|
34
|
+
is(STRICT.module_or_class(expected), value)
|
|
55
35
|
end
|
|
56
36
|
|
|
57
37
|
private
|
|
58
38
|
|
|
59
39
|
def is(expected_kind, value) # :nodoc:
|
|
60
|
-
kind =
|
|
40
|
+
kind = STRICT.module_or_class(value)
|
|
61
41
|
|
|
62
|
-
if
|
|
42
|
+
if OF.class?(kind)
|
|
63
43
|
kind <= expected_kind || expected_kind == ::Class
|
|
64
44
|
else
|
|
65
45
|
kind == expected_kind || kind.kind_of?(expected_kind)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Kind
|
|
4
|
+
module OF
|
|
5
|
+
extend self
|
|
6
|
+
|
|
7
|
+
def class?(value) # :nodoc:
|
|
8
|
+
value.kind_of?(::Class)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def module?(value) # :nodoc:
|
|
12
|
+
::Module == value || (value.kind_of?(::Module) && !class?(value))
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private_constant :OF
|
|
17
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'kind/__lib__/of'
|
|
4
|
+
|
|
5
|
+
module Kind
|
|
6
|
+
module STRICT
|
|
7
|
+
extend self
|
|
8
|
+
|
|
9
|
+
def error(kind_name, value, label = nil) # :nodoc:
|
|
10
|
+
raise Error.new(kind_name, value, label: label)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def object_is_a(kind, value, label = nil) # :nodoc:
|
|
14
|
+
return value if kind === value
|
|
15
|
+
|
|
16
|
+
error(kind.name, value, label)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def kind_of(kind, value, kind_name = nil) # :nodoc:
|
|
20
|
+
return value if kind === value
|
|
21
|
+
|
|
22
|
+
error(kind_name || kind.name, value)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def module_or_class(value) # :nodoc:
|
|
26
|
+
kind_of(::Module, value, 'Module/Class')
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def class!(value) # :nodoc:
|
|
30
|
+
kind_of(::Class, value)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def module!(value) # :nodoc:
|
|
34
|
+
return value if OF.module?(value)
|
|
35
|
+
|
|
36
|
+
error('Module', value)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def not_nil(value, label) # :nodoc:
|
|
40
|
+
return value unless value.nil?
|
|
41
|
+
|
|
42
|
+
label_text = label ? "#{label}: " : ''
|
|
43
|
+
|
|
44
|
+
raise Error.new("#{label_text}expected to not be nil")
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
private_constant :STRICT
|
|
49
|
+
end
|
data/lib/kind/action.rb
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'kind/basic'
|
|
4
|
+
require 'kind/empty'
|
|
4
5
|
require 'kind/result'
|
|
5
6
|
require 'kind/immutable_attributes'
|
|
7
|
+
require 'kind/__lib__/action_steps'
|
|
6
8
|
|
|
7
9
|
module Kind
|
|
8
10
|
module Action
|
|
@@ -20,6 +22,8 @@ module Kind
|
|
|
20
22
|
'end'
|
|
21
23
|
].join("\n").freeze
|
|
22
24
|
|
|
25
|
+
private_constant :CALL_TMPL
|
|
26
|
+
|
|
23
27
|
module ClassMethods
|
|
24
28
|
include ImmutableAttributes::ClassMethods
|
|
25
29
|
|
|
@@ -71,21 +75,52 @@ module Kind
|
|
|
71
75
|
end
|
|
72
76
|
end
|
|
73
77
|
|
|
78
|
+
module StepAdapters
|
|
79
|
+
private
|
|
80
|
+
|
|
81
|
+
def Check!(mthod); __Check(mthod, Empty::HASH); end
|
|
82
|
+
def Step!(mthod); __Step(mthod, Empty::HASH); end
|
|
83
|
+
def Map!(mthod); __Map(mthod, Empty::HASH); end
|
|
84
|
+
def Tee!(_mthod); raise NotImplementedError; end
|
|
85
|
+
def Try!(mthod, opt = Empty::HASH); __Try(mthod, Empty::HASH, opt); end
|
|
86
|
+
|
|
87
|
+
def __resolve_step(method_name, value)
|
|
88
|
+
m = method(method_name)
|
|
89
|
+
m.arity > 0 ? m.call(value) : m.call
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def __map_step_exception(value)
|
|
93
|
+
{ exception: value }
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
private_constant :StepAdapters
|
|
98
|
+
|
|
74
99
|
def self.included(base)
|
|
75
|
-
|
|
100
|
+
Kind.of_class(base).extend(ClassMethods)
|
|
76
101
|
|
|
102
|
+
base.send(:include, ACTION_STEPS)
|
|
103
|
+
base.send(:include, StepAdapters)
|
|
77
104
|
base.send(:include, ImmutableAttributes::Reader)
|
|
78
105
|
end
|
|
79
106
|
|
|
80
107
|
include ImmutableAttributes::Initializer
|
|
81
108
|
|
|
109
|
+
def inspect
|
|
110
|
+
'#<%s attributes=%p nil_attributes=%p>' % [self.class.name, attributes, nil_attributes]
|
|
111
|
+
end
|
|
112
|
+
|
|
82
113
|
private
|
|
83
114
|
|
|
84
115
|
def Failure(arg1 = UNDEFINED, arg2 = UNDEFINED)
|
|
116
|
+
arg1 = Empty::HASH if UNDEFINED == arg1 && UNDEFINED == arg2
|
|
117
|
+
|
|
85
118
|
Result::Failure[arg1, arg2, value_must_be_a: ::Hash]
|
|
86
119
|
end
|
|
87
120
|
|
|
88
121
|
def Success(arg1 = UNDEFINED, arg2 = UNDEFINED)
|
|
122
|
+
arg1 = Empty::HASH if UNDEFINED == arg1 && UNDEFINED == arg2
|
|
123
|
+
|
|
89
124
|
Result::Success[arg1, arg2, value_must_be_a: ::Hash]
|
|
90
125
|
end
|
|
91
126
|
end
|
data/lib/kind/basic.rb
CHANGED
|
@@ -35,11 +35,11 @@ module Kind
|
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
def of_class?(value)
|
|
38
|
-
|
|
38
|
+
OF.class?(value)
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
def of_module?(value)
|
|
42
|
-
|
|
42
|
+
OF.module?(value)
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
def respond_to?(value, *method_names)
|
|
@@ -49,15 +49,21 @@ module Kind
|
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
def of(kind, value, label: nil)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
KIND.error!(kind.name, value, label)
|
|
52
|
+
STRICT.object_is_a(kind, value, label)
|
|
55
53
|
end
|
|
56
54
|
|
|
57
55
|
alias_method :of!, :of
|
|
58
56
|
|
|
57
|
+
def of_class(value)
|
|
58
|
+
STRICT.class!(value)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def of_module(value)
|
|
62
|
+
STRICT.module!(value)
|
|
63
|
+
end
|
|
64
|
+
|
|
59
65
|
def of_module_or_class(value)
|
|
60
|
-
|
|
66
|
+
STRICT.module_or_class(value)
|
|
61
67
|
end
|
|
62
68
|
|
|
63
69
|
def respond_to(value, *method_names)
|
|
@@ -70,4 +76,8 @@ module Kind
|
|
|
70
76
|
def value(kind, value, default:)
|
|
71
77
|
KIND.value(kind, value, of(kind, default))
|
|
72
78
|
end
|
|
79
|
+
|
|
80
|
+
def or_nil(kind, value)
|
|
81
|
+
return value if kind === value
|
|
82
|
+
end
|
|
73
83
|
end
|
data/lib/kind/dig.rb
CHANGED
|
@@ -12,7 +12,7 @@ module Kind
|
|
|
12
12
|
keys.reduce(data) do |memo, key|
|
|
13
13
|
value = get(memo, key)
|
|
14
14
|
|
|
15
|
-
break if KIND.
|
|
15
|
+
break if KIND.nil_or_undefined?(value)
|
|
16
16
|
|
|
17
17
|
value
|
|
18
18
|
end
|
|
@@ -25,7 +25,7 @@ module Kind
|
|
|
25
25
|
|
|
26
26
|
return result unless block_given?
|
|
27
27
|
|
|
28
|
-
yield(result) unless KIND.
|
|
28
|
+
yield(result) unless KIND.nil_or_undefined?(result)
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
def presence(*args, &block)
|
data/lib/kind/either/left.rb
CHANGED
data/lib/kind/function.rb
CHANGED
data/lib/kind/functional.rb
CHANGED
|
@@ -11,7 +11,7 @@ module Kind
|
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def self.included(base)
|
|
14
|
-
|
|
14
|
+
Kind.of_class(base).send(:extend, ClassMethods)
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
module Behavior
|
|
@@ -22,7 +22,7 @@ module Kind
|
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
def initialize(arg = Empty::HASH)
|
|
25
|
-
hash =
|
|
25
|
+
hash = STRICT.kind_of(::Hash, arg)
|
|
26
26
|
|
|
27
27
|
self.class.__dependencies__.each do |name, (kind, default, _visibility)|
|
|
28
28
|
value_to_assign = ATTRIBUTES.value_to_assign!(kind, default, hash, name)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'kind/result'
|
|
4
3
|
require 'kind/functional'
|
|
4
|
+
require 'kind/functional/steps'
|
|
5
5
|
|
|
6
6
|
module Kind
|
|
7
7
|
module Functional::Action
|
|
@@ -56,10 +56,10 @@ module Kind
|
|
|
56
56
|
"#{CALL_TMPL % [call_tmpl_args, call_tmpl_args]}"
|
|
57
57
|
)
|
|
58
58
|
|
|
59
|
-
if
|
|
60
|
-
self.send(:extend,
|
|
59
|
+
if Kind.of_module?(self)
|
|
60
|
+
self.send(:extend, Functional::Steps)
|
|
61
61
|
else
|
|
62
|
-
self.send(:include,
|
|
62
|
+
self.send(:include, Functional::Steps)
|
|
63
63
|
self.send(:include, Functional::Behavior)
|
|
64
64
|
|
|
65
65
|
__dependencies__.freeze
|
|
@@ -72,15 +72,13 @@ module Kind
|
|
|
72
72
|
end
|
|
73
73
|
|
|
74
74
|
def self.included(base)
|
|
75
|
-
|
|
75
|
+
Kind.of_class(base).send(:extend, Functional::DependencyInjection)
|
|
76
76
|
|
|
77
77
|
base.send(:extend, Macros)
|
|
78
78
|
end
|
|
79
79
|
|
|
80
80
|
def self.extended(base)
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
base.send(:extend, base)
|
|
81
|
+
base.send(:extend, Kind.of_module(base))
|
|
84
82
|
base.send(:extend, Macros)
|
|
85
83
|
end
|
|
86
84
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'kind/basic'
|
|
4
|
+
require 'kind/empty'
|
|
5
|
+
require 'kind/result'
|
|
6
|
+
require 'kind/__lib__/action_steps'
|
|
7
|
+
|
|
8
|
+
module Kind
|
|
9
|
+
module Functional
|
|
10
|
+
module Steps
|
|
11
|
+
def self.extended(base)
|
|
12
|
+
base.extend(Result::Methods)
|
|
13
|
+
base.extend(ACTION_STEPS)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.included(base)
|
|
17
|
+
base.send(:include, Result::Methods)
|
|
18
|
+
base.send(:include, ACTION_STEPS)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
data/lib/kind/maybe.rb
CHANGED
data/lib/kind/maybe/none.rb
CHANGED
data/lib/kind/maybe/some.rb
CHANGED
|
@@ -6,12 +6,12 @@ require 'kind/presence'
|
|
|
6
6
|
module Kind
|
|
7
7
|
module Maybe
|
|
8
8
|
class Some < Monad
|
|
9
|
-
KindSymbol = ->(value) {
|
|
9
|
+
KindSymbol = ->(value) { STRICT.kind_of(::Symbol, value) }
|
|
10
10
|
|
|
11
11
|
VALUE_CANT_BE_NONE = "value can't be nil or Kind::Undefined".freeze
|
|
12
12
|
|
|
13
13
|
def self.[](value)
|
|
14
|
-
return new(value) if !KIND.
|
|
14
|
+
return new(value) if !KIND.nil_or_undefined?(value)
|
|
15
15
|
|
|
16
16
|
raise ArgumentError, VALUE_CANT_BE_NONE
|
|
17
17
|
end
|
|
@@ -57,7 +57,7 @@ module Kind
|
|
|
57
57
|
fn.call(@value)
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
-
!result || KIND.
|
|
60
|
+
!result || KIND.nil_or_undefined?(result) ? NONE_INSTANCE : self
|
|
61
61
|
end
|
|
62
62
|
|
|
63
63
|
alias_method :accept, :check
|
|
@@ -73,7 +73,7 @@ module Kind
|
|
|
73
73
|
fn.call(@value)
|
|
74
74
|
end
|
|
75
75
|
|
|
76
|
-
result || KIND.
|
|
76
|
+
result || KIND.nil_or_undefined?(result) ? NONE_INSTANCE : self
|
|
77
77
|
end
|
|
78
78
|
|
|
79
79
|
def try!(method_name = UNDEFINED, *args, &block)
|
|
@@ -120,7 +120,7 @@ module Kind
|
|
|
120
120
|
|
|
121
121
|
def resolve(result)
|
|
122
122
|
return result if Maybe::None === result
|
|
123
|
-
return NONE_INSTANCE if KIND.
|
|
123
|
+
return NONE_INSTANCE if KIND.nil_or_undefined?(result)
|
|
124
124
|
return None.new(result) if ::Exception === result
|
|
125
125
|
|
|
126
126
|
Some.new(result)
|
|
@@ -3,9 +3,7 @@
|
|
|
3
3
|
module Kind
|
|
4
4
|
module BasicObject
|
|
5
5
|
def [](value, label: nil)
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
KIND.error!(name, value, label)
|
|
6
|
+
STRICT.object_is_a(self, value, label)
|
|
9
7
|
end
|
|
10
8
|
|
|
11
9
|
def or_nil(value)
|
|
@@ -33,7 +31,7 @@ module Kind
|
|
|
33
31
|
end
|
|
34
32
|
|
|
35
33
|
def or_null(value) # :nodoc:
|
|
36
|
-
KIND.
|
|
34
|
+
KIND.nil_or_undefined?(value) ? value : self[value]
|
|
37
35
|
end
|
|
38
36
|
|
|
39
37
|
private
|
data/lib/kind/objects/not_nil.rb
CHANGED
data/lib/kind/objects/object.rb
CHANGED
data/lib/kind/presence.rb
CHANGED
data/lib/kind/result/failure.rb
CHANGED
|
@@ -11,13 +11,15 @@ module Kind
|
|
|
11
11
|
def value_or(default = UNDEFINED, &block)
|
|
12
12
|
Error.invalid_default_arg! if UNDEFINED == default && !block
|
|
13
13
|
|
|
14
|
-
UNDEFINED != default ? default : block.call
|
|
14
|
+
UNDEFINED != default ? default : block.call(value)
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
def map(&
|
|
17
|
+
def map(_ = UNDEFINED, &_fn)
|
|
18
18
|
self
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
+
alias_method :|, :map
|
|
22
|
+
alias_method :>>, :map
|
|
21
23
|
alias_method :map!, :map
|
|
22
24
|
alias_method :then, :map
|
|
23
25
|
alias_method :then!, :map
|
data/lib/kind/result/monad.rb
CHANGED
|
@@ -4,18 +4,21 @@ module Kind
|
|
|
4
4
|
class Result::Monad
|
|
5
5
|
include Result::Abstract
|
|
6
6
|
|
|
7
|
+
require 'kind/empty'
|
|
7
8
|
require 'kind/result/monad/wrapper'
|
|
8
9
|
|
|
9
10
|
attr_reader :type, :value
|
|
10
11
|
|
|
11
|
-
def self.[](arg1 = UNDEFINED, arg2 = UNDEFINED,
|
|
12
|
-
|
|
12
|
+
def self.[](arg1 = UNDEFINED, arg2 = UNDEFINED, opt = Empty::HASH) # :nodoc:
|
|
13
|
+
value_must_be_a = opt[:value_must_be_a]
|
|
14
|
+
|
|
15
|
+
type = UNDEFINED == arg2 ? self::DEFAULT_TYPE : STRICT.kind_of(::Symbol, arg1)
|
|
13
16
|
|
|
14
17
|
Error.wrong_number_of_args!(given: 0, expected: '1 or 2') if UNDEFINED == arg1
|
|
15
18
|
|
|
16
19
|
value = UNDEFINED == arg2 ? arg1 : arg2
|
|
17
20
|
|
|
18
|
-
new(type, (value_must_be_a ?
|
|
21
|
+
new(type, (value_must_be_a ? STRICT.kind_of(value_must_be_a, value) : value))
|
|
19
22
|
end
|
|
20
23
|
|
|
21
24
|
private_class_method :new
|
|
@@ -29,10 +32,12 @@ module Kind
|
|
|
29
32
|
raise NotImplementedError
|
|
30
33
|
end
|
|
31
34
|
|
|
32
|
-
def map(&
|
|
35
|
+
def map(_ = UNDEFINED, &_fn)
|
|
33
36
|
raise NotImplementedError
|
|
34
37
|
end
|
|
35
38
|
|
|
39
|
+
alias_method :|, :map
|
|
40
|
+
alias_method :>>, :map
|
|
36
41
|
alias_method :map!, :map
|
|
37
42
|
alias_method :then, :map
|
|
38
43
|
alias_method :then!, :map
|
data/lib/kind/result/success.rb
CHANGED
|
@@ -12,29 +12,42 @@ module Kind
|
|
|
12
12
|
@value
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
def map(&fn)
|
|
16
|
-
|
|
15
|
+
def map(callable = UNDEFINED, &fn)
|
|
16
|
+
_resolve_map(callable, fn)
|
|
17
17
|
rescue Kind::Monad::Error => e
|
|
18
18
|
raise e
|
|
19
19
|
rescue StandardError => e
|
|
20
20
|
Result::Failure[:exception, e]
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return monad if Result::Monad === monad
|
|
23
|
+
alias_method :then, :map
|
|
24
|
+
alias_method :and_then, :map
|
|
27
25
|
|
|
28
|
-
|
|
26
|
+
def map!(callable = UNDEFINED, &fn)
|
|
27
|
+
_resolve_map(callable, fn)
|
|
29
28
|
end
|
|
30
29
|
|
|
31
|
-
alias_method
|
|
30
|
+
alias_method :|, :map!
|
|
31
|
+
alias_method :>>, :map!
|
|
32
32
|
alias_method :then!, :map!
|
|
33
|
-
alias_method :and_then, :map
|
|
34
33
|
alias_method :and_then!, :map!
|
|
35
34
|
|
|
36
35
|
def inspect
|
|
37
36
|
'#<%s type=%p value=%p>' % ['Kind::Success', type, value]
|
|
38
37
|
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
def _resolve_map(callable, fn)
|
|
42
|
+
callable.respond_to?(:call) ? _map(callable) : _map(fn)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def _map(fn)
|
|
46
|
+
monad = fn.call(@value)
|
|
47
|
+
|
|
48
|
+
return monad if Result::Monad === monad
|
|
49
|
+
|
|
50
|
+
raise Kind::Monad::Error.new('Kind::Success | Kind::Failure', monad)
|
|
51
|
+
end
|
|
39
52
|
end
|
|
40
53
|
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Kind
|
|
4
|
+
module STRICT
|
|
5
|
+
[
|
|
6
|
+
:object_is_a, :class!, :kind_of,
|
|
7
|
+
:module_or_class, :module!, :not_nil
|
|
8
|
+
].each { |method_name| remove_method(method_name) }
|
|
9
|
+
|
|
10
|
+
def object_is_a(_kind, value, _label = nil) # :nodoc:
|
|
11
|
+
value
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def class!(value) # :nodoc:
|
|
15
|
+
value
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def kind_of(_kind, value, _kind_name = nil) # :nodoc:
|
|
19
|
+
value
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def module_or_class(value) # :nodoc:
|
|
23
|
+
value
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def module!(value) # :nodoc:
|
|
27
|
+
value
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def not_nil(value, label) # :nodoc:
|
|
31
|
+
value
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
data/lib/kind/try.rb
CHANGED
|
@@ -9,7 +9,7 @@ module Kind
|
|
|
9
9
|
extend self
|
|
10
10
|
|
|
11
11
|
def call!(object, method_name, args = Empty::ARRAY) # :nodoc
|
|
12
|
-
return if KIND.
|
|
12
|
+
return if KIND.nil_or_undefined?(object)
|
|
13
13
|
|
|
14
14
|
resolve(object, method_name, args)
|
|
15
15
|
end
|
|
@@ -21,7 +21,7 @@ module Kind
|
|
|
21
21
|
|
|
22
22
|
return result unless block_given?
|
|
23
23
|
|
|
24
|
-
yield(result) unless KIND.
|
|
24
|
+
yield(result) unless KIND.nil_or_undefined?(result)
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
def presence(*args, &block)
|
data/lib/kind/validator.rb
CHANGED
|
@@ -101,7 +101,7 @@ class KindValidator < ActiveModel::EachValidator
|
|
|
101
101
|
def kind_is_not(expected, value)
|
|
102
102
|
case expected
|
|
103
103
|
when ::Class
|
|
104
|
-
return if expected == Kind.
|
|
104
|
+
return if expected == Kind.of_class(value) || value < expected
|
|
105
105
|
|
|
106
106
|
"must be the class or a subclass of `#{expected.name}`"
|
|
107
107
|
when ::Module
|
data/lib/kind/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kind
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 5.
|
|
4
|
+
version: 5.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Rodrigo Serradura
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2021-
|
|
11
|
+
date: 2021-05-14 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
|
-
description: A
|
|
13
|
+
description: A development toolkit for Ruby with several small/cohesive abstractions
|
|
14
|
+
(monads, enums, business logic, data validation...) to empower your development
|
|
15
|
+
workflow - It's totally free of dependencies.
|
|
14
16
|
email:
|
|
15
17
|
- rodrigo.serradura@gmail.com
|
|
16
18
|
executables: []
|
|
@@ -31,8 +33,11 @@ files:
|
|
|
31
33
|
- bin/setup
|
|
32
34
|
- kind.gemspec
|
|
33
35
|
- lib/kind.rb
|
|
36
|
+
- lib/kind/__lib__/action_steps.rb
|
|
34
37
|
- lib/kind/__lib__/attributes.rb
|
|
35
38
|
- lib/kind/__lib__/kind.rb
|
|
39
|
+
- lib/kind/__lib__/of.rb
|
|
40
|
+
- lib/kind/__lib__/strict.rb
|
|
36
41
|
- lib/kind/__lib__/undefined.rb
|
|
37
42
|
- lib/kind/action.rb
|
|
38
43
|
- lib/kind/active_model/validation.rb
|
|
@@ -54,6 +59,7 @@ files:
|
|
|
54
59
|
- lib/kind/function.rb
|
|
55
60
|
- lib/kind/functional.rb
|
|
56
61
|
- lib/kind/functional/action.rb
|
|
62
|
+
- lib/kind/functional/steps.rb
|
|
57
63
|
- lib/kind/immutable_attributes.rb
|
|
58
64
|
- lib/kind/immutable_attributes/initializer.rb
|
|
59
65
|
- lib/kind/immutable_attributes/reader.rb
|
|
@@ -109,6 +115,7 @@ files:
|
|
|
109
115
|
- lib/kind/result/monad.rb
|
|
110
116
|
- lib/kind/result/monad/wrapper.rb
|
|
111
117
|
- lib/kind/result/success.rb
|
|
118
|
+
- lib/kind/strict/disabled.rb
|
|
112
119
|
- lib/kind/try.rb
|
|
113
120
|
- lib/kind/validator.rb
|
|
114
121
|
- lib/kind/version.rb
|
|
@@ -137,5 +144,6 @@ requirements: []
|
|
|
137
144
|
rubygems_version: 3.2.11
|
|
138
145
|
signing_key:
|
|
139
146
|
specification_version: 4
|
|
140
|
-
summary: A
|
|
147
|
+
summary: A development toolkit for Ruby with several small/cohesive abstractions to
|
|
148
|
+
empower your development workflow.
|
|
141
149
|
test_files: []
|