kind 6.0.0 → 6.0.1
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/CHANGELOG.md +345 -1943
- data/CLAUDE.md +117 -0
- data/README.md +2 -2
- data/kind.gemspec +1 -0
- data/lib/kind/version.rb +1 -1
- metadata +4 -2
data/CHANGELOG.md
CHANGED
|
@@ -1,420 +1,152 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
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
|
-
|
|
5
|
-
- [Unreleased](#unreleased)
|
|
6
|
-
- [Added](#added)
|
|
7
|
-
- [5.10.0 (2021-09-23)](#5100-2021-09-23)
|
|
8
|
-
- [Added](#added-1)
|
|
9
|
-
- [5.9.0 (2021-09-22)](#590-2021-09-22)
|
|
10
|
-
- [Added](#added-2)
|
|
11
|
-
- [5.8.1 (2021-09-22)](#581-2021-09-22)
|
|
12
|
-
- [Fixed](#fixed)
|
|
13
|
-
- [5.8.0 (2021-09-22)](#580-2021-09-22)
|
|
14
|
-
- [Added](#added-3)
|
|
15
|
-
- [5.7.0 (2021-06-22)](#570-2021-06-22)
|
|
16
|
-
- [Added](#added-4)
|
|
17
|
-
- [5.6.0 (2021-05-14)](#560-2021-05-14)
|
|
18
|
-
- [Added](#added-5)
|
|
19
|
-
- [5.5.0 (2021-04-05)](#550-2021-04-05)
|
|
20
|
-
- [Added](#added-6)
|
|
21
|
-
- [5.4.1 (2021-03-26)](#541-2021-03-26)
|
|
22
|
-
- [Fixed](#fixed-1)
|
|
23
|
-
- [5.4.0 (2021-03-25)](#540-2021-03-25)
|
|
24
|
-
- [Added](#added-7)
|
|
25
|
-
- [5.3.0 (2021-03-23)](#530-2021-03-23)
|
|
26
|
-
- [Added](#added-8)
|
|
27
|
-
- [5.2.0 (2021-03-17)](#520-2021-03-17)
|
|
28
|
-
- [Added](#added-9)
|
|
29
|
-
- [Deprecated](#deprecated)
|
|
30
|
-
- [Changes](#changes)
|
|
31
|
-
- [5.1.0 (2021-02-23)](#510-2021-02-23)
|
|
32
|
-
- [Added](#added-10)
|
|
33
|
-
- [Deprecated](#deprecated-1)
|
|
34
|
-
- [5.0.0 (2021-02-22)](#500-2021-02-22)
|
|
35
|
-
- [Breaking Changes](#breaking-changes)
|
|
36
|
-
- [Removed](#removed)
|
|
37
|
-
- [4.1.0 (2021-02-22)](#410-2021-02-22)
|
|
38
|
-
- [Added](#added-11)
|
|
39
|
-
- [4.0.0 (2021-02-22)](#400-2021-02-22)
|
|
40
|
-
- [Added](#added-12)
|
|
41
|
-
- [Deprecated](#deprecated-2)
|
|
42
|
-
- [Fixed](#fixed-2)
|
|
43
|
-
- [3.1.0 (2020-07-08)](#310-2020-07-08)
|
|
44
|
-
- [Added](#added-13)
|
|
45
|
-
- [3.0.0 (2020-06-25)](#300-2020-06-25)
|
|
46
|
-
- [Breaking Changes](#breaking-changes-1)
|
|
47
|
-
- [Added](#added-14)
|
|
48
|
-
- [2.3.0 (2020-06-24)](#230-2020-06-24)
|
|
49
|
-
- [Added](#added-15)
|
|
50
|
-
- [2.2.0 (2020-06-23)](#220-2020-06-23)
|
|
51
|
-
- [Added](#added-16)
|
|
52
|
-
- [2.1.0 (2020-05-12)](#210-2020-05-12)
|
|
53
|
-
- [Added](#added-17)
|
|
54
|
-
- [Breaking Changes](#breaking-changes-2)
|
|
55
|
-
- [2.0.0 (2020-05-07)](#200-2020-05-07)
|
|
56
|
-
- [Added](#added-18)
|
|
57
|
-
- [Breaking Changes](#breaking-changes-3)
|
|
58
|
-
- [Removed](#removed-1)
|
|
59
|
-
- [1.9.0 (2020-05-06)](#190-2020-05-06)
|
|
60
|
-
- [Added](#added-19)
|
|
61
|
-
- [1.8.0 (2020-05-03)](#180-2020-05-03)
|
|
62
|
-
- [Added](#added-20)
|
|
63
|
-
- [1.7.0 (2020-05-03)](#170-2020-05-03)
|
|
64
|
-
- [Fixed](#fixed-3)
|
|
65
|
-
- [1.6.0 (2020-04-17)](#160-2020-04-17)
|
|
66
|
-
- [Added](#added-21)
|
|
67
|
-
- [Changes](#changes-1)
|
|
68
|
-
- [1.5.0 (2020-04-12)](#150-2020-04-12)
|
|
69
|
-
- [Added](#added-22)
|
|
70
|
-
- [1.4.0 (2020-04-12)](#140-2020-04-12)
|
|
71
|
-
- [Added](#added-23)
|
|
72
|
-
- [1.3.0 (2020-04-12)](#130-2020-04-12)
|
|
73
|
-
- [Added](#added-24)
|
|
74
|
-
- [1.2.0 (2020-04-12)](#120-2020-04-12)
|
|
75
|
-
- [Added](#added-25)
|
|
76
|
-
- [1.1.0 (2020-04-09)](#110-2020-04-09)
|
|
77
|
-
- [Added](#added-26)
|
|
78
|
-
- [Fixed](#fixed-4)
|
|
79
|
-
- [1.0.0 (2020-03-16)](#100-2020-03-16)
|
|
80
|
-
- [Added](#added-27)
|
|
81
|
-
- [0.6.0 (2020-01-06)](#060-2020-01-06)
|
|
82
|
-
- [Added](#added-28)
|
|
83
|
-
- [0.5.0 (2020-01-04)](#050-2020-01-04)
|
|
84
|
-
- [Added](#added-29)
|
|
85
|
-
- [0.4.0 (2020-01-03)](#040-2020-01-03)
|
|
86
|
-
- [Added](#added-30)
|
|
87
|
-
- [0.3.0 (2020-01-03)](#030-2020-01-03)
|
|
88
|
-
- [Added](#added-31)
|
|
89
|
-
- [Breaking Changes](#breaking-changes-4)
|
|
90
|
-
- [0.2.0 (2020-01-02)](#020-2020-01-02)
|
|
91
|
-
- [Added](#added-32)
|
|
92
|
-
- [0.1.0 (2019-12-26)](#010-2019-12-26)
|
|
93
|
-
- [Added](#added-33)
|
|
94
|
-
|
|
95
|
-
## Unreleased
|
|
1
|
+
# Changelog
|
|
96
2
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
* [#71](https://github.com/serradura/kind/pull/71) - Add `Kind::Maybe#to_proc`.
|
|
100
|
-
```ruby
|
|
101
|
-
result = operation_that_can_return_nil().then(&Kind::Maybe)
|
|
102
|
-
# => #<Kind::Some value=:result>
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
<!--
|
|
106
|
-
### Breaking Changes
|
|
107
|
-
### Deprecated
|
|
108
|
-
### Removed
|
|
109
|
-
### Fixed
|
|
110
|
-
-->
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
111
4
|
|
|
112
|
-
|
|
113
|
-
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
114
7
|
|
|
8
|
+
## [6.0.1] - 2026-05-24
|
|
115
9
|
### Added
|
|
10
|
+
- This `CHANGELOG.md`, rewritten to follow the [Keep a Changelog 1.1.0](https://keepachangelog.com/en/1.1.0/) spec and backfilled to cover every tagged release from `0.1.0` through `6.0.1` (including the previously undocumented `3.0.1` patch and the `6.0.0` major).
|
|
11
|
+
- `bug_tracker_uri` entry in `spec.metadata` so RubyGems.org surfaces a direct link to the issue tracker from the gem page.
|
|
116
12
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
Kind::Any
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
[⬆️ Back to Top](#changelog-)
|
|
127
|
-
|
|
128
|
-
5.9.0 (2021-09-22)
|
|
129
|
-
------------------
|
|
13
|
+
## [6.0.0] - 2026-05-23
|
|
14
|
+
### Changed
|
|
15
|
+
- **BREAKING:** Bumped minimum Ruby to **2.7.0** (Ruby 2.1 – 2.6 are EOL and no longer supported).
|
|
16
|
+
- Modernized the CI/test runner via Appraisal (mirroring the `u-case` 5.0 layout): the per-Ruby `ENV`-switched `Gemfile` and `bin/test` / `bin/prepare_coverage` scripts were replaced with an `Appraisals` file gated on `RUBY_VERSION`, the GitHub Actions matrix now covers Ruby 2.7 – 4.0+head with conditional ActiveModel steps, and per-module (`KIND_BASIC`) and `KIND_STRICT` runs are preserved as matrix axes.
|
|
17
|
+
- Switched code coverage reporting from CodeClimate to **Qlty** (token-based upload, badges updated in README).
|
|
18
|
+
- README polish: new header/badge layout, refreshed Ruby × ActiveModel compatibility table, added Ruby × Rails CI support matrix, and installation example pinned to `~> 6.0`. Pre-5.x rows dropped from the Documentation and Compatibility tables (long EOL).
|
|
19
|
+
- Ruby 3.4+/4.0 compatibility: rebuild `Kind::Any`'s brace-list `inspect` from values directly so the name stays `Kind::Any{:low, :high}` across the Ruby 4.0 `Set#inspect` format change; tests updated for the 3.4 quote/hash-literal display changes.
|
|
130
20
|
|
|
131
21
|
### Added
|
|
22
|
+
- [#71](https://github.com/serradura/kind/pull/71) - Add `Kind::Maybe#to_proc` (thanks @tomascco), so `Kind::Maybe` can be passed where a block-arg is expected.
|
|
23
|
+
```ruby
|
|
24
|
+
result = operation_that_can_return_nil().then(&Kind::Maybe)
|
|
25
|
+
# => #<Kind::Some value=:result>
|
|
26
|
+
```
|
|
27
|
+
- Appraisal-generated gemfiles for **Rails 8.1** and **Rails edge**.
|
|
28
|
+
- `bin/matrix` script and `rake matrix` task to run the full local test matrix.
|
|
29
|
+
- `bin/setup` script.
|
|
132
30
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
PositiveInteger = Kind.object(name: 'PositiveInteger') do |value|
|
|
136
|
-
value.kind_of?(Integer) && value > 0
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
# PositiveInteger.name
|
|
140
|
-
# PositiveInteger.kind
|
|
141
|
-
# The type handler can return its kind and its name
|
|
142
|
-
PositiveInteger.name # "PositiveInteger"
|
|
143
|
-
PositiveInteger.kind # #<Proc:0x0000.... >
|
|
144
|
-
|
|
145
|
-
# PositiveInteger.===
|
|
146
|
-
# Can check if a given value is an instance of its kind.
|
|
147
|
-
PositiveInteger === 1 # true
|
|
148
|
-
PositiveInteger === 0 # false
|
|
149
|
-
|
|
150
|
-
# PositiveInteger.value?(value)
|
|
151
|
-
# Can check if a given value is an instance of its kind.
|
|
152
|
-
PositiveInteger.value?(1) # true
|
|
153
|
-
PositiveInteger.value?(-1) # false
|
|
154
|
-
|
|
155
|
-
# If it doesn't receive an argument, a lambda will be returned and it will know how to do the type verification.
|
|
156
|
-
[1, 2, 0, 3, -1].select(&PositiveInteger.value?) # [1, 2, 3]
|
|
157
|
-
|
|
158
|
-
# PositiveInteger.or_nil(value)
|
|
159
|
-
# Can return nil if the given value isn't an instance of its kind
|
|
160
|
-
PositiveInteger.or_nil(1) # 1
|
|
161
|
-
PositiveInteger.or_nil(0) # nil
|
|
162
|
-
|
|
163
|
-
# PositiveInteger.or_undefined(value)
|
|
164
|
-
# Can return Kind::Undefined if the given value isn't an instance of its kind
|
|
165
|
-
PositiveInteger.or_undefined(2) # 2
|
|
166
|
-
PositiveInteger.or_undefined(-1) # Kind::Undefined
|
|
167
|
-
|
|
168
|
-
# PositiveInteger.or(fallback, value)
|
|
169
|
-
# Can return a fallback if the given value isn't an instance of its kind
|
|
170
|
-
PositiveInteger.or(nil, 1) # 1
|
|
171
|
-
PositiveInteger.or(nil, 0) # nil
|
|
172
|
-
|
|
173
|
-
# If it doesn't receive a second argument (the value), it will return a callable that knows how to expose an instance of the expected type or a fallback if the given value was wrong.
|
|
174
|
-
[1, 2, 0, 3, -1].map(&PositiveInteger.or(1)) # [1, 2, 1, 3, 1]
|
|
175
|
-
[1, 2, 0, 3, -1].map(&PositiveInteger.or(nil)) # [1, 2, nil, 3, nil]
|
|
176
|
-
|
|
177
|
-
# An error will be raised if the fallback didn't have the expected kind or if not nil / Kind::Undefined.
|
|
178
|
-
[1, 2, 0, 3, -1].map(&PositiveInteger.or(:foo)) # Kind::Error (:foo expected to be a kind of PositiveInteger)
|
|
179
|
-
|
|
180
|
-
# PositiveInteger[value]
|
|
181
|
-
# Will raise Kind::Error if the given value isn't an instance of the expected kind
|
|
182
|
-
PositiveInteger[1] # 1
|
|
183
|
-
PositiveInteger[:foo] # Kind::Error (:foo expected to be a kind of PositiveInteger)
|
|
184
|
-
|
|
185
|
-
# PositiveInteger.value(arg, default:)
|
|
186
|
-
# This method ensures that you will have a value of the expected kind. But, in the case of the given value be invalid, this method will require a default value (with the expected kind) to be returned.
|
|
187
|
-
PositiveInteger.value(2, default: 1) # 2
|
|
188
|
-
|
|
189
|
-
PositiveInteger.value('1', default: 1) # 1
|
|
31
|
+
### Removed
|
|
32
|
+
- `bin/test` and `bin/prepare_coverage` (replaced by the Appraisal-driven setup).
|
|
190
33
|
|
|
191
|
-
|
|
34
|
+
### Security
|
|
35
|
+
- Hardened the GitHub Actions workflow: least-privilege `contents: read` permissions on the test job and `persist-credentials: false` on `actions/checkout`.
|
|
192
36
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
37
|
+
## [5.10.0] - 2021-09-23
|
|
38
|
+
### Added
|
|
39
|
+
- [#69](https://github.com/serradura/kind/pull/69) - Make `Kind::Any` work with a `Set`.
|
|
40
|
+
```ruby
|
|
41
|
+
require 'kind/any'
|
|
196
42
|
|
|
197
|
-
|
|
198
|
-
|
|
43
|
+
Kind::Any.new(Set[:low, :high]).inspect # Kind::Any{:low, :high}
|
|
44
|
+
Kind::Any.new(Array['open', 'close']).inspect # Kind::Any["open", "close"]
|
|
45
|
+
```
|
|
199
46
|
|
|
200
|
-
[
|
|
47
|
+
## [5.9.0] - 2021-09-22
|
|
48
|
+
### Added
|
|
49
|
+
- [#68](https://github.com/serradura/kind/pull/68) - Add `Kind.object(name:, &block)` to create `Kind::Objects` (custom type handlers) with the full handler API: `.name`, `.kind`, `.===`, `.value?`, `.or_nil`, `.or_undefined`, `.or(fallback)`, `.[]`, `.value(arg, default:)`, and `.maybe`.
|
|
50
|
+
```ruby
|
|
51
|
+
PositiveInteger = Kind.object(name: 'PositiveInteger') do |value|
|
|
52
|
+
value.kind_of?(Integer) && value > 0
|
|
53
|
+
end
|
|
201
54
|
|
|
202
|
-
|
|
203
|
-
|
|
55
|
+
PositiveInteger === 1 # true
|
|
56
|
+
PositiveInteger.or_nil(0) # nil
|
|
57
|
+
PositiveInteger[:foo] # Kind::Error (:foo expected to be a kind of PositiveInteger)
|
|
58
|
+
PositiveInteger.value(2, default: 1) # 2
|
|
59
|
+
PositiveInteger.maybe(0).value_or(1) # 1
|
|
60
|
+
```
|
|
204
61
|
|
|
62
|
+
## [5.8.1] - 2021-09-22
|
|
205
63
|
### Fixed
|
|
64
|
+
- [#67](https://github.com/serradura/kind/pull/67) - Make `Kind.assert_hash!(some_hash, schema:)` work with a `Kind::Any` instance.
|
|
65
|
+
```ruby
|
|
66
|
+
require 'kind/any'
|
|
206
67
|
|
|
207
|
-
|
|
208
|
-
```ruby
|
|
209
|
-
require 'kind/any'
|
|
210
|
-
|
|
211
|
-
Level = Kind::Any[:low, :high]
|
|
212
|
-
|
|
213
|
-
Kind.assert_hash!({level: :medium}, schema: {level: Level})
|
|
214
|
-
# Kind::Error (The key :status has an invalid value. Expected: Kind::Any[:low, :high])
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
[⬆️ Back to Top](#changelog-)
|
|
68
|
+
Level = Kind::Any[:low, :high]
|
|
218
69
|
|
|
219
|
-
|
|
220
|
-
|
|
70
|
+
Kind.assert_hash!({level: :medium}, schema: {level: Level})
|
|
71
|
+
# Kind::Error (The key :status has an invalid value. Expected: Kind::Any[:low, :high])
|
|
72
|
+
```
|
|
221
73
|
|
|
74
|
+
## [5.8.0] - 2021-09-22
|
|
222
75
|
### Added
|
|
223
|
-
|
|
224
|
-
* [#66](https://github.com/serradura/kind/pull/66) - Add `Kind::Any` to make easier the verification of a value in a list (array) of expected values.
|
|
76
|
+
- [#66](https://github.com/serradura/kind/pull/66) - Add `Kind::Any` to verify a value belongs to a list of expected values.
|
|
225
77
|
```ruby
|
|
226
78
|
require 'kind/any'
|
|
227
79
|
|
|
228
80
|
Level = Kind::Any[:low, :high] # or Kind::Any.new([:low, :high])
|
|
229
81
|
|
|
230
|
-
Level === :low
|
|
231
|
-
Level === :
|
|
232
|
-
|
|
233
|
-
Level
|
|
234
|
-
|
|
235
|
-
Level[:low] # :low
|
|
236
|
-
Level[:high] # :high
|
|
237
|
-
|
|
238
|
-
Level[:foo] # Kind::Error (:foo expected to be a kind of Kind::Any[:low, :high])
|
|
239
|
-
|
|
240
|
-
level_or_any_symbol = # (Kind::Any[:low, :high] | Symbol)
|
|
241
|
-
|
|
242
|
-
Level.name # 'Kind::Any[:low, :high]'
|
|
243
|
-
Level.inspect # 'Kind::Any[:low, :high]'
|
|
244
|
-
|
|
245
|
-
Level.values # [:low, :high]
|
|
82
|
+
Level === :low # true
|
|
83
|
+
Level === :foo # false
|
|
84
|
+
Level[:low] # :low
|
|
85
|
+
Level[:foo] # Kind::Error (:foo expected to be a kind of Kind::Any[:low, :high])
|
|
86
|
+
Level.values # [:low, :high]
|
|
246
87
|
```
|
|
247
|
-
|
|
248
|
-
* [#66](https://github.com/serradura/kind/pull/66) - Add `Kind::Enum.from_array(arg, use_index_as_value:)` to allow the creation of enums where its values will be the array values.
|
|
88
|
+
- [#66](https://github.com/serradura/kind/pull/66) - Add `Kind::Enum.from_array(arg, use_index_as_value:)` to allow the creation of enums where the values come from the array (either the values themselves or their indices).
|
|
249
89
|
```ruby
|
|
250
|
-
require 'kind/enum'
|
|
251
|
-
|
|
252
90
|
module Level
|
|
253
91
|
include Kind::Enum.from_array([:low, :medium, :high], use_index_as_value: false)
|
|
254
92
|
end
|
|
255
|
-
|
|
256
|
-
Level.keys # ["low", "medium", "high"]
|
|
257
93
|
Level.values # [:low, :medium, :high]
|
|
258
94
|
|
|
259
|
-
# ---
|
|
260
|
-
|
|
261
95
|
module Status
|
|
262
96
|
include Kind::Enum.from_array([:open, :closed], use_index_as_value: true)
|
|
263
97
|
end
|
|
264
|
-
|
|
265
|
-
Status.keys # ["open", "closed"]
|
|
266
98
|
Status.values # [0, 1]
|
|
267
99
|
```
|
|
100
|
+
- [#66](https://github.com/serradura/kind/pull/66) - Make `Kind.assert_hash!(hash, schema:)` work with `Kind::Object` instances.
|
|
101
|
+
- [#66](https://github.com/serradura/kind/pull/66) - Improve the exception messages of `Kind.assert_hash!(hash, schema:)`.
|
|
102
|
+
- [#66](https://github.com/serradura/kind/pull/66) - Make `Kind.assert_hash!(hash, **options)` raise `ArgumentError` if the given hash is empty.
|
|
268
103
|
|
|
269
|
-
|
|
270
|
-
```ruby
|
|
271
|
-
FilledString = begin
|
|
272
|
-
filled_string = ->(value) {value.is_a?(String) && value.present?}
|
|
273
|
-
|
|
274
|
-
Kind[filled_string, name: 'FilledString']
|
|
275
|
-
end
|
|
276
|
-
|
|
277
|
-
Kind.assert_hash!(some_hash, schema: {
|
|
278
|
-
string: FilledString,
|
|
279
|
-
callable: Kind::Callable,
|
|
280
|
-
})
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
* [#66](https://github.com/serradura/kind/pull/66) - Improve the exception messages of `Kind.assert_hash!(hash, schema:)`.
|
|
284
|
-
```ruby
|
|
285
|
-
Kind.assert_hash!({status: 1}, schema: {status: Kind::String | Symbol})
|
|
286
|
-
# Kind::Error (The key :status has an invalid value. Expected: (String | Symbol))
|
|
287
|
-
|
|
288
|
-
Kind.assert_hash!({status: 'closed'}, schema: {status: 'active'})
|
|
289
|
-
# Kind::Error (The key :status has an invalid value. Expected: active, Given: closed)
|
|
290
|
-
|
|
291
|
-
Kind.assert_hash!({callable: 1}, schema: {callable: Kind::Callable})
|
|
292
|
-
# Kind::Error (The key :callable has an invalid value. Expected: Callable)
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
* [#66](https://github.com/serradura/kind/pull/66) - Make `Kind.assert_hash!(hash, **options)` raises an error if the given hash be empty.
|
|
296
|
-
```ruby
|
|
297
|
-
Kind.assert_hash!({}, keys: []) # ArgumentError (hash can't be empty)
|
|
298
|
-
Kind.assert_hash!({}, schema: {}) # ArgumentError (hash can't be empty)
|
|
299
|
-
```
|
|
300
|
-
|
|
301
|
-
[⬆️ Back to Top](#changelog-)
|
|
302
|
-
|
|
303
|
-
5.7.0 (2021-06-22)
|
|
304
|
-
------------------
|
|
305
|
-
|
|
104
|
+
## [5.7.0] - 2021-06-22
|
|
306
105
|
### Added
|
|
307
|
-
|
|
308
|
-
* [#58](https://github.com/serradura/kind/pull/58) - Add `Add Kind.assert_hash!(hash, keys:)`, you can use the `require_all:` option to check if the hashes have the same keys.
|
|
106
|
+
- [#58](https://github.com/serradura/kind/pull/58) - Add `Kind.assert_hash!(hash, keys:)` with an optional `require_all:` to check the hash exposes exactly the expected keys.
|
|
309
107
|
```ruby
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
Kind.assert_hash!(h1, keys: [:a, :b])
|
|
313
|
-
Kind.assert_hash!(h1, keys: [:a]) # ArgumentError (Unknown key: :b. Valid keys are: :a)
|
|
314
|
-
|
|
315
|
-
# --
|
|
316
|
-
|
|
317
|
-
h2 = {'a' => 1, 'b' => 2}
|
|
318
|
-
|
|
319
|
-
Kind.assert_hash!(h2, keys: ['a', 'b'])
|
|
108
|
+
Kind.assert_hash!({a: 1, b: 1}, keys: [:a, :b])
|
|
109
|
+
Kind.assert_hash!({a: 1, b: 1}, keys: [:a]) # ArgumentError (Unknown key: :b. Valid keys are: :a)
|
|
320
110
|
```
|
|
321
|
-
|
|
322
|
-
* [#58](https://github.com/serradura/kind/pull/58) - Add `Add Kind.assert_hash!(hash, schema:)`, you can use the `require_all:` option to check if the hashes have the same keys.
|
|
111
|
+
- [#58](https://github.com/serradura/kind/pull/58) - Add `Kind.assert_hash!(hash, schema:)` to validate hash shapes via literal values, classes, regexes or lambdas.
|
|
323
112
|
```ruby
|
|
324
|
-
hash = {hash: {}, array: [], number: 1, string: 'foo', email: 'bar@bar.com', null: nil}
|
|
325
|
-
|
|
326
|
-
Kind.assert_hash!(hash, schema: {
|
|
327
|
-
hash: {},
|
|
328
|
-
array: [],
|
|
329
|
-
email: 'bar@bar.com',
|
|
330
|
-
string: 'foo',
|
|
331
|
-
number: 1,
|
|
332
|
-
null: nil
|
|
333
|
-
})
|
|
334
|
-
|
|
335
|
-
Kind.assert_hash!(hash, schema: {
|
|
336
|
-
hash: Enumerable,
|
|
337
|
-
array: Enumerable,
|
|
338
|
-
email: /\A.+@.+\..+\z/,
|
|
339
|
-
string: String
|
|
340
|
-
})
|
|
341
|
-
|
|
342
113
|
Kind.assert_hash!(hash, schema: {
|
|
343
|
-
hash:
|
|
344
|
-
array:
|
|
345
|
-
email:
|
|
114
|
+
hash: Enumerable,
|
|
115
|
+
array: Enumerable,
|
|
116
|
+
email: /\A.+@.+\..+\z/,
|
|
346
117
|
string: String
|
|
347
118
|
})
|
|
348
|
-
|
|
349
|
-
Kind.assert_hash!(h1, schema: {
|
|
350
|
-
email: ->(value) { value.is_a?(String) && value.include?('@') }
|
|
351
|
-
})
|
|
352
119
|
```
|
|
353
120
|
|
|
354
|
-
[
|
|
355
|
-
|
|
356
|
-
5.6.0 (2021-05-14)
|
|
357
|
-
------------------
|
|
358
|
-
|
|
121
|
+
## [5.6.0] - 2021-05-14
|
|
359
122
|
### Added
|
|
360
|
-
|
|
361
|
-
* [#57](https://github.com/serradura/kind/pull/57) - Allow the usage of `nil` to define union types.
|
|
123
|
+
- [#57](https://github.com/serradura/kind/pull/57) - Allow `nil` in union-type definitions.
|
|
362
124
|
```ruby
|
|
363
125
|
(Kind::String | nil) === '' # true
|
|
364
126
|
(Kind::String | nil) === nil # true
|
|
365
|
-
|
|
366
127
|
(Kind::String | nil) === {} # false
|
|
367
128
|
```
|
|
368
129
|
|
|
369
|
-
[
|
|
370
|
-
|
|
371
|
-
5.5.0 (2021-04-05)
|
|
372
|
-
------------------
|
|
373
|
-
|
|
130
|
+
## [5.5.0] - 2021-04-05
|
|
374
131
|
### Added
|
|
375
|
-
|
|
376
|
-
* [#56](https://github.com/serradura/kind/pull/56) - Add `Kind.or_nil()`.
|
|
132
|
+
- [#56](https://github.com/serradura/kind/pull/56) - Add `Kind.or_nil()`.
|
|
377
133
|
```ruby
|
|
378
|
-
Kind.or_nil(String, 1)
|
|
379
|
-
|
|
134
|
+
Kind.or_nil(String, 1) # nil
|
|
380
135
|
Kind.or_nil(String, '') # ""
|
|
381
136
|
|
|
382
|
-
# --
|
|
383
|
-
|
|
384
137
|
filled_string = ->(value) { value.is_a?(String) && !value.empty? }
|
|
385
|
-
|
|
386
|
-
Kind.or_nil(filled_string, 1) # nil
|
|
387
|
-
Kind.or_nil(filled_string, '') # nil
|
|
388
|
-
|
|
138
|
+
Kind.or_nil(filled_string, '') # nil
|
|
389
139
|
Kind.or_nil(filled_string, '1') # "1"
|
|
390
140
|
```
|
|
391
141
|
|
|
392
|
-
[
|
|
393
|
-
|
|
394
|
-
5.4.1 (2021-03-26)
|
|
395
|
-
------------------
|
|
396
|
-
|
|
142
|
+
## [5.4.1] - 2021-03-26
|
|
397
143
|
### Fixed
|
|
144
|
+
- [#55](https://github.com/serradura/kind/pull/55) - Fix `Kind::Either::Left#value_or` and `Kind::Result::Failure#value_or` so a block call receives the underlying value of the monad.
|
|
398
145
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
[⬆️ Back to Top](#changelog-)
|
|
402
|
-
|
|
403
|
-
5.4.0 (2021-03-25)
|
|
404
|
-
------------------
|
|
405
|
-
|
|
146
|
+
## [5.4.0] - 2021-03-25
|
|
406
147
|
### Added
|
|
407
|
-
|
|
408
|
-
* [#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.
|
|
148
|
+
- [#54](https://github.com/serradura/kind/pull/54) - Add `Kind::Functional::Steps`, allowing the use of `Step`, `Map`, `Try`, `Tee`, `Check`, `Success` and `Failure` in any object (classes and modules) to chain operations through `>>`.
|
|
409
149
|
```ruby
|
|
410
|
-
# Usage in classes' instances
|
|
411
|
-
|
|
412
|
-
class BaseJob
|
|
413
|
-
def self.perform_now(input); new.perform(input); end
|
|
414
|
-
|
|
415
|
-
def perform(input); raise NotImplementedError; end
|
|
416
|
-
end
|
|
417
|
-
|
|
418
150
|
class CreateUserJob < BaseJob
|
|
419
151
|
include Kind::Functional::Steps
|
|
420
152
|
|
|
@@ -425,1653 +157,323 @@ Kind.assert_hash!({level: :medium}, schema: {level: Level})
|
|
|
425
157
|
end
|
|
426
158
|
|
|
427
159
|
private
|
|
428
|
-
|
|
429
|
-
def
|
|
430
|
-
|
|
431
|
-
end
|
|
432
|
-
|
|
433
|
-
def create(input)
|
|
434
|
-
# Success() or Failure()
|
|
435
|
-
end
|
|
436
|
-
|
|
437
|
-
def welcome_email(email)
|
|
438
|
-
# Success() or Failure()
|
|
439
|
-
end
|
|
440
|
-
end
|
|
441
|
-
|
|
442
|
-
# Usage in modules (singleton methods)
|
|
443
|
-
|
|
444
|
-
module CreateUser
|
|
445
|
-
extend self, Kind::Functional::Steps
|
|
446
|
-
|
|
447
|
-
def perform(input)
|
|
448
|
-
Step!(:validate, input) \
|
|
449
|
-
>> Step(:create) \
|
|
450
|
-
>> Step(:welcome_email)
|
|
451
|
-
end
|
|
452
|
-
|
|
453
|
-
private
|
|
454
|
-
|
|
455
|
-
def validate(input)
|
|
456
|
-
# Success() or Failure()
|
|
457
|
-
end
|
|
458
|
-
|
|
459
|
-
def create(input)
|
|
460
|
-
# Success() or Failure()
|
|
461
|
-
end
|
|
462
|
-
|
|
463
|
-
def welcome_email(email)
|
|
464
|
-
# Success() or Failure()
|
|
465
|
-
end
|
|
160
|
+
def validate(input); end # Success() or Failure()
|
|
161
|
+
def create(input); end # Success() or Failure()
|
|
162
|
+
def welcome_email(email); end # Success() or Failure()
|
|
466
163
|
end
|
|
467
164
|
```
|
|
468
165
|
|
|
469
|
-
[
|
|
470
|
-
|
|
471
|
-
5.3.0 (2021-03-23)
|
|
472
|
-
------------------
|
|
473
|
-
|
|
166
|
+
## [5.3.0] - 2021-03-23
|
|
474
167
|
### Added
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
* [#53](https://github.com/serradura/kind/pull/53) - Add `|` and `>>` as an alias of `Kind::Result#map!`.
|
|
479
|
-
|
|
480
|
-
* [#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`.
|
|
168
|
+
- [#53](https://github.com/serradura/kind/pull/53) - Allow `Kind::Result#map` and `Kind::Result#map!` to receive a callable.
|
|
169
|
+
- [#53](https://github.com/serradura/kind/pull/53) - Add `|` and `>>` as aliases for `Kind::Result#map!`.
|
|
170
|
+
- [#53](https://github.com/serradura/kind/pull/53) - Add step adapters (`Step`, `Map`, `Try`, `Tee`, `Check`) for `Kind::Action` and `Kind::Functional::Action`.
|
|
481
171
|
```ruby
|
|
482
172
|
module CreateUser
|
|
483
173
|
extend Kind::Functional::Action
|
|
484
174
|
|
|
485
175
|
def call!(input)
|
|
486
|
-
Step!(:validate, input)
|
|
487
|
-
| Step(:create)
|
|
176
|
+
Step!(:validate, input) | Step(:create)
|
|
488
177
|
end
|
|
489
178
|
|
|
490
179
|
private
|
|
491
|
-
|
|
492
|
-
def
|
|
493
|
-
# returns Success(valid_data) or Failure(validation)
|
|
494
|
-
end
|
|
495
|
-
|
|
496
|
-
def create(input)
|
|
497
|
-
# returns Success(user)
|
|
498
|
-
end
|
|
180
|
+
def validate(input); end # returns Success(valid_data) or Failure(validation)
|
|
181
|
+
def create(input); end # returns Success(user)
|
|
499
182
|
end
|
|
500
183
|
```
|
|
184
|
+
- [#53](https://github.com/serradura/kind/pull/53) - Add `kind/strict/disabled` to turn off all strict validations (`Kind.of`, `Kind.of_class`, `Kind.of_module`, `Kind.of_module_or_class`, `Kind::<Type>[1]`, `Kind::NotNil[1]`) to optimize the runtime in production while keeping strict validation in development.
|
|
185
|
+
|
|
186
|
+
## [5.2.0] - 2021-03-17
|
|
187
|
+
### Added
|
|
188
|
+
- [#46](https://github.com/serradura/kind/pull/46) - Add `Kind.respond_to?(method_name)` — behaves like the native `respond_to?` — and `Kind.respond_to?(object, *method_names)` to check an object implements a given set of methods.
|
|
189
|
+
- [#46](https://github.com/serradura/kind/pull/46) - Add `Kind::UnionType` for composing type checks via `|`, with `===`, `[]` and `#name`/`#inspect` returning e.g. `"(Array | Hash)"`.
|
|
190
|
+
- [#46](https://github.com/serradura/kind/pull/46) - Add `Kind::Nil`, useful when composing union types: `Kind::UnionType[Hash] | Kind::Nil`.
|
|
191
|
+
- [#46](https://github.com/serradura/kind/pull/46), [#47](https://github.com/serradura/kind/pull/47) - Add `Kind::NotNil[value, label:]` for strict not-nil verification.
|
|
192
|
+
- [#46](https://github.com/serradura/kind/pull/46) - Add `Kind::RespondTo[*method_names]` for building duck-type checkers and composing them via `|`.
|
|
193
|
+
- [#46](https://github.com/serradura/kind/pull/46) - Unfreeze the output of `Kind::Boolean.kind`.
|
|
194
|
+
- [#46](https://github.com/serradura/kind/pull/46) - Freeze `Kind::UNDEFINED` and define its `inspect` method.
|
|
195
|
+
- [#46](https://github.com/serradura/kind/pull/46) - Add `Kind::TypeChecker#|` to compose union types (e.g. `Kind::String | Kind::Symbol`).
|
|
196
|
+
- [#46](https://github.com/serradura/kind/pull/46) - Allow `Kind.of()` and `Kind::TypeChecker#[]` to receive a `label:` for clearer error messages.
|
|
197
|
+
- [#46](https://github.com/serradura/kind/pull/46) - Add `kind/basic`, a minimal entry point exposing just the type-handling essentials: `Kind.is?`, `Kind.of`, `Kind.of?`, `Kind.of_class?`, `Kind.of_module?`, `Kind.of_module_or_class`, `Kind.respond_to`, `Kind.respond_to?`, `Kind.value`, `Kind::Error`, `Kind::Undefined`.
|
|
198
|
+
- [#46](https://github.com/serradura/kind/pull/46) - Improve `Kind::Maybe`: better `#inspect`; `Kind::Maybe.{new,[],wrap}` returns `None` when given an exception; add `#accept` (alias of `#check`) and `#reject` (its reverse); let `#map`, `#map!`, `#then`, `#then!`, `#check`, `#accept`, `#reject` accept a symbol (treated as a method to invoke on the wrapped value); add `Kind::Maybe#on` for block-based `some`/`none` handling.
|
|
199
|
+
- [#46](https://github.com/serradura/kind/pull/46) - Add `Kind::Either` (either monad). Not loaded by default — `require 'kind/either'`. Provides `Kind::Left()`, `Kind::Right()`, `#right?`/`#left?`, `#map`/`#then` for chaining (auto-handle `StandardError` returning `Left`), and `#map!`/`#then!` variants that let exceptions leak.
|
|
200
|
+
- [#46](https://github.com/serradura/kind/pull/46) - Add `Kind::Result` (an `Either` variation).
|
|
201
|
+
- [#46](https://github.com/serradura/kind/pull/46) - Add `Kind::Function`.
|
|
202
|
+
- [#46](https://github.com/serradura/kind/pull/46) - Add `Kind::Functional`.
|
|
203
|
+
- [#46](https://github.com/serradura/kind/pull/46) - Add `Kind::Try.presence` and improve the input/output handling of `Kind::Try.call`.
|
|
204
|
+
- [#46](https://github.com/serradura/kind/pull/46) - Add `Kind::Dig.presence` and improve the input/output handling of `Kind::Dig.call`.
|
|
205
|
+
- [#47](https://github.com/serradura/kind/pull/47) - Add `Kind.is!`.
|
|
206
|
+
- [#47](https://github.com/serradura/kind/pull/47) - Add aliases `Kind.of!` (for `Kind.of`) and `Kind.respond_to!` (for `Kind.respond_to`).
|
|
207
|
+
- [#47](https://github.com/serradura/kind/pull/47) - Add `Kind[]` as the replacement for `Kind::Of()`.
|
|
208
|
+
- [#49](https://github.com/serradura/kind/pull/49) - Add `Kind::Either::Methods` and `Kind::Result::Methods`.
|
|
209
|
+
- [#49](https://github.com/serradura/kind/pull/49) - Add `Kind::Undefined.empty?`.
|
|
210
|
+
- [#50](https://github.com/serradura/kind/pull/50) - Add `Kind::<Type>.empty_or` as an alias of `Kind::<Type>.value_or_empty`.
|
|
211
|
+
- [#46](https://github.com/serradura/kind/pull/46), [#51](https://github.com/serradura/kind/pull/51) - Add `Kind::Functional::Action`.
|
|
212
|
+
- [#51](https://github.com/serradura/kind/pull/51) - Add `Kind::Action`, `Kind::Maybe::ImmutableAttributes`, `Kind::Maybe::Methods`, and `Kind::Enum`.
|
|
213
|
+
- [#51](https://github.com/serradura/kind/pull/51) - Modularize all the `kind` components: `kind/action`, `kind/dig`, `kind/either`, `kind/empty`, `kind/enum`, `kind/function`, `kind/functional`, `kind/functional/action`, `kind/immutable_attributes`, `kind/maybe`, `kind/objects`, `kind/presence`, `kind/result`, `kind/try`, `kind/validator`. `kind/action` is the minimal requirement for all of them.
|
|
214
|
+
- [#52](https://github.com/serradura/kind/pull/52) - Improve `Kind::Validator` to accept lambdas or any object responding to `.===` and `.name` for kind validation.
|
|
215
|
+
- [#52](https://github.com/serradura/kind/pull/52) - Add `Kind::Enum.===`.
|
|
216
|
+
|
|
217
|
+
### Changed
|
|
218
|
+
- [#48](https://github.com/serradura/kind/pull/48) - Rename `Kind::TypeChecker` to `Kind::Object`, and `Kind::TypeChecker::Object` to `Kind::Object::Instance`.
|
|
501
219
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
* `Kind.of_module()`
|
|
506
|
-
* `Kind.of_module_or_class()`
|
|
507
|
-
* `Kind::<Type>[1]`
|
|
508
|
-
* `Kind::NotNil[1]`
|
|
509
|
-
|
|
510
|
-
[⬆️ Back to Top](#changelog-)
|
|
511
|
-
|
|
512
|
-
5.2.0 (2021-03-17)
|
|
513
|
-
------------------
|
|
220
|
+
### Deprecated
|
|
221
|
+
- [#47](https://github.com/serradura/kind/pull/47) - Deprecate `Kind.is` and `Kind::Of()`.
|
|
222
|
+
- [#48](https://github.com/serradura/kind/pull/48) - Deprecate `Kind::Maybe()` and `Kind::Optional()`.
|
|
514
223
|
|
|
224
|
+
## [5.1.0] - 2021-02-23
|
|
515
225
|
### Added
|
|
226
|
+
- [#45](https://github.com/serradura/kind/pull/45) - Add support for Ruby `>= 2.1.0`.
|
|
516
227
|
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
```ruby
|
|
520
|
-
Kind.respond_to?(:is?) # true
|
|
521
|
-
|
|
522
|
-
Kind.respond_to?(:foo?) # true
|
|
523
|
-
|
|
524
|
-
# --
|
|
525
|
-
|
|
526
|
-
Kind.respond_to?({}, :fetch, :merge) # true
|
|
527
|
-
|
|
528
|
-
Kind.respond_to?([], :fetch, :merge) # false
|
|
529
|
-
```
|
|
530
|
-
|
|
531
|
-
* [#46](https://github.com/serradura/kind/pull/46) - Add `Kind::UnionType`. This class allows the creation of an object that knows how to compare a value through different kinds of types. e.g.
|
|
532
|
-
```ruby
|
|
533
|
-
# The method [] can build a union type object that will have the method #|
|
|
534
|
-
# which allows the composition with other object kinds.
|
|
535
|
-
array_or_hash = Kind::UnionType[Array] | Hash
|
|
536
|
-
|
|
537
|
-
# The method === can verify if a given value is one of the kinds that compounds the union type.
|
|
538
|
-
array_or_hash === {} # true
|
|
539
|
-
array_or_hash === [] # true
|
|
540
|
-
array_or_hash === 1 # false
|
|
541
|
-
array_or_hash === nil # false
|
|
542
|
-
|
|
543
|
-
# The method #[] will return the given value if it has one of the expected kinds,
|
|
544
|
-
# but if not, it will raise a Kind::Error.
|
|
545
|
-
array_or_hash[{}] # {}
|
|
228
|
+
### Deprecated
|
|
229
|
+
- [#45](https://github.com/serradura/kind/pull/45) - `kind/active_model/validation` is deprecated; use `kind/validator` instead.
|
|
546
230
|
|
|
547
|
-
|
|
231
|
+
## [5.0.0] - 2021-02-22
|
|
232
|
+
### Changed
|
|
233
|
+
- [#44](https://github.com/serradura/kind/pull/44) - **BREAKING:** The top-level `Empty` constant is no longer defined automatically. Require `kind/empty/constant` to opt in to defining `Empty` as a `Kind::Empty` alias.
|
|
548
234
|
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
235
|
+
### Removed
|
|
236
|
+
- [#44](https://github.com/serradura/kind/pull/44) - Remove `Kind::Is.call`.
|
|
237
|
+
- [#44](https://github.com/serradura/kind/pull/44) - Remove `Kind::Of.call`.
|
|
238
|
+
- [#44](https://github.com/serradura/kind/pull/44) - Remove `Kind::Types.add`.
|
|
239
|
+
- [#44](https://github.com/serradura/kind/pull/44) - Remove `Kind::Of::<Type>` and `Kind::Is::<Type>` modules.
|
|
240
|
+
- [#44](https://github.com/serradura/kind/pull/44) - Remove `Kind::Checker`, `Kind::Checker::Protocol`, `Kind::Checker::Factory`.
|
|
241
|
+
- [#44](https://github.com/serradura/kind/pull/44) - Remove the invocation of `Kind.is` without arguments.
|
|
242
|
+
- [#44](https://github.com/serradura/kind/pull/44) - Remove the invocation of `Kind.of` without arguments.
|
|
243
|
+
- [#44](https://github.com/serradura/kind/pull/44) - Remove the invocation of `Kind.of` with a single argument (the kind).
|
|
553
244
|
|
|
554
|
-
|
|
245
|
+
## [4.1.0] - 2021-02-22
|
|
246
|
+
### Added
|
|
247
|
+
- [#43](https://github.com/serradura/kind/pull/43) - Make `Kind::Maybe::Typed` verify the kind of the value via `===`, enabling type checkers as the typed-`Maybe` kind.
|
|
555
248
|
```ruby
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
hash_or_nil === {} # true
|
|
559
|
-
hash_or_nil === [] # false
|
|
560
|
-
hash_or_nil === 1 # false
|
|
561
|
-
hash_or_nil === nil # true
|
|
249
|
+
Kind::Maybe(Kind::Boolean).wrap(nil).value_or(false) # false
|
|
250
|
+
Kind::Maybe(Kind::Boolean).wrap(true).value_or(false) # true
|
|
562
251
|
```
|
|
252
|
+
- [#43](https://github.com/serradura/kind/pull/43) - Add `Kind::<Type>.maybe` and `Kind::<Type>.optional`. Without arguments, returns a typed `Maybe` with the expected kind; with arguments, behaves like `Kind::Maybe.wrap`.
|
|
253
|
+
- [#43](https://github.com/serradura/kind/pull/43) - Make the `:respond_to` kind validation accept one or many method names: `validates :params, kind: { respond_to: [:[], :values_at] }`.
|
|
254
|
+
- [#43](https://github.com/serradura/kind/pull/43) - Make the `:of` kind validation verify the expected value kind via `===`, allowing type checkers to be used as expected kinds: `validates :alive, kind: Kind::Boolean`.
|
|
563
255
|
|
|
564
|
-
|
|
256
|
+
## [4.0.0] - 2021-02-22
|
|
257
|
+
### Added
|
|
258
|
+
- [#40](https://github.com/serradura/kind/pull/40) - Add `Kind.of_class?`, `Kind.of_module?`, and `Kind.of_module_or_class(value)` (returns the given value if it is a module/class, otherwise raises `Kind::Error`).
|
|
259
|
+
- [#40](https://github.com/serradura/kind/pull/40) - Add `Kind.respond_to(object, *method_names)`: returns the object if it responds to all of the given methods, raises otherwise.
|
|
260
|
+
- [#40](https://github.com/serradura/kind/pull/40) - Add `Kind::Try.call(receiver, method_name, *args)`: like `public_send`, but returns `nil` instead of raising when the receiver doesn't respond to the method.
|
|
261
|
+
- [#40](https://github.com/serradura/kind/pull/40), [#41](https://github.com/serradura/kind/pull/41) - Add `Kind::DEPRECATION` to warn about deprecations. Set `DISABLE_KIND_DEPRECATION` to silence the warnings.
|
|
262
|
+
- [#40](https://github.com/serradura/kind/pull/40), [#41](https://github.com/serradura/kind/pull/41) - Add **type checker modules** (`Kind::String`, `Kind::Integer`, etc.) exposing `.name`, `.kind`, `===`, `.value?`, `.or_nil`, `.or_undefined`, `.or(fallback)`, and `[value]`. The full list covers Core (`Array`, `Class`, `Comparable`, `Enumerable`, `Enumerator`, `File`, `Float`, `Hash`, `Integer`, `IO`, `Method`, `Module`, `Numeric`, `Proc`, `Queue`, `Range`, `Regexp`, `String`, `Struct`, `Symbol`, `Time`), Custom (`Boolean`, `Callable`, `Lambda`) and Stdlib (`OpenStruct`, `Set`).
|
|
263
|
+
- [#40](https://github.com/serradura/kind/pull/40) - Add `Kind::Of(kind, name: ...)` to create type checkers in runtime from any object responding to `.===`.
|
|
565
264
|
```ruby
|
|
566
|
-
Kind::
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
Kind::NotNil[nil, label: 'Foo#bar'] # Kind::Error (Foo#bar: expected to not be nil)
|
|
265
|
+
PositiveInteger = Kind::Of(-> value { value.is_a?(Integer) && value > 0 }, name: 'PositiveInteger')
|
|
266
|
+
PositiveInteger[1] # 1
|
|
267
|
+
PositiveInteger[:foo] # Kind::Error (:foo expected to be a kind of PositiveInteger)
|
|
571
268
|
```
|
|
269
|
+
- [#40](https://github.com/serradura/kind/pull/40), [#41](https://github.com/serradura/kind/pull/41) - Add **type checker methods** (`Kind::String?`, `Kind::Integer?`, etc.) that accept one or many values and return a lambda when called without arguments.
|
|
270
|
+
- [#41](https://github.com/serradura/kind/pull/41) - Make `Kind::Dig.call` extract values from regular objects (not just `Hash`/`Array`/`Struct`/`OpenStruct`).
|
|
271
|
+
- [#41](https://github.com/serradura/kind/pull/41) - Add `Kind::Presence.call`. Returns the given value if it is present, otherwise `nil`. Honors `#blank?` if defined on the object.
|
|
272
|
+
- [#41](https://github.com/serradura/kind/pull/41) - Add `Kind::Maybe#presence` returning `None` if the wrapped value is not present.
|
|
273
|
+
- [#41](https://github.com/serradura/kind/pull/41) - Make `Kind::Maybe#wrap` accept a block and intercept `StandardError` (returns `None` with the exception as its value).
|
|
274
|
+
- [#41](https://github.com/serradura/kind/pull/41) - Make `Kind::Maybe#map`/`#then` intercept `StandardError` and return `None`. Add `#map!`/`#then!` for the leaking variants.
|
|
275
|
+
- [#41](https://github.com/serradura/kind/pull/41) - Add `Kind::TypeCheckers#value(arg, default:)`, which ensures the returned value is of the expected kind (the default must also be of the kind).
|
|
276
|
+
- [#41](https://github.com/serradura/kind/pull/41) - Add `value_or_empty` for `Kind::Array`, `Kind::Hash`, `Kind::String`, `Kind::Set` (returns an empty frozen value when the input has the wrong kind).
|
|
277
|
+
- [#42](https://github.com/serradura/kind/pull/42) - Add `Kind.value(kind, arg, default:)`.
|
|
278
|
+
- [#42](https://github.com/serradura/kind/pull/42) - Add `Kind::Presence.to_proc` (e.g. `[...].map(&Kind::Presence)`).
|
|
279
|
+
- [#42](https://github.com/serradura/kind/pull/42) - Make `Kind::Maybe(<Type>).{new,[],wrap}` understand other `Maybe` monads as inputs (unwrapping their value).
|
|
280
|
+
- [#42](https://github.com/serradura/kind/pull/42) - Make `Kind::Maybe(<Type>).wrap(arg) { |arg_value| }` verify the argument kind when the block declares it.
|
|
281
|
+
- [#42](https://github.com/serradura/kind/pull/42) - Add `Kind::Maybe#check { ... }` returning the current `Some` if the block result is truthy, otherwise `None`.
|
|
282
|
+
- [#42](https://github.com/serradura/kind/pull/42) - Add `Kind::Dig[]` and `Kind::Try[]` for building lambdas that perform the dig/try strategies.
|
|
572
283
|
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
HashLike = Kind::RespondTo[:fetch, :merge!]
|
|
576
|
-
Fetchable = Kind::RespondTo[:fetch]
|
|
577
|
-
|
|
578
|
-
# Verifying if an object implements the expected interface.
|
|
579
|
-
HashLike === ENV # true
|
|
580
|
-
HashLike === {} # true
|
|
581
|
-
HashLike === [] # false
|
|
582
|
-
|
|
583
|
-
Fetchable === ENV # true
|
|
584
|
-
Fetchable === [] # true
|
|
585
|
-
Fetchable === {} # true
|
|
586
|
-
|
|
587
|
-
# Performing an strict verification
|
|
588
|
-
HashLike[ENV] # true
|
|
589
|
-
HashLike[{}] # true
|
|
590
|
-
HashLike[Array.new] # false Kind::Error ([] expected to be a kind of Kind::RespondTo[:fetch, :merge!])
|
|
591
|
-
|
|
592
|
-
# Creating union types using interfaces
|
|
593
|
-
HashLikeOrArray = HashLike | Array # Kind::RespondTo[:fetch, :merge!] | Array
|
|
284
|
+
### Deprecated
|
|
285
|
+
- [#40](https://github.com/serradura/kind/pull/40) - Deprecate `Kind::Is.call`, `Kind::Of.call`, `Kind::Types.add`, the `Kind::Of::<Type>` / `Kind::Is::<Type>` modules, `Kind::Checker` (+ `Protocol` / `Factory`), and the bare-argument invocations of `Kind.is`/`Kind.of`.
|
|
594
286
|
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
HashLikeOrArray === ENV # true
|
|
598
|
-
```
|
|
287
|
+
### Fixed
|
|
288
|
+
- [#40](https://github.com/serradura/kind/pull/40) - Make `Kind::Maybe.try!()` raise when called without a block or arguments.
|
|
599
289
|
|
|
600
|
-
|
|
290
|
+
## [3.1.0] - 2020-07-08
|
|
291
|
+
### Added
|
|
292
|
+
- [#33](https://github.com/serradura/kind/pull/33) - Add `Kind::Of::OpenStruct` / `Kind::Is::OpenStruct`.
|
|
293
|
+
- [#33](https://github.com/serradura/kind/pull/33) - Add `Kind::Maybe::Result#dig`. Extracts nested values; if any step returns `nil`, returns `None`, otherwise `Some(final_value)`.
|
|
294
|
+
- [#33](https://github.com/serradura/kind/pull/33) - Add `Kind::Dig.call` utility. Same behavior as Ruby's `dig` (`Hash`, `Array`, `Struct`, `OpenStruct`) but returns `nil` instead of raising when a step cannot be digged.
|
|
601
295
|
|
|
602
|
-
|
|
296
|
+
## [3.0.1] - 2020-06-25
|
|
297
|
+
### Fixed
|
|
298
|
+
- [#32](https://github.com/serradura/kind/pull/32) - Fix the `Kind::Maybe::None#try` methods.
|
|
603
299
|
|
|
604
|
-
|
|
300
|
+
## [3.0.0] - 2020-06-25
|
|
301
|
+
### Changed
|
|
302
|
+
- [#31](https://github.com/serradura/kind/pull/31) - **BREAKING:** Change the behavior of `Kind::Maybe::Result#try()`. It now mirrors `public_send` semantics — returning `nil` when the receiver does not respond to the method — and wraps the result in `Some` when the value isn't `nil` / `Kind::Undefined`.
|
|
605
303
|
```ruby
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
StatusLabel === 'ok' # true
|
|
610
|
-
StatusLabel === true # false
|
|
304
|
+
Kind::Maybe['foo'].try(:upcase).value # "FOO"
|
|
305
|
+
Kind::Maybe[{}].try(:fetch, :number, 0).value # 0
|
|
306
|
+
Kind::Optional[' Rodrigo '].try(:strip).value_or('') # "Rodrigo"
|
|
611
307
|
```
|
|
612
308
|
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
# Kind.of(<Type>, value, label:)
|
|
616
|
-
class Person
|
|
617
|
-
attr_reader :name
|
|
618
|
-
|
|
619
|
-
def initialize(name:)
|
|
620
|
-
@name = Kind.of(String, name, label: 'Person#name')
|
|
621
|
-
end
|
|
622
|
-
end
|
|
623
|
-
|
|
624
|
-
Person.new(name: 'Rodrigo') # #<Person:0x0000... @name="Rodrigo">
|
|
625
|
-
Person.new(name: :ok) # Kind::Error (Person#name: :ok expected to be a kind of String)
|
|
626
|
-
|
|
627
|
-
# Kind<Type>[value, label:]
|
|
628
|
-
class User
|
|
629
|
-
attr_reader :name
|
|
630
|
-
|
|
631
|
-
def initialize(name:)
|
|
632
|
-
@name = Kind::String[name, label: 'User#name']
|
|
633
|
-
end
|
|
634
|
-
end
|
|
635
|
-
|
|
636
|
-
User.new(name: 'Rodrigo') # #<User:0x0000... @name="Rodrigo">
|
|
637
|
-
User.new(name: :ok) # Kind::Error (User#name: :ok expected to be a kind of String)
|
|
638
|
-
```
|
|
309
|
+
### Added
|
|
310
|
+
- [#31](https://github.com/serradura/kind/pull/31) - Add `Kind::Maybe::Result#try!()` — like `#try`, but raises when the wrapped value does not respond to the method.
|
|
639
311
|
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
* `Kind.of_class?`
|
|
645
|
-
* `Kind.of_module?`
|
|
646
|
-
* `Kind.of_module_or_class`
|
|
647
|
-
* `Kind.respond_to`
|
|
648
|
-
* `Kind.respond_to?`
|
|
649
|
-
* `Kind.value`
|
|
650
|
-
* `Kind::Error`
|
|
651
|
-
* `Kind::Undefined`
|
|
652
|
-
|
|
653
|
-
* [#46](https://github.com/serradura/kind/pull/46) - Improve `Kind::Maybe`.
|
|
654
|
-
* Improve the `#inspect` output.
|
|
655
|
-
* Make `Kind::Maybe.{new,[],wrap}` return `None` if they receive an exception instance.
|
|
656
|
-
* Add `#accept` as an alias of `#check` method.
|
|
657
|
-
* Add `#reject` as the reverse of the methods `#check` and `#accept`.
|
|
658
|
-
* Allow the methods `#map`, `#map!`, `#then`, `#then!`, `#check`, `#accept`, `#reject` to receive one symbol as an argument, it will be used to perform the correspondent method in the `Maybe` value, so if the object responds to the expected method a `Some` will be returned.
|
|
659
|
-
* Add `Kind::Maybe#on`, this method allows you to use a block where will be possible to define a `Some` or `None` handling. The output of the matched result (some or none) will be the block's output.
|
|
660
|
-
```ruby
|
|
661
|
-
# Kind::Maybe#accept (an alias of Kind::Maybe#check)
|
|
662
|
-
Kind::Maybe[1].accept(&:odd?) # #<Kind::Some value=1>
|
|
663
|
-
Kind::Maybe[1].accept(&:even?) # #<Kind::None value=nil>
|
|
312
|
+
## [2.3.0] - 2020-06-24
|
|
313
|
+
### Added
|
|
314
|
+
- [#30](https://github.com/serradura/kind/pull/30) - Add `Kind::Maybe.wrap()` as an alias for `Kind::Maybe.new()`.
|
|
315
|
+
- [#30](https://github.com/serradura/kind/pull/30) - Add `Kind::Maybe::Typed` and the helpers `Kind::Maybe()` / `Kind::Optional()` for typed monads. They return `Some` only if the value has the expected kind.
|
|
664
316
|
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
317
|
+
## [2.2.0] - 2020-06-23
|
|
318
|
+
### Changed
|
|
319
|
+
- [#29](https://github.com/serradura/kind/pull/29) - Invert the comparison with `Kind::Undefined` to avoid unexpected callbacks (e.g. `ActiveRecord::AssociationRelation#==` always performing a query).
|
|
668
320
|
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
321
|
+
## [2.1.0] - 2020-05-12
|
|
322
|
+
### Added
|
|
323
|
+
- [#28](https://github.com/serradura/kind/pull/28) - Allow passing multiple arguments to `Kind.of.<Type>.instance?(*args)` and `Kind.of.<Type>?(*args)`.
|
|
324
|
+
- [#28](https://github.com/serradura/kind/pull/28) - Add `Kind::Some()` and `Kind::None()` helpers.
|
|
325
|
+
- [#28](https://github.com/serradura/kind/pull/28) - Add `Kind.of?(<Type>, *args)` to check if one or many values have the expected kind. With a single `<Type>` argument it returns a lambda usable as a block.
|
|
672
326
|
|
|
673
|
-
|
|
674
|
-
|
|
327
|
+
### Changed
|
|
328
|
+
- [#28](https://github.com/serradura/kind/pull/28) - **BREAKING:** `Kind.of.<Type>.to_proc` now behaves like `Kind.of.<Type>.instance(value)` (returns the value or raises `Kind::Error`). For the predicate behavior, use the new `Kind.of.<Type>?` instead.
|
|
675
329
|
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
result.some { 1 }
|
|
680
|
-
end
|
|
330
|
+
## [2.0.0] - 2020-05-07
|
|
331
|
+
### Added
|
|
332
|
+
- [#24](https://github.com/serradura/kind/pull/24) - Improve `kind: { is: }` validation to check class/module inheritance.
|
|
681
333
|
|
|
682
|
-
|
|
683
|
-
|
|
334
|
+
### Changed
|
|
335
|
+
- [#24](https://github.com/serradura/kind/pull/24) - **BREAKING:** `Kind.{of,is}.Callable` now only checks that the given object `respond_to?(:call)`.
|
|
684
336
|
|
|
685
|
-
|
|
337
|
+
### Removed
|
|
338
|
+
- [#24](https://github.com/serradura/kind/pull/24) - Remove `kind: { is_a: }` from `Kind::Validator`.
|
|
339
|
+
- [#24](https://github.com/serradura/kind/pull/24) - Remove `kind: { klass: }` from `Kind::Validator`.
|
|
686
340
|
|
|
687
|
-
|
|
341
|
+
## [1.9.0] - 2020-05-06
|
|
342
|
+
### Added
|
|
343
|
+
- [#23](https://github.com/serradura/kind/pull/23) - Add `Kind.of.<Type>.to_proc` as an alias for `Kind.of.<Type>.instance?`.
|
|
344
|
+
- [#23](https://github.com/serradura/kind/pull/23) - Add `Kind::Validator` (`ActiveModel` validator) as an alternative to [`type_validator`](https://github.com/serradura/type_validator).
|
|
688
345
|
```ruby
|
|
689
|
-
require 'kind/
|
|
690
|
-
|
|
691
|
-
# Use the methods Kind::Left() or Kind::Right() to create either monads
|
|
692
|
-
Kind::Left(0) # #<Kind::Left value=0>
|
|
693
|
-
Kind::Right(1) # #<Kind::Right value=1>
|
|
694
|
-
|
|
695
|
-
# The Kind::Either.new() or Kind::Either[] also creates a Kind::Right monad
|
|
696
|
-
Kind::Either.new(2) # #<Kind::Right value=2>
|
|
697
|
-
Kind::Either[3] # #<Kind::Right value=3>
|
|
698
|
-
|
|
699
|
-
# An Either has methods that allow you to know what kind it is.
|
|
700
|
-
monad = Kind::Right(1)
|
|
701
|
-
monad.right? # true
|
|
702
|
-
monad.left? # false
|
|
703
|
-
|
|
704
|
-
# This monad allows you to chain a sequence of operations that will continue while the output
|
|
705
|
-
# of each step is a Right monad. So, if some step return a Left, all of the next steps will be avoided.
|
|
706
|
-
# Let's see an example of how you can use the method #map to define a sequence of operations.
|
|
707
|
-
|
|
708
|
-
def do_some_calculation(arg)
|
|
709
|
-
Kind::Right(arg)
|
|
710
|
-
.map { |value| Kind::Numeric?(value) ? Kind::Right(value + 2) : Kind::Left('value must be numeric') }
|
|
711
|
-
.map { |value| value.odd? ? Kind::Right(value) : Kind::Left('value can\'t be even') }
|
|
712
|
-
.map { |value| Kind::Right(value * 3) }
|
|
713
|
-
end
|
|
714
|
-
|
|
715
|
-
do_some_calculation('1') # #<Kind::Left value="value must be numeric">
|
|
716
|
-
do_some_calculation(2) # #<Kind::Left value="value can't be even">
|
|
717
|
-
do_some_calculation(1) # #<Kind::Right value=9>
|
|
718
|
-
|
|
719
|
-
# You can use procs/lambdas as an alternative of blocks
|
|
720
|
-
Add = ->(a, b) do
|
|
721
|
-
return Kind::Right(a + b) if Kind::Numeric?(a, b)
|
|
722
|
-
|
|
723
|
-
Kind::Left('the arguments must be numerics')
|
|
724
|
-
end
|
|
725
|
-
|
|
726
|
-
Double = ->(number) do
|
|
727
|
-
return Kind::Right(number * 2) if Kind::Numeric?(number)
|
|
728
|
-
|
|
729
|
-
Kind::Left('the argument must be numeric')
|
|
730
|
-
end
|
|
731
|
-
|
|
732
|
-
AsString = ->(value) { Kind::Right(value.to_s) }
|
|
733
|
-
|
|
734
|
-
Add.(1, 2).map(&Double).map(&Double) # #<Kind::Right value=12>
|
|
735
|
-
Add.(1, 2).map(&AsString).map(&Double) # #<Kind::Left value="the argument must be numeric">
|
|
736
|
-
|
|
737
|
-
# The method #then is an alias for #map
|
|
738
|
-
Add.(2, 2).then(&Double).then(&AsString) # #<Kind::Right value="8">
|
|
739
|
-
|
|
740
|
-
# An exception will occur when your block or lambda doesn't return a Kind::Either
|
|
741
|
-
Add.(2, 2).map { |number| number * 2 } # Kind::Monad::Error (8 expected to be a kind of Kind::Right | Kind::Left)
|
|
742
|
-
|
|
743
|
-
# The methods #map, #then auto handle StandardError exceptions,
|
|
744
|
-
# so Left will be returned when an exception occur.
|
|
745
|
-
Add.(0, 0).map { |number| Kind::Right(10 / number) } # #<Kind::Left value=#<ZeroDivisionError: divided by 0>>
|
|
746
|
-
|
|
747
|
-
# You can use #map! or #then! if you don't want this auto exception handling.
|
|
748
|
-
Add.(0, 0).map! { |number| Kind::Right(10 / number) } # ZeroDivisionError (divided by 0)
|
|
749
|
-
|
|
750
|
-
Add.(0, 0).then! { |number| Kind::Right(10 / number) } # ZeroDivisionError (divided by 0)
|
|
751
|
-
```
|
|
752
|
-
|
|
753
|
-
* [#46](https://github.com/serradura/kind/pull/46) - Add `Kind::Result` (an Either monad variation)
|
|
754
|
-
|
|
755
|
-
* [#46](https://github.com/serradura/kind/pull/46) - Add `Kind::Function`.
|
|
756
|
-
|
|
757
|
-
* [#46](https://github.com/serradura/kind/pull/46) - Add `Kind::Functional`.
|
|
758
|
-
|
|
759
|
-
* [#46](https://github.com/serradura/kind/pull/46) - Add `Kind::Try.presence` and improve the input/output handling of `Kind::Try.call`.
|
|
760
|
-
|
|
761
|
-
* [#46](https://github.com/serradura/kind/pull/46) - Add `Kind::Dig.presence` and improve the input/output handling of `Kind::Dig.call`.
|
|
762
|
-
|
|
763
|
-
* [#47](https://github.com/serradura/kind/pull/47) - Add `Kind.is!`
|
|
764
|
-
|
|
765
|
-
* [#47](https://github.com/serradura/kind/pull/47) - Create aliases to the methods `Kind.of` (`Kind.of!`) and `Kind.respond_to` (`Kind.respond_to!`)
|
|
766
|
-
|
|
767
|
-
* [#47](https://github.com/serradura/kind/pull/47) - Add `Kind[]` as the `Kind::Of()` substitute.
|
|
768
|
-
|
|
769
|
-
* [#49](https://github.com/serradura/kind/pull/49) - Add `Kind::Either::Methods` and `Kind::Result::Methods`
|
|
770
|
-
|
|
771
|
-
* [#49](https://github.com/serradura/kind/pull/49) - Add `Kind::Undefined.empty?`
|
|
772
|
-
|
|
773
|
-
* [#50](https://github.com/serradura/kind/pull/50) - Add `Kind::<Type>.empty_or` as an alias of `Kind::<Type>.value_or_empty`
|
|
774
|
-
|
|
775
|
-
* [#46](https://github.com/serradura/kind/pull/46), [#51](https://github.com/serradura/kind/pull/51) - Add `Kind::Functional::Action`.
|
|
776
|
-
|
|
777
|
-
* [#51](https://github.com/serradura/kind/pull/51) - Add `Kind::Action`.
|
|
778
|
-
|
|
779
|
-
* [#51](https://github.com/serradura/kind/pull/51) - Add `Kind::Maybe::ImmutableAttributes`.
|
|
780
|
-
|
|
781
|
-
* [#51](https://github.com/serradura/kind/pull/51) - Add `Kind::Maybe::Methods`.
|
|
782
|
-
|
|
783
|
-
* [#51](https://github.com/serradura/kind/pull/51) - Add `Kind::Enum`.
|
|
784
|
-
|
|
785
|
-
* [#51](https://github.com/serradura/kind/pull/51) - Modularize all the kind components. So now you can require only the modules/features that do you want, `kind/action` is the minimal requirement for all of them.
|
|
786
|
-
* `kind/action`
|
|
787
|
-
* `kind/dig`
|
|
788
|
-
* `kind/either`
|
|
789
|
-
* `kind/empty`
|
|
790
|
-
* `kind/enum`
|
|
791
|
-
* `kind/function`
|
|
792
|
-
* `kind/functional`
|
|
793
|
-
* `kind/functional/action`
|
|
794
|
-
* `kind/immutable_attributes`
|
|
795
|
-
* `kind/maybe`
|
|
796
|
-
* `kind/objects`
|
|
797
|
-
* `kind/presence`
|
|
798
|
-
* `kind/result`
|
|
799
|
-
* `kind/try`
|
|
800
|
-
* `kind/validator`
|
|
346
|
+
require 'kind/active_model/validation'
|
|
801
347
|
|
|
802
|
-
|
|
803
|
-
```ruby
|
|
804
|
-
class User
|
|
348
|
+
class Person
|
|
805
349
|
include ActiveModel::Validations
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
Bool = Object.new
|
|
812
|
-
def Bool.===(value)
|
|
813
|
-
value == true || value == false
|
|
814
|
-
end
|
|
815
|
-
def Bool.name; 'Bool'; end
|
|
816
|
-
|
|
817
|
-
validates :name, kind: FilledString
|
|
818
|
-
validates :bool, kind: Bool
|
|
819
|
-
|
|
820
|
-
def initialize(name:, bool:)
|
|
821
|
-
@name, @bool = name, bool
|
|
822
|
-
end
|
|
350
|
+
attr_reader :name, :age
|
|
351
|
+
validates :name, kind: { of: String }
|
|
352
|
+
validates :age, kind: { of: Integer }
|
|
353
|
+
def initialize(name:, age:); @name, @age = name, age; end
|
|
823
354
|
end
|
|
824
|
-
|
|
825
|
-
user = User.new(name: '', bool: 1)
|
|
826
|
-
|
|
827
|
-
user.valid? # true
|
|
828
|
-
user.errors[:name] # ['invalid kind']
|
|
829
|
-
user.errors[:bool] # ['must be a kind of Bool']
|
|
830
|
-
|
|
831
|
-
User.new(name: 'Serradura', bool: true).valid? # true
|
|
832
355
|
```
|
|
833
356
|
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
### Deprecated
|
|
837
|
-
|
|
838
|
-
* [#47](https://github.com/serradura/kind/pull/47) - Deprecate `Kind.is` and `Kind::Of()`.
|
|
839
|
-
|
|
840
|
-
* [#48](https://github.com/serradura/kind/pull/48) - Deprecate `Kind::Maybe()` and `Kind::Optional()`
|
|
841
|
-
|
|
842
|
-
### Changes
|
|
843
|
-
|
|
844
|
-
* [#48](https://github.com/serradura/kind/pull/48) - Rename `Kind::TypeChecker` to `Kind::Object` and `Kind::TypeChecker::Object` to `Kind::Object::Instance`.
|
|
845
|
-
|
|
846
|
-
[⬆️ Back to Top](#changelog-)
|
|
847
|
-
|
|
848
|
-
5.1.0 (2021-02-23)
|
|
849
|
-
------------------
|
|
850
|
-
|
|
357
|
+
## [1.8.0] - 2020-05-03
|
|
851
358
|
### Added
|
|
359
|
+
- [#22](https://github.com/serradura/kind/pull/22) - `Kind.of.<Type>.instance?` returns a lambda when called without an argument (block-friendly).
|
|
360
|
+
- [#22](https://github.com/serradura/kind/pull/22) - Add `.as_optional` / `.as_maybe` on type checkers (returns a typed `Maybe`; lambda when called without arguments).
|
|
852
361
|
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
* [#45](https://github.com/serradura/kind/pull/45) - `kind/active_model/validation` is deprecated; use `kind/validator` instead.
|
|
858
|
-
|
|
859
|
-
5.0.0 (2021-02-22)
|
|
860
|
-
------------------
|
|
362
|
+
## [1.7.0] - 2020-05-03
|
|
363
|
+
### Fixed
|
|
364
|
+
- [#20](https://github.com/serradura/kind/pull/20) - Fix the verification of modules using `Kind.is()`.
|
|
861
365
|
|
|
862
|
-
|
|
366
|
+
## [1.6.0] - 2020-04-17
|
|
367
|
+
### Added
|
|
368
|
+
- [#19](https://github.com/serradura/kind/pull/19) - Add aliases to perform strict type verification on registered type checkers: `Kind.of.<Type>[value, or: ...]` and `Kind.of.<Type>.instance(value, or: ...)`.
|
|
369
|
+
- [#19](https://github.com/serradura/kind/pull/19) - Add `.or_undefined` for any type checker (returns `Kind::Undefined` instead of raising).
|
|
370
|
+
- [#19](https://github.com/serradura/kind/pull/19) - Allow dynamic verification of types with `Kind.of(<Type>, value)` and dynamic checker creation with `Kind.of(<Type>)` (no registration required), exposing the full type-checker API (`[]`, `instance`, `instance?`, `class?`, `or_nil`, `or_undefined`).
|
|
371
|
+
- [#19](https://github.com/serradura/kind/pull/19) - Add new type checkers: `Kind::Of::Set`, `Kind::Of::Maybe`, `Kind::Of::Optional`.
|
|
372
|
+
- [#19](https://github.com/serradura/kind/pull/19) - Add `Kind::Empty` with constants for frozen empty values: `Kind::Empty::SET`, `Kind::Empty::HASH`, `Kind::Empty::ARRAY`, `Kind::Empty::STRING`. When the top-level `Empty` constant is undefined, it is aliased to `Kind::Empty`.
|
|
863
373
|
|
|
864
|
-
|
|
374
|
+
### Changed
|
|
375
|
+
- [#19](https://github.com/serradura/kind/pull/19) - Change the output of `Kind::Undefined.to_s` / `Kind::Undefined.inspect` from `"Undefined"` to `"Kind::Undefined"`.
|
|
865
376
|
|
|
866
|
-
|
|
377
|
+
## [1.5.0] - 2020-04-12
|
|
378
|
+
### Added
|
|
379
|
+
- [#18](https://github.com/serradura/kind/pull/18) - Refactor `Kind::Maybe`.
|
|
380
|
+
- [#18](https://github.com/serradura/kind/pull/18) - Add `Kind::Maybe::Value` module with `.some?` / `.none?` predicates for raw values.
|
|
867
381
|
|
|
868
|
-
|
|
382
|
+
## [1.4.0] - 2020-04-12
|
|
383
|
+
### Changed
|
|
384
|
+
- [#17](https://github.com/serradura/kind/pull/17) - Rename `Kind::Optional` to `Kind::Maybe`. `Kind::Optional` remains available as an alias.
|
|
869
385
|
|
|
870
|
-
|
|
386
|
+
## [1.3.0] - 2020-04-12
|
|
387
|
+
### Added
|
|
388
|
+
- [#16](https://github.com/serradura/kind/pull/16) - Add the special type checkers `Kind::Of::Callable` (object responds to `:call`) and `Kind::Is::Callable` (class whose `public_instance_methods.include?(:call)`).
|
|
871
389
|
|
|
872
|
-
|
|
390
|
+
## [1.2.0] - 2020-04-12
|
|
391
|
+
### Added
|
|
392
|
+
- [#15](https://github.com/serradura/kind/pull/15) - Add `Kind::Optional`, the Maybe monad: encapsulates an optional value (`Some` / `None`) and short-circuits chained operations when a `nil` / `Kind::Undefined` is produced. Exposes `#map`/`#then`, `#value`, `#some?`/`#none?`, `#value_or(default | { ... })`, `#try(method, *args)`, and the `Kind::Optional[value]` constructor.
|
|
393
|
+
- [#15](https://github.com/serradura/kind/pull/15) - Add `Kind::Undefined.to_s`, `Kind::Undefined.inspect`, `Kind::Undefined.clone`, `Kind::Undefined.dup`, and `Kind::Undefined.default(value, fallback)`.
|
|
873
394
|
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
* [#44](https://github.com/serradura/kind/pull/44) - Remove the invocation of `Kind.is` without arguments.
|
|
879
|
-
|
|
880
|
-
* [#44](https://github.com/serradura/kind/pull/44) - Remove the invocation of `Kind.of` without arguments.
|
|
881
|
-
|
|
882
|
-
* [#44](https://github.com/serradura/kind/pull/44) - Remove the invocation of `Kind.of` with a single argument (the kind).
|
|
883
|
-
|
|
884
|
-
4.1.0 (2021-02-22)
|
|
885
|
-
------------------
|
|
886
|
-
|
|
887
|
-
### Added
|
|
888
|
-
|
|
889
|
-
* [#43](https://github.com/serradura/kind/pull/43) - Make `Kind::Maybe::Typed` verify the kind of the value via `===`, because of this, now is possible to use type checkers in typed Maybes.
|
|
890
|
-
```ruby
|
|
891
|
-
Kind::Maybe(Kind::Boolean).wrap(nil).value_or(false) # false
|
|
892
|
-
|
|
893
|
-
Kind::Maybe(Kind::Boolean).wrap(true).value_or(false) # true
|
|
894
|
-
```
|
|
895
|
-
|
|
896
|
-
* [#43](https://github.com/serradura/kind/pull/43) - Add `Kind::<Type>.maybe` and `Kind::<Type>.optional`. This method returns a typed Maybe with the expected kind when it is invoked without arguments. But, if it receives arguments, it will behave like the `Kind::Maybe.wrap` method. e.g.
|
|
897
|
-
```ruby
|
|
898
|
-
Kind::Integer.maybe #<Kind::Maybe::Typed:0x0000... @kind=Kind::Integer>
|
|
899
|
-
|
|
900
|
-
Kind::Integer.maybe(0).some? # true
|
|
901
|
-
Kind::Integer.maybe { 1 }.some? # true
|
|
902
|
-
Kind::Integer.maybe(2) { |n| n * 2 }.some? # true
|
|
903
|
-
|
|
904
|
-
Kind::Integer.maybe { 2 / 0 }.none? # true
|
|
905
|
-
Kind::Integer.maybe(2) { |n| n / 0 }.none? # true
|
|
906
|
-
Kind::Integer.maybe('2') { |n| n * n }.none? # true
|
|
907
|
-
```
|
|
908
|
-
|
|
909
|
-
* [#43](https://github.com/serradura/kind/pull/43) - Make the `:respond_to` kind validation verify by one or multiple methods. e.g.
|
|
910
|
-
```ruby
|
|
911
|
-
validates :params, kind: { respond_to: [:[], :values_at] }
|
|
912
|
-
```
|
|
913
|
-
|
|
914
|
-
* [#43](https://github.com/serradura/kind/pull/43) - Make the `:of` kind validation verify the expected value kind using `===`, because of this, now is possible to use type checkers as expected kinds. e.g.
|
|
915
|
-
```ruby
|
|
916
|
-
validates :alive, kind: Kind::Boolean
|
|
917
|
-
```
|
|
918
|
-
|
|
919
|
-
4.0.0 (2021-02-22)
|
|
920
|
-
------------------
|
|
921
|
-
|
|
922
|
-
### Added
|
|
923
|
-
|
|
924
|
-
* [#40](https://github.com/serradura/kind/pull/40) - Add `Kind.of_class?` to verify if a given value is a `Class`.
|
|
925
|
-
|
|
926
|
-
* [#40](https://github.com/serradura/kind/pull/40) - Add `Kind.of_module?` to verify if a given value is a `Module`.
|
|
927
|
-
|
|
928
|
-
* [#40](https://github.com/serradura/kind/pull/40) - Add `Kind.of_module_or_class()` that returns the given value if it is a module or a class. If not, a `Kind::Error` will be raised.
|
|
929
|
-
```ruby
|
|
930
|
-
Kind.of_module_or_class(String) # String
|
|
931
|
-
Kind.of_module_or_class(1) # Kind::Error (1 expected to be a kind of Module/Class)
|
|
932
|
-
```
|
|
933
|
-
|
|
934
|
-
* [#40](https://github.com/serradura/kind/pull/40) - Add `Kind.respond_to(object, *method_names)`, this method returns the given object if it responds to all of the method names. But if the object does not respond to some of the expected methods, an error will be raised.
|
|
935
|
-
```ruby
|
|
936
|
-
Kind.respond_to('', :upcase) # ""
|
|
937
|
-
Kind.respond_to('', :upcase, :strip) # ""
|
|
938
|
-
|
|
939
|
-
Kind.respond_to(1, :upcase) # expected 1 to respond to :upcase
|
|
940
|
-
Kind.respond_to(2, :to_s, :upcase) # expected 2 to respond to :upcase
|
|
941
|
-
```
|
|
942
|
-
|
|
943
|
-
* [#40](https://github.com/serradura/kind/pull/40) - Add `Kind::Try.call()`. This method invokes a public method with or without arguments like public_send does, except that if the receiver does not respond to it the call returns `nil` rather than raising an exception.
|
|
944
|
-
```ruby
|
|
945
|
-
Kind::Try.(' foo ', :strip) # "foo"
|
|
946
|
-
Kind::Try.({a: 1}, :[], :a) # 1
|
|
947
|
-
Kind::Try.({a: 1}, :[], :b) # nil
|
|
948
|
-
Kind::Try.({a: 1}, :fetch, :b, 2) # 2
|
|
949
|
-
|
|
950
|
-
Kind::Try.(:symbol, :strip) # nil
|
|
951
|
-
Kind::Try.(:symbol, :fetch, :b, 2) # nil
|
|
952
|
-
|
|
953
|
-
# It raises an exception if the method name isn't a string or a symbol
|
|
954
|
-
Kind::Try.({a: 1}, 1, :a) # TypeError (1 is not a symbol nor a string)
|
|
955
|
-
```
|
|
956
|
-
|
|
957
|
-
* [#40](https://github.com/serradura/kind/pull/40), [#41](https://github.com/serradura/kind/pull/40) - Add `Kind::DEPRECATION` module to be used to warn about all of the deprecations. You can use the `DISABLE_KIND_DEPRECATION` environment variable to disable the warning messages.
|
|
958
|
-
|
|
959
|
-
* [#40](https://github.com/serradura/kind/pull/40), [#41](https://github.com/serradura/kind/pull/40) - Add type checkers modules that have several utility methods related to type checking/handling.
|
|
960
|
-
```ruby
|
|
961
|
-
# All of the methods used with the Kind::String can be used with any other type checker module.
|
|
962
|
-
|
|
963
|
-
# Kind::<Type>.name
|
|
964
|
-
# Kind::<Type>.kind
|
|
965
|
-
# The type checker can return its kind and its name
|
|
966
|
-
Kind::String.name # "String"
|
|
967
|
-
Kind::String.kind # ::String
|
|
968
|
-
|
|
969
|
-
# Kind::<Type>.===
|
|
970
|
-
# Can check if a given value is an instance of its kind.
|
|
971
|
-
Kind::String === 'foo' # true
|
|
972
|
-
Kind::String === :foo # false
|
|
973
|
-
|
|
974
|
-
# Kind::<Type>.value?(value)
|
|
975
|
-
# Can check if a given value is an instance of its kind.
|
|
976
|
-
Kind::String.value?('foo') # true
|
|
977
|
-
Kind::String.value?(:foo) # false
|
|
978
|
-
|
|
979
|
-
# If it doesn't receive an argument, a lambda will be returned and it will know how to do the type verification.
|
|
980
|
-
[1, 2, 'foo', 3, 'Bar'].select?(&Kind::String.value?) # ["foo", "bar"]
|
|
981
|
-
|
|
982
|
-
# Kind::<Type>.or_nil(value)
|
|
983
|
-
# Can return nil if the given value isn't an instance of its kind
|
|
984
|
-
Kind::String.or_nil('foo') # "foo"
|
|
985
|
-
Kind::String.or_nil(:foo) # nil
|
|
986
|
-
|
|
987
|
-
# Kind::<Type>.or_undefined(value)
|
|
988
|
-
# Can return Kind::Undefined if the given value isn't an instance of its kind
|
|
989
|
-
Kind::String.or_undefined('foo') # "foo"
|
|
990
|
-
Kind::String.or_undefined(:foo) # Kind::Undefined
|
|
991
|
-
|
|
992
|
-
# Kind::<Type>.or(fallback, value)
|
|
993
|
-
# Can return a fallback if the given value isn't an instance of its kind
|
|
994
|
-
Kind::String.or(nil, 'foo') # "foo"
|
|
995
|
-
Kind::String.or(nil, :foo) # nil
|
|
996
|
-
|
|
997
|
-
# If it doesn't receive a second argument (the value), it will return a callable that knows how to expose an instance of the expected type or a fallback if the given value is wrong.
|
|
998
|
-
[1, 2, 'foo', 3, 'Bar'].map(&Kind::String.or('')) # ["", "", "foo", "", "Bar"]
|
|
999
|
-
[1, 2, 'foo', 3, 'Bar'].map(&Kind::String.or(nil)) # [nil, nil, "foo", nil, "Bar"]
|
|
1000
|
-
|
|
1001
|
-
# An error will be raised if the fallback didn't have the expected kind or if not nil / Kind::Undefined.
|
|
1002
|
-
[1, 2, 'foo', 3, 'Bar'].map(&Kind::String.or(:foo)) # Kind::Error (:foo expected to be a kind of String)
|
|
1003
|
-
|
|
1004
|
-
# Kind::<Type>[value]
|
|
1005
|
-
# Will raise Kind::Error if the given value isn't an instance of the expected kind
|
|
1006
|
-
Kind::String['foo'] # "foo"
|
|
1007
|
-
Kind::String[:foo ] # Kind::Error (:foo expected to be a kind of String)
|
|
1008
|
-
```
|
|
1009
|
-
* List of all type checkers:
|
|
1010
|
-
* **Core:**
|
|
1011
|
-
* `Kind::Array`
|
|
1012
|
-
* `Kind::Class`
|
|
1013
|
-
* `Kind::Comparable`
|
|
1014
|
-
* `Kind::Enumerable`
|
|
1015
|
-
* `Kind::Enumerator`
|
|
1016
|
-
* `Kind::File`
|
|
1017
|
-
* `Kind::Float`
|
|
1018
|
-
* `Kind::Hash`
|
|
1019
|
-
* `Kind::Integer`
|
|
1020
|
-
* `Kind::IO`
|
|
1021
|
-
* `Kind::Method`
|
|
1022
|
-
* `Kind::Module`
|
|
1023
|
-
* `Kind::Numeric`
|
|
1024
|
-
* `Kind::Proc`
|
|
1025
|
-
* `Kind::Queue`
|
|
1026
|
-
* `Kind::Range`
|
|
1027
|
-
* `Kind::Regexp`
|
|
1028
|
-
* `Kind::String`
|
|
1029
|
-
* `Kind::Struct`
|
|
1030
|
-
* `Kind::Symbol`
|
|
1031
|
-
* `Kind::Time`
|
|
1032
|
-
* **Custom:**
|
|
1033
|
-
* `Kind::Boolean`
|
|
1034
|
-
* `Kind::Callable`
|
|
1035
|
-
* `Kind::Lambda`
|
|
1036
|
-
* **Stdlib:**
|
|
1037
|
-
* `Kind::OpenStruct`
|
|
1038
|
-
* `Kind::Set`
|
|
1039
|
-
|
|
1040
|
-
* [#40](https://github.com/serradura/kind/pull/40) - Add `Kind::Of()`. This method allows the creation of type checkers in runtime. To do this, the kind must respond to the method `.===`, and if doesn't have the `.name` method (which needs to return a string), a hash must be provided with a filled `:name` property.
|
|
1041
|
-
```ruby
|
|
1042
|
-
# Example using a class (an object which responds to .=== and has the .name method):
|
|
1043
|
-
# This object will have all of the default methods that a standard type checker (e.g: Kind::String) has.
|
|
1044
|
-
kind_of_string = Kind::Of(String)
|
|
1045
|
-
|
|
1046
|
-
kind_of_string[''] # ""
|
|
1047
|
-
kind_of_string[{}] # Kind::Error ({} expected to be a kind of String)
|
|
1048
|
-
|
|
1049
|
-
# Example using a lambda (an object which responds to .===) and a hash with the kind name.
|
|
1050
|
-
|
|
1051
|
-
PositiveInteger = Kind::Of(-> value { value.kind_of?(Integer) && value > 0 }, name: 'PositiveInteger')
|
|
1052
|
-
|
|
1053
|
-
# PositiveInteger.name
|
|
1054
|
-
# PositiveInteger.kind
|
|
1055
|
-
# The type checker can return its kind and its name
|
|
1056
|
-
PositiveInteger.name # "PositiveInteger"
|
|
1057
|
-
PositiveInteger.kind # #<Proc:0x0000.... >
|
|
1058
|
-
|
|
1059
|
-
# PositiveInteger.===
|
|
1060
|
-
# Can check if a given value is an instance of its kind.
|
|
1061
|
-
PositiveInteger === 1 # true
|
|
1062
|
-
PositiveInteger === 0 # false
|
|
1063
|
-
|
|
1064
|
-
# PositiveInteger.value?(value)
|
|
1065
|
-
# Can check if a given value is an instance of its kind.
|
|
1066
|
-
PositiveInteger.value?(1) # true
|
|
1067
|
-
PositiveInteger.value?(-1) # false
|
|
1068
|
-
|
|
1069
|
-
# If it doesn't receive an argument, a lambda will be returned and it will know how to do the type verification.
|
|
1070
|
-
[1, 2, 0, 3, -1].select?(&PositiveInteger.value?) # [1, 2, 3]
|
|
1071
|
-
|
|
1072
|
-
# PositiveInteger.or_nil(value)
|
|
1073
|
-
# Can return nil if the given value isn't an instance of its kind
|
|
1074
|
-
PositiveInteger.or_nil(1) # 1
|
|
1075
|
-
PositiveInteger.or_nil(0) # nil
|
|
1076
|
-
|
|
1077
|
-
# PositiveInteger.or_undefined(value)
|
|
1078
|
-
# Can return Kind::Undefined if the given value isn't an instance of its kind
|
|
1079
|
-
PositiveInteger.or_undefined(2) # 2
|
|
1080
|
-
PositiveInteger.or_undefined(-1) # Kind::Undefined
|
|
1081
|
-
|
|
1082
|
-
# PositiveInteger.or(fallback, value)
|
|
1083
|
-
# Can return a fallback if the given value isn't an instance of its kind
|
|
1084
|
-
PositiveInteger.or(nil, 1) # 1
|
|
1085
|
-
PositiveInteger.or(nil, 0) # nil
|
|
1086
|
-
|
|
1087
|
-
# If it doesn't receive a second argument (the value), it will return a callable that knows how to expose an instance of the expected type or a fallback if the given value is wrong.
|
|
1088
|
-
[1, 2, 0, 3, -1].map(&PositiveInteger.or(1)) # [1, 2, 1, 3, 1]
|
|
1089
|
-
[1, 2, 0, 3, -1].map(&PositiveInteger.or(nil)) # [1, 2, nil, 3, nil]
|
|
1090
|
-
|
|
1091
|
-
# An error will be raised if the fallback didn't have the expected kind or if not nil / Kind::Undefined.
|
|
1092
|
-
[1, 2, 0, 3, -1].map(&PositiveInteger.or(:foo)) # Kind::Error (:foo expected to be a kind of PositiveInteger)
|
|
1093
|
-
|
|
1094
|
-
# PositiveInteger[value]
|
|
1095
|
-
# Will raise Kind::Error if the given value isn't an instance of the expected kind
|
|
1096
|
-
PositiveInteger[1] # 1
|
|
1097
|
-
PositiveInteger[:foo] # Kind::Error (:foo expected to be a kind of PositiveInteger)
|
|
1098
|
-
```
|
|
1099
|
-
* [#40](https://github.com/serradura/kind/pull/40), [#41](https://github.com/serradura/kind/pull/40) - Add type checkers methods.
|
|
1100
|
-
```ruby
|
|
1101
|
-
# All of the methods used with the Kind::String? can be used with any other type checker method.
|
|
1102
|
-
|
|
1103
|
-
# Kind::<Type>?(*values)
|
|
1104
|
-
# Can check if a given value (one or many) is an instance of its kind.
|
|
1105
|
-
Kind::String?('foo') # true
|
|
1106
|
-
Kind::String?('foo', 'bar') # true
|
|
1107
|
-
Kind::String?('foo', :bar) # false
|
|
1108
|
-
|
|
1109
|
-
# If it doesn't receive an argument, a lambda will be returned and it will know how to do the type verification.
|
|
1110
|
-
[1, 2, 'foo', 3, 'Bar'].select?(&Kind::String?) # ["foo", "bar"]
|
|
1111
|
-
```
|
|
1112
|
-
* List of all type checkers:
|
|
1113
|
-
* **Core:**
|
|
1114
|
-
* `Kind::Array?`
|
|
1115
|
-
* `Kind::Class?`
|
|
1116
|
-
* `Kind::Comparable?`
|
|
1117
|
-
* `Kind::Enumerable?`
|
|
1118
|
-
* `Kind::Enumerator?`
|
|
1119
|
-
* `Kind::File?`
|
|
1120
|
-
* `Kind::Float?`
|
|
1121
|
-
* `Kind::Hash?`
|
|
1122
|
-
* `Kind::Integer?`
|
|
1123
|
-
* `Kind::IO?`
|
|
1124
|
-
* `Kind::Method?`
|
|
1125
|
-
* `Kind::Module?`
|
|
1126
|
-
* `Kind::Numeric?`
|
|
1127
|
-
* `Kind::Proc?`
|
|
1128
|
-
* `Kind::Queue?`
|
|
1129
|
-
* `Kind::Range?`
|
|
1130
|
-
* `Kind::Regexp?`
|
|
1131
|
-
* `Kind::String?`
|
|
1132
|
-
* `Kind::Struct?`
|
|
1133
|
-
* `Kind::Symbol?`
|
|
1134
|
-
* `Kind::Time?`
|
|
1135
|
-
* **Custom:**
|
|
1136
|
-
* `Kind::Boolean?`
|
|
1137
|
-
* `Kind::Callable?`
|
|
1138
|
-
* `Kind::Lambda?`
|
|
1139
|
-
* **Stdlib:**
|
|
1140
|
-
* `Kind::OpenStruct?`
|
|
1141
|
-
* `Kind::Set?`
|
|
1142
|
-
|
|
1143
|
-
* [#41](https://github.com/serradura/kind/pull/41) - Make `Kind::Dig.call` extract values from regular objects.
|
|
1144
|
-
```ruby
|
|
1145
|
-
class Person
|
|
1146
|
-
attr_reader :name
|
|
1147
|
-
|
|
1148
|
-
def initialize(name)
|
|
1149
|
-
@name = name
|
|
1150
|
-
end
|
|
1151
|
-
end
|
|
1152
|
-
|
|
1153
|
-
person = Person.new('Rodrigo')
|
|
1154
|
-
|
|
1155
|
-
Kind::Dig.(person, [:name]) # "Rodrigo"
|
|
1156
|
-
|
|
1157
|
-
Kind::Dig.({people: [person]}, [:people, 0, :name]) # "Rodrigo"
|
|
1158
|
-
```
|
|
1159
|
-
|
|
1160
|
-
* [#41](https://github.com/serradura/kind/pull/41) - Add `Kind::Presence.call`. Returns the given value if it's present otherwise it will return `nil`.
|
|
1161
|
-
```ruby
|
|
1162
|
-
Kind::Presence.(true) # true
|
|
1163
|
-
Kind::Presence.('foo') # "foo"
|
|
1164
|
-
Kind::Presence.([1, 2]) # [1, 2]
|
|
1165
|
-
Kind::Presence.({a: 3}) # {a: 3}
|
|
1166
|
-
Kind::Presence.(Set.new([4])) # #<Set: {4}>
|
|
1167
|
-
|
|
1168
|
-
Kind::Presence.('') # nil
|
|
1169
|
-
Kind::Presence.(' ') # nil
|
|
1170
|
-
Kind::Presence.("\t\n\r") # nil
|
|
1171
|
-
Kind::Presence.("\u00a0") # nil
|
|
1172
|
-
|
|
1173
|
-
Kind::Presence.([]) # nil
|
|
1174
|
-
Kind::Presence.({}) # nil
|
|
1175
|
-
Kind::Presence.(Set.new) # nil
|
|
1176
|
-
|
|
1177
|
-
Kind::Presence.(nil) # nil
|
|
1178
|
-
Kind::Presence.(false) # nil
|
|
1179
|
-
|
|
1180
|
-
# nil will be returned if the given object responds to the method blank? and this method result is true.
|
|
1181
|
-
MyObject = Struct.new(:is_blank) do
|
|
1182
|
-
def blank?
|
|
1183
|
-
is_blank
|
|
1184
|
-
end
|
|
1185
|
-
end
|
|
1186
|
-
|
|
1187
|
-
my_object = MyObject.new
|
|
1188
|
-
|
|
1189
|
-
my_object.is_blank = true
|
|
1190
|
-
|
|
1191
|
-
Kind::Presence.(my_object) # nil
|
|
1192
|
-
|
|
1193
|
-
my_object.is_blank = false
|
|
1194
|
-
|
|
1195
|
-
Kind::Presence.(my_object) # #<struct MyObject is_blank=false>
|
|
1196
|
-
```
|
|
1197
|
-
|
|
1198
|
-
* [#41](https://github.com/serradura/kind/pull/41) - Add `Kind::Maybe#presence`, this method will return None if the wrapped value wasn't present.
|
|
1199
|
-
```ruby
|
|
1200
|
-
result1 = Kind::Maybe(Hash).wrap(foo: '').dig(:foo).presence
|
|
1201
|
-
result1.none? # true
|
|
1202
|
-
result1.value # nil
|
|
1203
|
-
|
|
1204
|
-
result2 = Kind::Maybe(Hash).wrap(foo: 'bar').dig(:foo).presence
|
|
1205
|
-
result2.none? # false
|
|
1206
|
-
result2.value # "bar"
|
|
1207
|
-
```
|
|
1208
|
-
|
|
1209
|
-
* [#41](https://github.com/serradura/kind/pull/41) - Make `Kind::Maybe#wrap` receive a block and intercept StandardError exceptions. And a None will be returned if some exception happening.
|
|
1210
|
-
```ruby
|
|
1211
|
-
Kind::Maybe.wrap { 2 / 0 } # #<Kind::Maybe::None:0x0000... @value=#<ZeroDivisionError: divided by 0>>
|
|
1212
|
-
|
|
1213
|
-
Kind::Maybe(Numeric).wrap(2) { |number| number / 0 } # #<Kind::Maybe::None:0x0000... @value=#<ZeroDivisionError: divided by 0>>
|
|
1214
|
-
```
|
|
1215
|
-
|
|
1216
|
-
* [#41](https://github.com/serradura/kind/pull/41) - Make `Kind::Maybe#map` intercept StandardError exceptions.
|
|
1217
|
-
* Now the `#map` and `#then` methods will intercept any StandardError and return None with the exception or their values.
|
|
1218
|
-
* Add `#map!` and `#then!` that allows the exception leak, so, the user must handle the exception by himself or use this method when he wants to see the error be raised.
|
|
1219
|
-
* If an exception (StandardError) is returned by the methods `#then`, `#map` it will be resolved as None.
|
|
1220
|
-
```ruby
|
|
1221
|
-
# Handling StandardError exceptions
|
|
1222
|
-
result1 = Kind::Maybe[2].map { |number| number / 0 }
|
|
1223
|
-
result1.none? # true
|
|
1224
|
-
result1.value # #<ZeroDivisionError: divided by 0>
|
|
1225
|
-
|
|
1226
|
-
result2 = Kind::Maybe[3].then { |number| number / 0 }
|
|
1227
|
-
result2.none? # true
|
|
1228
|
-
result2.value # #<ZeroDivisionError: divided by 0>
|
|
1229
|
-
|
|
1230
|
-
# Leaking StandardError exceptions
|
|
1231
|
-
Kind::Maybe[2].map! { |number| number / 0 } # ZeroDivisionError (divided by 0)
|
|
1232
|
-
|
|
1233
|
-
Kind::Maybe[2].then! { |number| number / 0 } # ZeroDivisionError (divided by 0)
|
|
1234
|
-
```
|
|
1235
|
-
|
|
1236
|
-
* [#41](https://github.com/serradura/kind/pull/41) - Add `Kind::TypeCheckers#value`. This method ensures that you will have a value of the expected kind. But, in the case of the given value be invalid, this method will require a default value (with the expected kind) to be returned.
|
|
1237
|
-
```ruby
|
|
1238
|
-
# Using built-in type checkers
|
|
1239
|
-
Kind::String.value(1, default: '') # ""
|
|
1240
|
-
Kind::String.value('1', default: '') # "1"
|
|
1241
|
-
|
|
1242
|
-
Kind::String.value('1', default: 1) # Kind::Error (1 expected to be a kind of String)
|
|
1243
|
-
|
|
1244
|
-
# Using custom type checkers
|
|
1245
|
-
PositiveInteger = Kind::Of(-> value { value.kind_of?(Integer) && value > 0 }, name: 'PositiveInteger')
|
|
1246
|
-
|
|
1247
|
-
PositiveInteger.value(0, default: 1) # 1
|
|
1248
|
-
PositiveInteger.value(2, default: 1) # 2
|
|
1249
|
-
|
|
1250
|
-
PositiveInteger.value(-1, default: 0) # Kind::Error (0 expected to be a kind of PositiveInteger)
|
|
1251
|
-
```
|
|
1252
|
-
|
|
1253
|
-
* [#41](https://github.com/serradura/kind/pull/41) - Add the method `value_or_empty` for some type checkers. This method is available for some type checkers (`Kind::Array`, `Kind::Hash`, `Kind::String`, `Kind::Set`), and it will return an empty frozen value if the given value hasn't the expected kind.
|
|
1254
|
-
```ruby
|
|
1255
|
-
Kind::Array.value_or_empty({}) # []
|
|
1256
|
-
Kind::Array.value_or_empty({}).frozen? # true
|
|
1257
|
-
```
|
|
1258
|
-
|
|
1259
|
-
* [#42](https://github.com/serradura/kind/pull/42) - Add the method `Kind.value`. This method ensures that you will have a value of the expected kind. But, in the case of the given value be invalid, this method will require a default value (with the expected kind) to be returned.
|
|
1260
|
-
```ruby
|
|
1261
|
-
Kind.value(String, '1', default: '') # "1"
|
|
1262
|
-
|
|
1263
|
-
Kind.value(String, 1, default: '') # ""
|
|
1264
|
-
|
|
1265
|
-
Kind.value(String, 1, default: 2) # Kind::Error (2 expected to be a kind of String)
|
|
1266
|
-
```
|
|
1267
|
-
|
|
1268
|
-
* [#42](https://github.com/serradura/kind/pull/42) - Add `Kind::Presence.to_proc`. This method allow you to make use of the `Kind::Presence` in methods that receive a block as an argument. e.g:
|
|
1269
|
-
```ruby
|
|
1270
|
-
['', [], {}, '1', [2]].map(&Kind::Presence) # [nil, nil, nil, "1", [2]]
|
|
1271
|
-
```
|
|
1272
|
-
|
|
1273
|
-
* [#42](https://github.com/serradura/kind/pull/42) - `Kind::Maybe(<Type>).{new,[],wrap}` Now, these methods know how to get the value of another Maybe monad.
|
|
1274
|
-
```ruby
|
|
1275
|
-
some_number = Kind::Some(2)
|
|
1276
|
-
|
|
1277
|
-
Kind::Maybe(Numeric)[some_number] # #<Kind::Maybe::Some:0x0000... @value=2>
|
|
1278
|
-
|
|
1279
|
-
Kind::Maybe(Numeric).new(some_number) # #<Kind::Maybe::Some:0x0000... @value=2>
|
|
1280
|
-
|
|
1281
|
-
Kind::Maybe(Numeric).wrap(some_number) # #<Kind::Maybe::Some:0x0000... @value=2>
|
|
1282
|
-
|
|
1283
|
-
Kind::Maybe(Numeric).wrap { some_number } # #<Kind::Maybe::Some:0x0000... @value=2>
|
|
1284
|
-
|
|
1285
|
-
Kind::Maybe(Numeric).wrap(some_number) { |number| number / 2 } # #<Kind::Maybe::Some:0x0000... @value=1>
|
|
1286
|
-
```
|
|
1287
|
-
|
|
1288
|
-
* [#42](https://github.com/serradura/kind/pull/42) - `Kind::Maybe(<Type>).wrap(arg) { |arg_value| }` if the block receives an argument, the typed Maybe monad will verify if the argument is from the expected kind.
|
|
1289
|
-
```ruby
|
|
1290
|
-
Kind::Maybe(Numeric).wrap('2') { |number| number / 0 } # #<Kind::Maybe::None:0x0000... @value=nil>
|
|
1291
|
-
|
|
1292
|
-
Kind::Maybe(Numeric).wrap(2) { |number| number / 0 } # #<Kind::Maybe::None:0x0000... @value=#<ZeroDivisionError: divided by 0>>
|
|
1293
|
-
```
|
|
1294
|
-
|
|
1295
|
-
* [#42](https://github.com/serradura/kind/pull/42) - Add `Kind::Maybe#check`. This method returns the current Some after verifies if the block output was truthy.
|
|
1296
|
-
```ruby
|
|
1297
|
-
person_name = ->(params) do
|
|
1298
|
-
Kind::Maybe(Hash)
|
|
1299
|
-
.wrap(params)
|
|
1300
|
-
.then { |hash| hash.values_at(:first_name, :last_name) }
|
|
1301
|
-
.then { |names| names.map(&Kind::Presence).tap(&:compact!) }
|
|
1302
|
-
.check { |names| names.size == 2 }
|
|
1303
|
-
.then { |(first_name, last_name)| "#{first_name} #{last_name}" }
|
|
1304
|
-
.value_or { 'John Doe' }
|
|
1305
|
-
end
|
|
1306
|
-
|
|
1307
|
-
person_name.('') # "John Doe"
|
|
1308
|
-
person_name.(nil) # "John Doe"
|
|
1309
|
-
person_name.(last_name: 'Serradura') # "John Doe"
|
|
1310
|
-
person_name.(first_name: 'Rodrigo') # "John Doe"
|
|
1311
|
-
|
|
1312
|
-
person_name.(first_name: 'Rodrigo', last_name: 'Serradura') # "Rodrigo Serradura"
|
|
1313
|
-
```
|
|
1314
|
-
|
|
1315
|
-
* [#42](https://github.com/serradura/kind/pull/42) - Add `Kind::Dig[]`. This method knows how to create a lambda that will know how to perform the dig strategy.
|
|
1316
|
-
```ruby
|
|
1317
|
-
results = [
|
|
1318
|
-
{ person: {} },
|
|
1319
|
-
{ person: { name: 'Foo Bar'} },
|
|
1320
|
-
{ person: { name: 'Rodrigo Serradura'} },
|
|
1321
|
-
].map(&Kind::Dig[:person, :name])
|
|
1322
|
-
|
|
1323
|
-
p results # [nil, "Foo Bar", "Rodrigo Serradura"],
|
|
1324
|
-
```
|
|
1325
|
-
|
|
1326
|
-
* [#42](https://github.com/serradura/kind/pull/42) - Add `Kind::Try[]`. This method knows how to create a lambda that will know how to perform the try strategy.
|
|
1327
|
-
```ruby
|
|
1328
|
-
results =
|
|
1329
|
-
[
|
|
1330
|
-
{},
|
|
1331
|
-
{name: 'Foo Bar'},
|
|
1332
|
-
{name: 'Rodrigo Serradura'},
|
|
1333
|
-
].map(&Kind::Try[:fetch, :name, 'John Doe'])
|
|
1334
|
-
|
|
1335
|
-
p results # ["John Doe", "Foo Bar", "Rodrigo Serradura"]
|
|
1336
|
-
```
|
|
1337
|
-
|
|
1338
|
-
### Deprecated
|
|
1339
|
-
|
|
1340
|
-
* [#40](https://github.com/serradura/kind/pull/40) - Deprecate `Kind::Is.call`
|
|
1341
|
-
|
|
1342
|
-
* [#40](https://github.com/serradura/kind/pull/40) - Deprecate `Kind::Of.call`
|
|
1343
|
-
|
|
1344
|
-
* [#40](https://github.com/serradura/kind/pull/40) - Deprecate `Kind::Types.add`.
|
|
1345
|
-
|
|
1346
|
-
* [#40](https://github.com/serradura/kind/pull/40) - Deprecate `Kind::Of::<Type>` and `Kind::Is::<Type>` modules.
|
|
1347
|
-
|
|
1348
|
-
* [#40](https://github.com/serradura/kind/pull/40) - Deprecate `Kind::Checker`, `Kind::Checker::Protocol`, `Kind::Checker::Factory`.
|
|
1349
|
-
|
|
1350
|
-
* [#40](https://github.com/serradura/kind/pull/40) - Deprecate the invocation of `Kind.is` without arguments.
|
|
1351
|
-
|
|
1352
|
-
* [#40](https://github.com/serradura/kind/pull/40) - Deprecate the invocation of `Kind.of` without arguments.
|
|
1353
|
-
|
|
1354
|
-
* [#40](https://github.com/serradura/kind/pull/40) - Deprecate the invocation of `Kind.of` with a single argument (the kind).
|
|
395
|
+
## [1.1.0] - 2020-04-09
|
|
396
|
+
### Added
|
|
397
|
+
- [#14](https://github.com/serradura/kind/pull/14) - Add `Kind::Undefined`, representing an undefined value distinct from `nil`.
|
|
1355
398
|
|
|
1356
399
|
### Fixed
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
[
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
### Added
|
|
1438
|
-
|
|
1439
|
-
* [#31](https://github.com/serradura/kind/pull/31) - Add `Kind::Maybe::Result#try!()` that have almost of the same behavior of `Kind::Maybe::Result#try()`, the difference is because it will raise an error when the monad value doesn't respond to the expected method.
|
|
1440
|
-
```ruby
|
|
1441
|
-
Kind::Maybe[{}].try(:upcase) # => #<Kind::Maybe::None:0x0000... @value=nil>
|
|
1442
|
-
|
|
1443
|
-
Kind::Maybe[{}].try!(:upcase) # => NoMethodError (undefined method `upcase' for {}:Hash)
|
|
1444
|
-
```
|
|
1445
|
-
|
|
1446
|
-
[⬆️ Back to Top](#changelog-)
|
|
1447
|
-
|
|
1448
|
-
2.3.0 (2020-06-24)
|
|
1449
|
-
------------------
|
|
1450
|
-
|
|
1451
|
-
### Added
|
|
1452
|
-
|
|
1453
|
-
* [#30](https://github.com/serradura/kind/pull/30) - Add `Kind::Maybe.wrap()` as an alias for `Kind::Maybe.new()`.
|
|
1454
|
-
|
|
1455
|
-
* [#30](https://github.com/serradura/kind/pull/30) - Add `Kind::Maybe::Typed` and the methods `Kind::Maybe()`, `Kind::Optional()` to create typed monads. It will return `Some` if the given value has the expected kind or `None` if it hasn't.
|
|
1456
|
-
```ruby
|
|
1457
|
-
Double = ->(arg) do
|
|
1458
|
-
Kind::Optional(Numeric)
|
|
1459
|
-
.wrap(arg)
|
|
1460
|
-
.then { |number| number * 2 }
|
|
1461
|
-
end
|
|
1462
|
-
```
|
|
1463
|
-
|
|
1464
|
-
[⬆️ Back to Top](#changelog-)
|
|
1465
|
-
|
|
1466
|
-
2.2.0 (2020-06-23)
|
|
1467
|
-
------------------
|
|
1468
|
-
|
|
1469
|
-
### Added
|
|
1470
|
-
|
|
1471
|
-
* [#29](https://github.com/serradura/kind/pull/29) - Improve the comparison of values with `Kind::Undefined`.
|
|
1472
|
-
- I've been using `Kind.of(ActiveRecord::Relation, some_ar_relation)` in one of my apps and I found an unexpected behavior, the relations were always been executed. The reason is `ActiveRecord::AssociationRelation#==` behavior, which always performs a query (`to_a`). So, to avoid this and other unexpected behaviors, I decided to invert the comparison with `Kind::Undefined` to ensure a regular equality checking.
|
|
1473
|
-
|
|
1474
|
-
[⬆️ Back to Top](#changelog-)
|
|
1475
|
-
|
|
1476
|
-
2.1.0 (2020-05-12)
|
|
1477
|
-
------------------
|
|
1478
|
-
|
|
1479
|
-
### Added
|
|
1480
|
-
|
|
1481
|
-
* [#28](https://github.com/serradura/kind/pull/28) - Allow passing multiple arguments to `Kind.of.<Type>.instance?(*args)`
|
|
1482
|
-
|
|
1483
|
-
* [#28](https://github.com/serradura/kind/pull/28) - Allow passing multiple arguments to `Kind.of.<Type>?(*args)`
|
|
1484
|
-
|
|
1485
|
-
* [#28](https://github.com/serradura/kind/pull/28) - Add `Kind::Some()` and `Kind::None()`. e.g:
|
|
1486
|
-
```ruby
|
|
1487
|
-
Double = ->(arg) do
|
|
1488
|
-
number = Kind::Of::Numeric.or_nil(arg)
|
|
1489
|
-
|
|
1490
|
-
Kind::Optional[number].then { |number| number * 2 }
|
|
1491
|
-
end
|
|
1492
|
-
|
|
1493
|
-
Add = -> params do
|
|
1494
|
-
a, b = Kind::Of::Hash(params, or: Empty::HASH).values_at(:a, :b)
|
|
1495
|
-
|
|
1496
|
-
return Kind::None unless Kind::Of::Numeric?(a, b)
|
|
1497
|
-
|
|
1498
|
-
Kind::Some(a + b)
|
|
1499
|
-
end
|
|
1500
|
-
|
|
1501
|
-
Kind::Optional[a: 1, b: 2].then(&Add).value_or(0) # 3
|
|
1502
|
-
|
|
1503
|
-
Add.({}).some? # false
|
|
1504
|
-
|
|
1505
|
-
Add.(a: 1, b: '2').some? # false
|
|
1506
|
-
|
|
1507
|
-
Add.(a: 2, b: 2).then(&Double).value # 8
|
|
1508
|
-
```
|
|
1509
|
-
|
|
1510
|
-
* [#28](https://github.com/serradura/kind/pull/28) - Add `Kind.of?(<Type>, *args)` to check if one or many values are the expected kind.
|
|
1511
|
-
```ruby
|
|
1512
|
-
Kind.of?(Numeric, 1, 2.0, 3) # true
|
|
1513
|
-
Kind.of?(Numeric, 1, '2', 3) # false
|
|
1514
|
-
```
|
|
1515
|
-
|
|
1516
|
-
* [#28](https://github.com/serradura/kind/pull/28) - Make the `Kind.of?(<Type>)` returns a lambda that knows how to do the type verification.
|
|
1517
|
-
```ruby
|
|
1518
|
-
[1, '2', 3].select(&Kind.of?(Numeric)) # [1, 3]
|
|
1519
|
-
```
|
|
1520
|
-
|
|
1521
|
-
### Breaking Changes
|
|
1522
|
-
|
|
1523
|
-
* [#28](https://github.com/serradura/kind/pull/28) - Make `Kind.of.<Type>.to_proc` have the same behavior of `Kind.of.<Type>.instance(value)` (returns the value if it has the expected kind or raise `Kind::Error` if it haven't). This change is because now we have a method to verify if the given value is an instance of the expected kind (`Kind.of.<Type>?`), and this new method has a `to_proc` behavior when is called without arguments.
|
|
1524
|
-
```ruby
|
|
1525
|
-
[1, 2, 3].map(&Kind::Of::Numeric) # [1, 2, 3]
|
|
1526
|
-
|
|
1527
|
-
[1, '2', 3].map(&Kind::Of::Numeric) # Kind::Error ("2" expected to be a kind of Numeric)
|
|
1528
|
-
|
|
1529
|
-
[1, '2', 3].select(&Kind::Of::Numeric?) # [1, 3]
|
|
1530
|
-
```
|
|
1531
|
-
|
|
1532
|
-
[⬆️ Back to Top](#changelog-)
|
|
1533
|
-
|
|
1534
|
-
2.0.0 (2020-05-07)
|
|
1535
|
-
------------------
|
|
1536
|
-
|
|
1537
|
-
### Added
|
|
1538
|
-
|
|
1539
|
-
* [#24](https://github.com/serradura/kind/pull/24) - Improve the `kind: { is: }` validation to check the inheritance of *classes*/*modules*.
|
|
1540
|
-
|
|
1541
|
-
### Breaking Changes
|
|
1542
|
-
|
|
1543
|
-
* [#24](https://github.com/serradura/kind/pull/24) - Change the `Kind.{of,is}.Callable` verification. Now, it only verifies if the given object `respond_to?(:call)`.
|
|
1544
|
-
|
|
1545
|
-
### Removed
|
|
1546
|
-
|
|
1547
|
-
* [#24](https://github.com/serradura/kind/pull/24) - Remove `kind: { is_a: }` from `Kind::Validator`.
|
|
1548
|
-
* [#24](https://github.com/serradura/kind/pull/24) - Remove `kind: { klass: }` from `Kind::Validator`.
|
|
1549
|
-
|
|
1550
|
-
[⬆️ Back to Top](#changelog-)
|
|
1551
|
-
|
|
1552
|
-
1.9.0 (2020-05-06)
|
|
1553
|
-
------------------
|
|
1554
|
-
|
|
1555
|
-
### Added
|
|
1556
|
-
|
|
1557
|
-
* [#23](https://github.com/serradura/kind/pull/23) - Add `Kind.of.<Type>.to_proc` as an alias for `Kind.of.<Type>.instance?`.
|
|
1558
|
-
```ruby
|
|
1559
|
-
collection = [
|
|
1560
|
-
{number: 1},
|
|
1561
|
-
'number 0',
|
|
1562
|
-
{number: 2},
|
|
1563
|
-
[0],
|
|
1564
|
-
]
|
|
1565
|
-
|
|
1566
|
-
collection
|
|
1567
|
-
.select(&Kind.of.Hash)
|
|
1568
|
-
.reduce(0) { |total, item| total + item[:number] }
|
|
1569
|
-
```
|
|
1570
|
-
|
|
1571
|
-
* [#23](https://github.com/serradura/kind/pull/23) - Add `Kind::Validator` (`ActiveModel` validator) as an alternative (substitute) of [`type_validator`](https://github.com/serradura/type_validator).
|
|
1572
|
-
```ruby
|
|
1573
|
-
require 'kind/active_model/validation'
|
|
1574
|
-
|
|
1575
|
-
class Person
|
|
1576
|
-
include ActiveModel::Validations
|
|
1577
|
-
|
|
1578
|
-
attr_reader :name, :age
|
|
1579
|
-
|
|
1580
|
-
validates :name, kind: { of: String }
|
|
1581
|
-
validates :age, kind: { of: Integer }
|
|
1582
|
-
|
|
1583
|
-
def initialize(name:, age:)
|
|
1584
|
-
@name, @age = name, age
|
|
1585
|
-
end
|
|
1586
|
-
end
|
|
1587
|
-
|
|
1588
|
-
person = Person.new(name: 'John', age: '21')
|
|
1589
|
-
|
|
1590
|
-
person.valid? # false
|
|
1591
|
-
|
|
1592
|
-
person.errors[:age] # ['must be a kind of: Integer']
|
|
1593
|
-
```
|
|
1594
|
-
|
|
1595
|
-
[⬆️ Back to Top](#changelog-)
|
|
1596
|
-
|
|
1597
|
-
1.8.0 (2020-05-03)
|
|
1598
|
-
------------------
|
|
1599
|
-
|
|
1600
|
-
### Added
|
|
1601
|
-
|
|
1602
|
-
* [#22](https://github.com/serradura/kind/pull/22) - `Kind.of.<Type>.instance?`returns a lambda when called without an argument.
|
|
1603
|
-
```ruby
|
|
1604
|
-
collection = [
|
|
1605
|
-
{number: 1},
|
|
1606
|
-
'number 0',
|
|
1607
|
-
{number: 2},
|
|
1608
|
-
[0],
|
|
1609
|
-
]
|
|
1610
|
-
|
|
1611
|
-
collection
|
|
1612
|
-
.select(&Kind::Of::Hash.instance?)
|
|
1613
|
-
.reduce(0) { |total, item| total + item[:number] }
|
|
1614
|
-
```
|
|
1615
|
-
|
|
1616
|
-
* [#22](https://github.com/serradura/kind/pull/22) - Add new methods `.as_optional`, `.as_maybe` in the type checkers.
|
|
1617
|
-
```ruby
|
|
1618
|
-
def person_name(params)
|
|
1619
|
-
Kind::Of::Hash
|
|
1620
|
-
.as_optional(params)
|
|
1621
|
-
.map { |data| data.values_at(:first_name, :last_name).compact }
|
|
1622
|
-
.map { |first, last| "#{first} #{last}" if first && last }
|
|
1623
|
-
.value_or { 'John Doe' }
|
|
1624
|
-
end
|
|
1625
|
-
|
|
1626
|
-
person_name('') # "John Doe"
|
|
1627
|
-
person_name(nil) # "John Doe"
|
|
1628
|
-
person_name(first_name: 'Rodrigo') # "John Doe"
|
|
1629
|
-
person_name(last_name: 'Serradura') # "John Doe"
|
|
1630
|
-
person_name(first_name: 'Rodrigo', last_name: 'Serradura') # "Rodrigo Serradura"
|
|
1631
|
-
|
|
1632
|
-
# A lambda will be returned if these methods receive only one argument
|
|
1633
|
-
|
|
1634
|
-
collection = [
|
|
1635
|
-
{number: 1},
|
|
1636
|
-
'number 0',
|
|
1637
|
-
{number: 2},
|
|
1638
|
-
[0],
|
|
1639
|
-
]
|
|
1640
|
-
|
|
1641
|
-
collection
|
|
1642
|
-
.map(&Kind.of.Hash.as_optional)
|
|
1643
|
-
.select(&:some?)
|
|
1644
|
-
.reduce(0) { |total, item| total + item.value[:number] }
|
|
1645
|
-
```
|
|
1646
|
-
|
|
1647
|
-
[⬆️ Back to Top](#changelog-)
|
|
1648
|
-
|
|
1649
|
-
1.7.0 (2020-05-03)
|
|
1650
|
-
------------------
|
|
1651
|
-
|
|
1652
|
-
### Fixed
|
|
1653
|
-
|
|
1654
|
-
* [#20](https://github.com/serradura/kind/pull/20) - Fix the verification of modules using `Kind.is()`.
|
|
1655
|
-
|
|
1656
|
-
[⬆️ Back to Top](#changelog-)
|
|
1657
|
-
|
|
1658
|
-
1.6.0 (2020-04-17)
|
|
1659
|
-
------------------
|
|
1660
|
-
|
|
1661
|
-
### Added
|
|
1662
|
-
|
|
1663
|
-
* [#19](https://github.com/serradura/kind/pull/19) - Add aliases to perform the strict type verification (in registered type checkers).
|
|
1664
|
-
```ruby
|
|
1665
|
-
# Kind.of.<Type>[]
|
|
1666
|
-
|
|
1667
|
-
Kind.of.Hash[nil] # raise Kind::Error, "nil expected to be a kind of Hash"
|
|
1668
|
-
Kind.of.Hash[''] # raise Kind::Error, "'' expected to be a kind of Hash"
|
|
1669
|
-
Kind.of.Hash[a: 1] # {a: 1}
|
|
1670
|
-
Kind.of.Hash['', or: {}] # {}
|
|
1671
|
-
|
|
1672
|
-
# Kind.of.<Type>.instance()
|
|
1673
|
-
|
|
1674
|
-
Kind.of.Array.instance(nil) # raise Kind::Error, "nil expected to be a kind of Array"
|
|
1675
|
-
Kind.of.Array.instance('') # raise Kind::Error, "'' expected to be a kind of Array"
|
|
1676
|
-
Kind.of.Array.instance([]) # []
|
|
1677
|
-
Kind.of.Array.instance('', or: []) # []
|
|
1678
|
-
```
|
|
1679
|
-
|
|
1680
|
-
* [#19](https://github.com/serradura/kind/pull/19) - Add `.or_undefined` method for any type checker.
|
|
1681
|
-
```ruby
|
|
1682
|
-
Kind.of.String.or_undefined(nil) # Kind::Undefined
|
|
1683
|
-
Kind.of.String.or_undefined("something") # "something"
|
|
1684
|
-
```
|
|
1685
|
-
|
|
1686
|
-
* [#19](https://github.com/serradura/kind/pull/19) - Allow a dynamical verification of types.
|
|
1687
|
-
```ruby
|
|
1688
|
-
class User
|
|
1689
|
-
end
|
|
1690
|
-
|
|
1691
|
-
class AdminUser < User
|
|
1692
|
-
end
|
|
1693
|
-
|
|
1694
|
-
Kind.of(User, User.new) # #<User:0x0000...>
|
|
1695
|
-
Kind.of(User, {}) # Kind::Error ({} expected to be a kind of User)
|
|
1696
|
-
```
|
|
1697
|
-
|
|
1698
|
-
* [#19](https://github.com/serradura/kind/pull/19) - Allow the creation of type checkers dynamically (without register one).
|
|
1699
|
-
```ruby
|
|
1700
|
-
class User
|
|
1701
|
-
end
|
|
1702
|
-
|
|
1703
|
-
kind_of_user = Kind.of(User)
|
|
1704
|
-
|
|
1705
|
-
kind_of_user[{}] # Kind::Error ({} expected to be a kind of User)
|
|
1706
|
-
kind_of_user[User.new] # #<User:0x0000...>
|
|
1707
|
-
|
|
1708
|
-
kind_of_user.instance({}) # Kind::Error ({} expected to be a kind of User)
|
|
1709
|
-
kind_of_user.instance(User.new) # #<User:0x0000...>
|
|
1710
|
-
|
|
1711
|
-
kind_of_user.instance?({}) # false
|
|
1712
|
-
kind_of_user.instance?(User.new) # true
|
|
1713
|
-
|
|
1714
|
-
kind_of_user.class?(Hash) # false
|
|
1715
|
-
kind_of_user.class?(User) # true
|
|
1716
|
-
|
|
1717
|
-
kind_of_user.or_undefined({}) # Kind::Undefined
|
|
1718
|
-
kind_of_user.or_undefined(User.new) # #<User:0x0000...>
|
|
1719
|
-
```
|
|
1720
|
-
|
|
1721
|
-
* [#19](https://github.com/serradura/kind/pull/19) - Add a new type checkers.
|
|
1722
|
-
- `Kind::Of::Set`
|
|
1723
|
-
- `Kind::Of::Maybe`, `Kind::Of::Optional`
|
|
1724
|
-
|
|
1725
|
-
* [#19](https://github.com/serradura/kind/pull/19) - Add `Kind::Empty` with several constants having empty frozen objects.
|
|
1726
|
-
```ruby
|
|
1727
|
-
Kind::Empty::SET
|
|
1728
|
-
Kind::Empty::HASH
|
|
1729
|
-
Kind::Empty::ARRAY
|
|
1730
|
-
Kind::Empty::STRING
|
|
1731
|
-
|
|
1732
|
-
# If there isn't any constant named as Empty, the gem will use it to create an alias for Kind::Empty.
|
|
1733
|
-
|
|
1734
|
-
Empty::SET == Kind::Empty::SET
|
|
1735
|
-
Empty::HASH == Kind::Empty::HASH
|
|
1736
|
-
Empty::ARRAY == Kind::Empty::ARRAY
|
|
1737
|
-
Empty::STRING == Kind::Empty::STRING
|
|
1738
|
-
```
|
|
1739
|
-
|
|
1740
|
-
### Changes
|
|
1741
|
-
|
|
1742
|
-
* [#19](https://github.com/serradura/kind/pull/19) - Change the output of `Kind::Undefined.to_s`, `Kind::Undefined.inspect`, the previous output was `"Undefined"` and the new is `"Kind::Undefined"`
|
|
1743
|
-
```ruby
|
|
1744
|
-
Kind::Undefined.to_s # "Kind::Undefined"
|
|
1745
|
-
Kind::Undefined.inspect # "Kind::Undefined"
|
|
1746
|
-
```
|
|
1747
|
-
|
|
1748
|
-
[⬆️ Back to Top](#changelog-)
|
|
1749
|
-
|
|
1750
|
-
1.5.0 (2020-04-12)
|
|
1751
|
-
------------------
|
|
1752
|
-
|
|
1753
|
-
### Added
|
|
1754
|
-
|
|
1755
|
-
* [#18](https://github.com/serradura/kind/pull/18) - Refactor `Kind::Maybe`.
|
|
1756
|
-
|
|
1757
|
-
* [#18](https://github.com/serradura/kind/pull/18) - Add `Kind::Maybe::Value` module, that has the `.some?` and `.none?` methods. Available to check if the given value is `Some` or `None`.
|
|
1758
|
-
```ruby
|
|
1759
|
-
Kind::Maybe::Value.some?(1) # true
|
|
1760
|
-
Kind::Maybe::Value.some?(nil) # false
|
|
1761
|
-
Kind::Maybe::Value.some?(Kind::Undefined) # false
|
|
1762
|
-
|
|
1763
|
-
Kind::Maybe::Value.none?(1) # false
|
|
1764
|
-
Kind::Maybe::Value.none?(nil) # true
|
|
1765
|
-
Kind::Maybe::Value.none?(Kind::Undefined) # true
|
|
1766
|
-
```
|
|
1767
|
-
|
|
1768
|
-
[⬆️ Back to Top](#changelog-)
|
|
1769
|
-
|
|
1770
|
-
1.4.0 (2020-04-12)
|
|
1771
|
-
------------------
|
|
1772
|
-
|
|
1773
|
-
### Added
|
|
1774
|
-
|
|
1775
|
-
* [#17](https://github.com/serradura/kind/pull/17) - Transform `Kind::Optional` into `Kind::Maybe`. `Kind::Optional` still is available but as an alias for `Kind::Maybe`.
|
|
1776
|
-
|
|
1777
|
-
[⬆️ Back to Top](#changelog-)
|
|
1778
|
-
|
|
1779
|
-
1.3.0 (2020-04-12)
|
|
1780
|
-
------------------
|
|
1781
|
-
|
|
1782
|
-
### Added
|
|
1783
|
-
|
|
1784
|
-
* [#16](https://github.com/serradura/kind/pull/16) - Add a new special type checkers.
|
|
1785
|
-
- `Kind::Of::Callable` for check if the given object respond to `call`.
|
|
1786
|
-
- `Kind::Is::Callable` if the given value is a `class`, it will verifies if its `public_instance_methods.include?(:call)`.
|
|
1787
|
-
|
|
1788
|
-
[⬆️ Back to Top](#changelog-)
|
|
1789
|
-
|
|
1790
|
-
1.2.0 (2020-04-12)
|
|
1791
|
-
------------------
|
|
1792
|
-
|
|
1793
|
-
### Added
|
|
1794
|
-
|
|
1795
|
-
* [#15](https://github.com/serradura/kind/pull/15) - Add `Kind::Optional` the maybe monad, it encapsulates an optional value. A `Kind::Optional` either contains a value (represented as `Some`), or it is empty (represented as `None`). This data structure is helpful to transform a value through several operations, but if any of them returns `nil` or `Kind::Undefined` as its result, the next operations will be avoided.
|
|
1796
|
-
```ruby
|
|
1797
|
-
# Some value
|
|
1798
|
-
|
|
1799
|
-
optional =
|
|
1800
|
-
Kind::Optional.new(2)
|
|
1801
|
-
.map { |value| value * 2 }
|
|
1802
|
-
.map { |value| value * 2 }
|
|
1803
|
-
|
|
1804
|
-
puts optional.value # 8
|
|
1805
|
-
puts optional.some? # true
|
|
1806
|
-
puts optional.none? # false
|
|
1807
|
-
|
|
1808
|
-
puts optional.value_or(0) # 8
|
|
1809
|
-
puts optional.value_or { 0 } # 8
|
|
1810
|
-
|
|
1811
|
-
# None value
|
|
1812
|
-
|
|
1813
|
-
even_number = Kind::Optional.new(3).map { |n| n if n.even? }
|
|
1814
|
-
|
|
1815
|
-
even_number.none? # true
|
|
1816
|
-
|
|
1817
|
-
even_number.value_or(0) # 0
|
|
1818
|
-
|
|
1819
|
-
# Utility method
|
|
1820
|
-
|
|
1821
|
-
# Kind::Optional#try
|
|
1822
|
-
# You could use the `#try` method to perform a method of the wrapped object and return its value.
|
|
1823
|
-
|
|
1824
|
-
Kind::Optional.new(' Rodrigo ').try(:strip) # "Rodrigo"
|
|
1825
|
-
|
|
1826
|
-
# Method aliases
|
|
1827
|
-
|
|
1828
|
-
# Kind::Optional[] is an alias for Kind::Optional.new
|
|
1829
|
-
Kind::Optional[2].map { |n| n if n.even? }.value_or(0) # 2
|
|
1830
|
-
|
|
1831
|
-
# Kind::Optional::Result#then is an alias for Kind::Optional::Result#map
|
|
1832
|
-
Kind::Optional[1].then { |n| n if n.even? }.value_or(0) # 0
|
|
1833
|
-
```
|
|
1834
|
-
|
|
1835
|
-
* [#15](https://github.com/serradura/kind/pull/15) - Add new methods to `Kind::Undefined`.
|
|
1836
|
-
```ruby
|
|
1837
|
-
Kind::Undefined.to_s # 'Undefined'
|
|
1838
|
-
Kind::Undefined.inspect # 'Undefined'
|
|
1839
|
-
|
|
1840
|
-
Kind::Undefined.clone # #<Kind::Undefined:0x0000...>
|
|
1841
|
-
Kind::Undefined.dup # #<Kind::Undefined:0x0000...>
|
|
1842
|
-
|
|
1843
|
-
Kind::Undefined.clone == Kind::Undefined # true
|
|
1844
|
-
Kind::Undefined.clone === Kind::Undefined # true
|
|
1845
|
-
|
|
1846
|
-
Kind::Undefined.dup == Kind::Undefined # true
|
|
1847
|
-
Kind::Undefined.dup === Kind::Undefined # true
|
|
1848
|
-
|
|
1849
|
-
value = Kind::Undefined
|
|
1850
|
-
|
|
1851
|
-
Kind::Undefined.default(value, 1) # 1
|
|
1852
|
-
```
|
|
1853
|
-
|
|
1854
|
-
[⬆️ Back to Top](#changelog-)
|
|
1855
|
-
|
|
1856
|
-
1.1.0 (2020-04-09)
|
|
1857
|
-
------------------
|
|
1858
|
-
|
|
1859
|
-
### Added
|
|
1860
|
-
|
|
1861
|
-
* [#14](https://github.com/serradura/kind/pull/14) - Add `Kind::Undefined` representing an undefined value to contrast with `nil`.
|
|
1862
|
-
|
|
1863
|
-
### Fixed
|
|
1864
|
-
|
|
1865
|
-
* [#14](https://github.com/serradura/kind/pull/14) - Raise a `Kind::Error` if `nil` is the argument of any strict type checker.
|
|
1866
|
-
```ruby
|
|
1867
|
-
Kind.of.Hash(nil) # raise Kind::Error, "nil expected to be a kind of Hash"
|
|
1868
|
-
```
|
|
1869
|
-
|
|
1870
|
-
[⬆️ Back to Top](#changelog-)
|
|
1871
|
-
|
|
1872
|
-
1.0.0 (2020-03-16)
|
|
1873
|
-
------------------
|
|
1874
|
-
|
|
1875
|
-
### Added
|
|
1876
|
-
|
|
1877
|
-
* [#12](https://github.com/serradura/kind/pull/12) - Register type checkers respecting their namespaces.
|
|
1878
|
-
```ruby
|
|
1879
|
-
module Account
|
|
1880
|
-
class User
|
|
1881
|
-
Kind::Types.add(self)
|
|
1882
|
-
end
|
|
1883
|
-
end
|
|
1884
|
-
|
|
1885
|
-
module Account
|
|
1886
|
-
class User
|
|
1887
|
-
class Membership
|
|
1888
|
-
Kind::Types.add(self)
|
|
1889
|
-
end
|
|
1890
|
-
end
|
|
1891
|
-
end
|
|
1892
|
-
|
|
1893
|
-
account_user = Account::User.new
|
|
1894
|
-
|
|
1895
|
-
Kind.of.Account::User(account_user) # #<Account::User:0x0000...>
|
|
1896
|
-
Kind.of.Account::User({}) # Kind::Error ({} expected to be a kind of Account::User)
|
|
1897
|
-
|
|
1898
|
-
Kind.of.Account::User.or_nil({}) # nil
|
|
1899
|
-
|
|
1900
|
-
Kind.of.Account::User.instance?({}) # false
|
|
1901
|
-
Kind.of.Account::User.instance?(account_user) # true
|
|
1902
|
-
|
|
1903
|
-
Kind.of.Account::User.class?(Hash) # false
|
|
1904
|
-
Kind.of.Account::User.class?(Account::User) # true
|
|
1905
|
-
|
|
1906
|
-
# ---
|
|
1907
|
-
|
|
1908
|
-
membership = Account::User::Membership.new
|
|
1909
|
-
|
|
1910
|
-
Kind.of.Account::User::Membership(membership) # #<Account::User::Membership:0x0000...>
|
|
1911
|
-
Kind.of.Account::User::Membership({}) # Kind::Error ({} expected to be a kind of Account::User::Membership)
|
|
1912
|
-
|
|
1913
|
-
Kind.of.Account::User::Membership.or_nil({}) # nil
|
|
1914
|
-
|
|
1915
|
-
Kind.of.Account::User::Membership.instance?({}) # false
|
|
1916
|
-
Kind.of.Account::User::Membership.instance?(membership) # true
|
|
1917
|
-
|
|
1918
|
-
Kind.of.Account::User::Membership.class?(Hash) # false
|
|
1919
|
-
Kind.of.Account::User::Membership.class?(Account::User::Membership) # true
|
|
1920
|
-
```
|
|
1921
|
-
|
|
1922
|
-
[⬆️ Back to Top](#changelog-)
|
|
1923
|
-
|
|
1924
|
-
0.6.0 (2020-01-06)
|
|
1925
|
-
------------------
|
|
1926
|
-
|
|
1927
|
-
### Added
|
|
1928
|
-
|
|
1929
|
-
* [#11](https://github.com/serradura/kind/pull/11) - Register the `Queue` (`Thread::Queue`) type checker. This registering creates:
|
|
1930
|
-
- `Kind::Of::Queue`, `Kind::Is::Queue`
|
|
1931
|
-
|
|
1932
|
-
[⬆️ Back to Top](#changelog-)
|
|
1933
|
-
|
|
1934
|
-
0.5.0 (2020-01-04)
|
|
1935
|
-
------------------
|
|
1936
|
-
|
|
1937
|
-
### Added
|
|
1938
|
-
|
|
1939
|
-
* [#4](https://github.com/serradura/kind/pull/4) - Allow defining a default value when the verified object is `nil`.
|
|
1940
|
-
```ruby
|
|
1941
|
-
Kind.of.Hash(nil, or: {}) # {}
|
|
1942
|
-
```
|
|
1943
|
-
|
|
1944
|
-
[⬆️ Back to Top](#changelog-)
|
|
1945
|
-
|
|
1946
|
-
0.4.0 (2020-01-03)
|
|
1947
|
-
------------------
|
|
1948
|
-
|
|
1949
|
-
### Added
|
|
1950
|
-
|
|
1951
|
-
* [#3](https://github.com/serradura/kind/pull/3) - Require `2.2.0` as the minimum Ruby version.
|
|
1952
|
-
|
|
1953
|
-
[⬆️ Back to Top](#changelog-)
|
|
1954
|
-
|
|
1955
|
-
0.3.0 (2020-01-03)
|
|
1956
|
-
------------------
|
|
1957
|
-
|
|
1958
|
-
### Added
|
|
1959
|
-
|
|
1960
|
-
* [#2](https://github.com/serradura/kind/pull/2) - Add `Kind::Checker` to create an object which knows how to do a type checking. (PR: #2)
|
|
1961
|
-
```ruby
|
|
1962
|
-
class User
|
|
1963
|
-
end
|
|
1964
|
-
|
|
1965
|
-
user = User.new
|
|
1966
|
-
|
|
1967
|
-
UserKind = Kind::Checker.new(User)
|
|
1968
|
-
|
|
1969
|
-
UserKind.class?(User) # true
|
|
1970
|
-
UserKind.class?(String) # false
|
|
1971
|
-
|
|
1972
|
-
UserKind.instance?(user) # true
|
|
1973
|
-
UserKind.instance?(1) # false
|
|
1974
|
-
|
|
1975
|
-
UserKind.or_nil(user) # #<User:0x0000...>
|
|
1976
|
-
UserKind.or_nil(1) # nil
|
|
1977
|
-
```
|
|
1978
|
-
|
|
1979
|
-
### Breaking Changes
|
|
1980
|
-
|
|
1981
|
-
* [#2](https://github.com/serradura/kind/pull/2) - Replace `instance_eval` in modules by singleton objects to define the type checkers (via `Kind::Types.add()`). The behavior still the same, but the constants become a `Kind::Checker` object instead of a module.
|
|
1982
|
-
|
|
1983
|
-
[⬆️ Back to Top](#changelog-)
|
|
1984
|
-
|
|
1985
|
-
0.2.0 (2020-01-02)
|
|
1986
|
-
------------------
|
|
1987
|
-
|
|
1988
|
-
### Added
|
|
1989
|
-
|
|
1990
|
-
* [#1](https://github.com/serradura/kind/pull/1) - Register type checkers for several Ruby classes/modules. (PR: #1)
|
|
1991
|
-
- **Classes:**
|
|
1992
|
-
- `Kind::Of::Symbol` , `Kind::Is::Symbol`
|
|
1993
|
-
- `Kind::Of::Numeric` , `Kind::Is::Numeric`
|
|
1994
|
-
- `Kind::Of::Integer` , `Kind::Is::Integer`
|
|
1995
|
-
- `Kind::Of::Float` , `Kind::Is::Float`
|
|
1996
|
-
- `Kind::Of::Regexp` , `Kind::Is::Regexp`
|
|
1997
|
-
- `Kind::Of::Time` , `Kind::Is::Time`
|
|
1998
|
-
- `Kind::Of::Array` , `Kind::Is::Array`
|
|
1999
|
-
- `Kind::Of::Range` , `Kind::Is::Range`
|
|
2000
|
-
- `Kind::Of::Hash` , `Kind::Is::Hash`
|
|
2001
|
-
- `Kind::Of::Struct` , `Kind::Is::Struct`
|
|
2002
|
-
- `Kind::Of::Enumerator`, `Kind::Is::Enumerator`
|
|
2003
|
-
- `Kind::Of::Method` , `Kind::Is::Method`
|
|
2004
|
-
- `Kind::Of::Proc` , `Kind::Is::Proc`
|
|
2005
|
-
- `Kind::Of::IO` , `Kind::Is::IO`
|
|
2006
|
-
- `Kind::Of::File` , `Kind::Is::File`
|
|
2007
|
-
- **Modules:**
|
|
2008
|
-
- `Kind::Of::Enumerable`, `Kind::Is::Enumerable`
|
|
2009
|
-
- `Kind::Of::Comparable`, `Kind::Is::Comparable`
|
|
2010
|
-
|
|
2011
|
-
* [#1](https://github.com/serradura/kind/pull/1) - Create special type checkers.
|
|
2012
|
-
- `Kind::Of::Boolean` for check if the given object is `true` or `false`.
|
|
2013
|
-
- `Kind::Of::Lambda` for check if the given object is a `lambda`.
|
|
2014
|
-
- `Kind::Of::Module` for check if the given object is a *module*.
|
|
2015
|
-
|
|
2016
|
-
[⬆️ Back to Top](#changelog-)
|
|
2017
|
-
|
|
2018
|
-
0.1.0 (2019-12-26)
|
|
2019
|
-
------------------
|
|
2020
|
-
|
|
2021
|
-
### Added
|
|
2022
|
-
|
|
2023
|
-
* Require `2.3.0` as the minimum Ruby version.
|
|
2024
|
-
|
|
2025
|
-
* `Kind::Error` for defining type checkers errors.
|
|
2026
|
-
|
|
2027
|
-
* `Kind::Of.call()` for check if the given *class* is the *class/superclass* of object, or if the given *module* is included in the object. `Kind::Error` will be raised, If the object hasn't the expected kind.
|
|
2028
|
-
```ruby
|
|
2029
|
-
Kind::Of.(String, '') # ''
|
|
2030
|
-
Kind::Of.(String, 1) # Kind::Error (1 expected to be a kind of String)
|
|
2031
|
-
```
|
|
2032
|
-
|
|
2033
|
-
* `Kind::Of::Class()` for check if the given object is a *class*.
|
|
2034
|
-
|
|
2035
|
-
* `Kind::Is.call()` for check if the first kind is equal or a parent class/module of the second one.
|
|
2036
|
-
```ruby
|
|
2037
|
-
Kind::Is.(String, String) # true
|
|
2038
|
-
Kind::Is.(Symbol, String) # false
|
|
2039
|
-
```
|
|
2040
|
-
|
|
2041
|
-
* `Kind.of` is a shortcut for `Kind::Of`.
|
|
2042
|
-
|
|
2043
|
-
* `Kind.is` is a shortcut for `Kind::Is`.
|
|
2044
|
-
|
|
2045
|
-
* `Kind::Types.add` allows the registering of new type checkers.
|
|
2046
|
-
```ruby
|
|
2047
|
-
# Registering Symbol
|
|
2048
|
-
|
|
2049
|
-
Kind::Type.add(Symbol)
|
|
2050
|
-
|
|
2051
|
-
# Adds a method in the Kind::Is module
|
|
2052
|
-
|
|
2053
|
-
class MySymbol < Symbol
|
|
2054
|
-
end
|
|
2055
|
-
|
|
2056
|
-
Kind.is.Symbol(Symbol) # true
|
|
2057
|
-
Kind.is.Symbol(MySymbol) # true
|
|
2058
|
-
Kind.is.Symbol(String) # false
|
|
2059
|
-
|
|
2060
|
-
# Adds a method in the Kind::Of module
|
|
2061
|
-
|
|
2062
|
-
Kind.of.Symbol(:a) # :a
|
|
2063
|
-
Kind.of.Symbol(1) # Kind::Error (1 expected to be a kind of Symbol)
|
|
2064
|
-
|
|
2065
|
-
# Creates a module in Kind::Of with type checking methods related to the given kind.
|
|
2066
|
-
|
|
2067
|
-
Kind::Of::Symbol.class?(Symbol) # true
|
|
2068
|
-
Kind::Of::Symbol.instance?(:a) # true
|
|
2069
|
-
Kind::Of::Symbol.or_nil(:b) # :b
|
|
2070
|
-
Kind::Of::Symbol.or_nil(1) # nil
|
|
2071
|
-
```
|
|
2072
|
-
|
|
2073
|
-
* Register the `String` and `Hash` type checkers. This registering creates:
|
|
2074
|
-
- `Kind::Of::Hash`, `Kind::Is::Hash`
|
|
2075
|
-
- `Kind::Of::String`, `Kind::Is::String`
|
|
2076
|
-
|
|
2077
|
-
[⬆️ Back to Top](#changelog-)
|
|
400
|
+
- [#14](https://github.com/serradura/kind/pull/14) - Raise `Kind::Error` if `nil` is the argument of any strict type checker.
|
|
401
|
+
|
|
402
|
+
## [1.0.0] - 2020-03-16
|
|
403
|
+
### Added
|
|
404
|
+
- [#12](https://github.com/serradura/kind/pull/12) - Register type checkers respecting their namespaces, so nested classes like `Account::User::Membership` get the full `Kind.of.Account::User::Membership` API (`[]`, `instance?`, `class?`, `or_nil`, …).
|
|
405
|
+
|
|
406
|
+
## [0.6.0] - 2020-01-06
|
|
407
|
+
### Added
|
|
408
|
+
- [#11](https://github.com/serradura/kind/pull/11) - Register the `Queue` (`Thread::Queue`) type checker: `Kind::Of::Queue`, `Kind::Is::Queue`.
|
|
409
|
+
|
|
410
|
+
## [0.5.0] - 2020-01-04
|
|
411
|
+
### Added
|
|
412
|
+
- [#4](https://github.com/serradura/kind/pull/4) - Allow defining a default value when the verified object is `nil`: `Kind.of.Hash(nil, or: {})`.
|
|
413
|
+
|
|
414
|
+
## [0.4.0] - 2020-01-03
|
|
415
|
+
### Changed
|
|
416
|
+
- [#3](https://github.com/serradura/kind/pull/3) - Require Ruby `>= 2.2.0` as the minimum supported version.
|
|
417
|
+
|
|
418
|
+
## [0.3.0] - 2020-01-03
|
|
419
|
+
### Added
|
|
420
|
+
- [#2](https://github.com/serradura/kind/pull/2) - Add `Kind::Checker.new(<Type>)` for building reusable type-checker objects with `class?`, `instance?`, `or_nil`, …
|
|
421
|
+
|
|
422
|
+
### Changed
|
|
423
|
+
- [#2](https://github.com/serradura/kind/pull/2) - **BREAKING:** Replace `instance_eval`-on-modules with singleton objects when defining type checkers via `Kind::Types.add()`. The behavior is unchanged, but `Kind::Of::<Type>` constants are now `Kind::Checker` objects instead of modules.
|
|
424
|
+
|
|
425
|
+
## [0.2.0] - 2020-01-02
|
|
426
|
+
### Added
|
|
427
|
+
- [#1](https://github.com/serradura/kind/pull/1) - Register type checkers for Ruby core classes (`Symbol`, `Numeric`, `Integer`, `Float`, `Regexp`, `Time`, `Array`, `Range`, `Hash`, `Struct`, `Enumerator`, `Method`, `Proc`, `IO`, `File`) and modules (`Enumerable`, `Comparable`).
|
|
428
|
+
- [#1](https://github.com/serradura/kind/pull/1) - Add the special type checkers `Kind::Of::Boolean` (`true`/`false`), `Kind::Of::Lambda`, and `Kind::Of::Module`.
|
|
429
|
+
|
|
430
|
+
## [0.1.0] - 2019-12-26
|
|
431
|
+
### Added
|
|
432
|
+
- Require Ruby `>= 2.3.0` as the minimum supported version.
|
|
433
|
+
- `Kind::Error` for type-checker errors.
|
|
434
|
+
- `Kind::Of.call(<Type>, value)` — returns the value if it is a kind of `<Type>`, raises `Kind::Error` otherwise. `Kind::Of::Class()` checks the given object is a class.
|
|
435
|
+
- `Kind::Is.call(<Type>, other)` — checks the first kind is equal to or a parent of the second.
|
|
436
|
+
- Shortcuts `Kind.of` (→ `Kind::Of`) and `Kind.is` (→ `Kind::Is`).
|
|
437
|
+
- `Kind::Types.add(<Type>)` for registering new type checkers. Registration adds `Kind.of.<Type>(value)` / `Kind.is.<Type>(other)` methods and a `Kind::Of::<Type>` module exposing `class?`, `instance?`, `or_nil`.
|
|
438
|
+
- Register the `String` and `Hash` type checkers: `Kind::Of::Hash` / `Kind::Is::Hash`, `Kind::Of::String` / `Kind::Is::String`.
|
|
439
|
+
|
|
440
|
+
[6.0.1]: https://github.com/serradura/kind/compare/v6.0.0...v6.0.1
|
|
441
|
+
[6.0.0]: https://github.com/serradura/kind/compare/v5.10.0...v6.0.0
|
|
442
|
+
[5.10.0]: https://github.com/serradura/kind/compare/v5.9.0...v5.10.0
|
|
443
|
+
[5.9.0]: https://github.com/serradura/kind/compare/v5.8.1...v5.9.0
|
|
444
|
+
[5.8.1]: https://github.com/serradura/kind/compare/v5.8.0...v5.8.1
|
|
445
|
+
[5.8.0]: https://github.com/serradura/kind/compare/v5.7.0...v5.8.0
|
|
446
|
+
[5.7.0]: https://github.com/serradura/kind/compare/v5.6.0...v5.7.0
|
|
447
|
+
[5.6.0]: https://github.com/serradura/kind/compare/v5.5.0...v5.6.0
|
|
448
|
+
[5.5.0]: https://github.com/serradura/kind/compare/v5.4.1...v5.5.0
|
|
449
|
+
[5.4.1]: https://github.com/serradura/kind/compare/v5.4.0...v5.4.1
|
|
450
|
+
[5.4.0]: https://github.com/serradura/kind/compare/v5.3.0...v5.4.0
|
|
451
|
+
[5.3.0]: https://github.com/serradura/kind/compare/v5.2.0...v5.3.0
|
|
452
|
+
[5.2.0]: https://github.com/serradura/kind/compare/v5.1.0...v5.2.0
|
|
453
|
+
[5.1.0]: https://github.com/serradura/kind/compare/v5.0.0...v5.1.0
|
|
454
|
+
[5.0.0]: https://github.com/serradura/kind/compare/v4.1.0...v5.0.0
|
|
455
|
+
[4.1.0]: https://github.com/serradura/kind/compare/v4.0.0...v4.1.0
|
|
456
|
+
[4.0.0]: https://github.com/serradura/kind/compare/v3.1.0...v4.0.0
|
|
457
|
+
[3.1.0]: https://github.com/serradura/kind/compare/v3.0.1...v3.1.0
|
|
458
|
+
[3.0.1]: https://github.com/serradura/kind/compare/v3.0.0...v3.0.1
|
|
459
|
+
[3.0.0]: https://github.com/serradura/kind/compare/v2.3.0...v3.0.0
|
|
460
|
+
[2.3.0]: https://github.com/serradura/kind/compare/v2.2.0...v2.3.0
|
|
461
|
+
[2.2.0]: https://github.com/serradura/kind/compare/v2.1.0...v2.2.0
|
|
462
|
+
[2.1.0]: https://github.com/serradura/kind/compare/v2.0.0...v2.1.0
|
|
463
|
+
[2.0.0]: https://github.com/serradura/kind/compare/v1.9.0...v2.0.0
|
|
464
|
+
[1.9.0]: https://github.com/serradura/kind/compare/v1.8.0...v1.9.0
|
|
465
|
+
[1.8.0]: https://github.com/serradura/kind/compare/v1.7.0...v1.8.0
|
|
466
|
+
[1.7.0]: https://github.com/serradura/kind/compare/v1.6.0...v1.7.0
|
|
467
|
+
[1.6.0]: https://github.com/serradura/kind/compare/v1.5.0...v1.6.0
|
|
468
|
+
[1.5.0]: https://github.com/serradura/kind/compare/v1.4.0...v1.5.0
|
|
469
|
+
[1.4.0]: https://github.com/serradura/kind/compare/v1.3.0...v1.4.0
|
|
470
|
+
[1.3.0]: https://github.com/serradura/kind/compare/v1.2.0...v1.3.0
|
|
471
|
+
[1.2.0]: https://github.com/serradura/kind/compare/v1.1.0...v1.2.0
|
|
472
|
+
[1.1.0]: https://github.com/serradura/kind/compare/v1.0.0...v1.1.0
|
|
473
|
+
[1.0.0]: https://github.com/serradura/kind/compare/v0.6.0...v1.0.0
|
|
474
|
+
[0.6.0]: https://github.com/serradura/kind/compare/v0.5.0...v0.6.0
|
|
475
|
+
[0.5.0]: https://github.com/serradura/kind/compare/v0.4.0...v0.5.0
|
|
476
|
+
[0.4.0]: https://github.com/serradura/kind/compare/v0.3.0...v0.4.0
|
|
477
|
+
[0.3.0]: https://github.com/serradura/kind/compare/v0.2.0...v0.3.0
|
|
478
|
+
[0.2.0]: https://github.com/serradura/kind/compare/v0.1.0...v0.2.0
|
|
479
|
+
[0.1.0]: https://github.com/serradura/kind/releases/tag/v0.1.0
|