kind 3.1.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.tool-versions +1 -0
- data/.travis.sh +37 -12
- data/.travis.yml +6 -3
- data/CHANGELOG.md +1230 -0
- data/Gemfile +10 -2
- data/README.md +817 -487
- data/lib/kind.rb +53 -283
- data/lib/kind/active_model/kind_validator.rb +7 -7
- data/lib/kind/core.rb +9 -0
- data/lib/kind/core/deprecation.rb +29 -0
- data/lib/kind/core/kind.rb +61 -0
- data/lib/kind/core/undefined.rb +7 -0
- data/lib/kind/deprecations/built_in_type_checkers.rb +23 -0
- data/lib/kind/{checker.rb → deprecations/checker.rb} +3 -2
- data/lib/kind/{checker → deprecations/checker}/factory.rb +1 -5
- data/lib/kind/{checker → deprecations/checker}/protocol.rb +3 -3
- data/lib/kind/deprecations/is.rb +35 -0
- data/lib/kind/deprecations/of.rb +258 -0
- data/lib/kind/{types.rb → deprecations/types.rb} +14 -8
- data/lib/kind/dig.rb +13 -9
- data/lib/kind/empty.rb +5 -11
- data/lib/kind/error.rb +2 -6
- data/lib/kind/maybe.rb +12 -161
- data/lib/kind/maybe/none.rb +57 -0
- data/lib/kind/maybe/result.rb +51 -0
- data/lib/kind/maybe/some.rb +90 -0
- data/lib/kind/maybe/typed.rb +29 -0
- data/lib/kind/maybe/wrappable.rb +35 -0
- data/lib/kind/presence.rb +33 -0
- data/lib/kind/try.rb +36 -0
- data/lib/kind/type_checker.rb +73 -0
- data/lib/kind/type_checkers.rb +30 -0
- data/lib/kind/type_checkers/core/array.rb +17 -0
- data/lib/kind/type_checkers/core/class.rb +13 -0
- data/lib/kind/type_checkers/core/comparable.rb +13 -0
- data/lib/kind/type_checkers/core/enumerable.rb +13 -0
- data/lib/kind/type_checkers/core/enumerator.rb +13 -0
- data/lib/kind/type_checkers/core/file.rb +13 -0
- data/lib/kind/type_checkers/core/float.rb +13 -0
- data/lib/kind/type_checkers/core/hash.rb +17 -0
- data/lib/kind/type_checkers/core/integer.rb +13 -0
- data/lib/kind/type_checkers/core/io.rb +13 -0
- data/lib/kind/type_checkers/core/method.rb +13 -0
- data/lib/kind/type_checkers/core/module.rb +17 -0
- data/lib/kind/type_checkers/core/numeric.rb +13 -0
- data/lib/kind/type_checkers/core/proc.rb +13 -0
- data/lib/kind/type_checkers/core/queue.rb +14 -0
- data/lib/kind/type_checkers/core/range.rb +13 -0
- data/lib/kind/type_checkers/core/regexp.rb +13 -0
- data/lib/kind/type_checkers/core/string.rb +17 -0
- data/lib/kind/type_checkers/core/struct.rb +13 -0
- data/lib/kind/type_checkers/core/symbol.rb +13 -0
- data/lib/kind/type_checkers/core/time.rb +13 -0
- data/lib/kind/type_checkers/custom/boolean.rb +19 -0
- data/lib/kind/type_checkers/custom/callable.rb +19 -0
- data/lib/kind/type_checkers/custom/lambda.rb +19 -0
- data/lib/kind/type_checkers/stdlib/open_struct.rb +13 -0
- data/lib/kind/type_checkers/stdlib/set.rb +17 -0
- data/lib/kind/undefined.rb +4 -2
- data/lib/kind/validator.rb +1 -1
- data/lib/kind/version.rb +1 -1
- data/test.sh +4 -4
- metadata +51 -9
- data/lib/kind/is.rb +0 -19
- data/lib/kind/of.rb +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 62e657cbbdd2af4aebab8cde9f010744a0321c7fceff24f3574a2f9ac4c2a9ad
|
4
|
+
data.tar.gz: c0f5690cef9d736b703ac2f1f75c23b30fccc309ad58c18972060074c8946d3b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 15281701426737bbf5c5cd4fa669ecb7c245fb520c1feb79d344d271f6552388111f75245babeffd4eadb3cd98120a3041a4d65959c78f0983ad167ce7060104
|
7
|
+
data.tar.gz: 6bd17ee29bcbf1bda1273eebf7ef2999a74a0e55935622330b19a07efac4f0e448436eb26115042e828c1e7ed9e00c1435207ddbcb84bbd11dcb15a1371a2a3a
|
data/.tool-versions
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby 2.7.2
|
data/.travis.sh
CHANGED
@@ -1,20 +1,45 @@
|
|
1
1
|
#!/bin/bash
|
2
2
|
|
3
|
-
|
3
|
+
RUBY_V=$(ruby -v)
|
4
4
|
|
5
|
-
|
5
|
+
function run_with_bundler {
|
6
|
+
rm Gemfile.lock
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
ACTIVEMODEL_VERSION='5.1' bundle update && bundle exec rake test
|
8
|
+
if [ ! -z "$1" ]; then
|
9
|
+
bundle_cmd="bundle _$1_"
|
10
|
+
else
|
11
|
+
bundle_cmd="bundle"
|
12
|
+
fi
|
13
13
|
|
14
|
-
|
15
|
-
|
14
|
+
eval "$2 $bundle_cmd update"
|
15
|
+
eval "$2 $bundle_cmd exec rake test"
|
16
|
+
}
|
17
|
+
|
18
|
+
function run_with_am_version_and_bundler {
|
19
|
+
run_with_bundler "$2" "ACTIVEMODEL_VERSION=$1"
|
20
|
+
}
|
21
|
+
|
22
|
+
RUBY_2_2345="ruby 2.[2345]."
|
23
|
+
|
24
|
+
if [[ $RUBY_V =~ $RUBY_2_2345 ]]; then
|
25
|
+
run_with_bundler "$BUNDLER_V1"
|
26
|
+
|
27
|
+
run_with_am_version_and_bundler "3.2" "$BUNDLER_V1"
|
28
|
+
run_with_am_version_and_bundler "4.0" "$BUNDLER_V1"
|
29
|
+
run_with_am_version_and_bundler "4.1" "$BUNDLER_V1"
|
30
|
+
run_with_am_version_and_bundler "4.2" "$BUNDLER_V1"
|
31
|
+
run_with_am_version_and_bundler "5.0" "$BUNDLER_V1"
|
32
|
+
run_with_am_version_and_bundler "5.1" "$BUNDLER_V1"
|
33
|
+
run_with_am_version_and_bundler "5.2" "$BUNDLER_V1"
|
16
34
|
fi
|
17
35
|
|
18
|
-
|
19
|
-
|
36
|
+
RUBY_2_567="ruby 2.[567]."
|
37
|
+
RUBY_3_x_x="ruby 3.0."
|
38
|
+
|
39
|
+
if [[ $RUBY_V =~ $RUBY_2_567 ]] || [[ $RUBY_V =~ $RUBY_3_x_x ]]; then
|
40
|
+
gem install bundler -v ">= 2" --no-doc
|
41
|
+
|
42
|
+
run_with_bundler
|
43
|
+
run_with_am_version_and_bundler "6.0"
|
44
|
+
run_with_am_version_and_bundler "6.1"
|
20
45
|
fi
|
data/.travis.yml
CHANGED
@@ -9,16 +9,19 @@ cache:
|
|
9
9
|
- /home/travis/.rvm/
|
10
10
|
|
11
11
|
rvm:
|
12
|
-
- 2.2.
|
12
|
+
- 2.2.2
|
13
13
|
- 2.3.0
|
14
14
|
- 2.4.0
|
15
15
|
- 2.5.0
|
16
16
|
- 2.6.0
|
17
17
|
- 2.7.0
|
18
|
+
- 3.0.0
|
19
|
+
|
20
|
+
env:
|
21
|
+
- BUNDLER_V1="1.17.3"
|
18
22
|
|
19
23
|
before_install:
|
20
|
-
- gem
|
21
|
-
- gem install bundler -v '< 2'
|
24
|
+
- gem install bundler -v "$BUNDLER_V1"
|
22
25
|
|
23
26
|
install: bundle install --jobs=3 --retry=3
|
24
27
|
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,1230 @@
|
|
1
|
+
# Changelog <!-- omit in toc -->
|
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
|
+
- [4.0.0 (2021-02-22)](#400-2021-02-22)
|
7
|
+
- [Added](#added)
|
8
|
+
- [Deprecated](#deprecated)
|
9
|
+
- [Fixed](#fixed)
|
10
|
+
- [3.1.0 (2020-07-08)](#310-2020-07-08)
|
11
|
+
- [Added](#added-1)
|
12
|
+
- [3.0.0 (2020-06-25)](#300-2020-06-25)
|
13
|
+
- [Breaking Changes](#breaking-changes)
|
14
|
+
- [Added](#added-2)
|
15
|
+
- [2.3.0 (2020-06-24)](#230-2020-06-24)
|
16
|
+
- [Added](#added-3)
|
17
|
+
- [2.2.0 (2020-06-23)](#220-2020-06-23)
|
18
|
+
- [Added](#added-4)
|
19
|
+
- [2.1.0 (2020-05-12)](#210-2020-05-12)
|
20
|
+
- [Added](#added-5)
|
21
|
+
- [Breaking Changes](#breaking-changes-1)
|
22
|
+
- [2.0.0 (2020-05-07)](#200-2020-05-07)
|
23
|
+
- [Added](#added-6)
|
24
|
+
- [Breaking Changes](#breaking-changes-2)
|
25
|
+
- [Removed](#removed)
|
26
|
+
- [1.9.0 (2020-05-06)](#190-2020-05-06)
|
27
|
+
- [Added](#added-7)
|
28
|
+
- [1.8.0 (2020-05-03)](#180-2020-05-03)
|
29
|
+
- [Added](#added-8)
|
30
|
+
- [1.7.0 (2020-05-03)](#170-2020-05-03)
|
31
|
+
- [Fixed](#fixed-1)
|
32
|
+
- [1.6.0 (2020-04-17)](#160-2020-04-17)
|
33
|
+
- [Added](#added-9)
|
34
|
+
- [Changes](#changes)
|
35
|
+
- [1.5.0 (2020-04-12)](#150-2020-04-12)
|
36
|
+
- [Added](#added-10)
|
37
|
+
- [1.4.0 (2020-04-12)](#140-2020-04-12)
|
38
|
+
- [Added](#added-11)
|
39
|
+
- [1.3.0 (2020-04-12)](#130-2020-04-12)
|
40
|
+
- [Added](#added-12)
|
41
|
+
- [1.2.0 (2020-04-12)](#120-2020-04-12)
|
42
|
+
- [Added](#added-13)
|
43
|
+
- [1.1.0 (2020-04-09)](#110-2020-04-09)
|
44
|
+
- [Added](#added-14)
|
45
|
+
- [Fixed](#fixed-2)
|
46
|
+
- [1.0.0 (2020-03-16)](#100-2020-03-16)
|
47
|
+
- [Added](#added-15)
|
48
|
+
- [0.6.0 (2020-01-06)](#060-2020-01-06)
|
49
|
+
- [Added](#added-16)
|
50
|
+
- [0.5.0 (2020-01-04)](#050-2020-01-04)
|
51
|
+
- [Added](#added-17)
|
52
|
+
- [0.4.0 (2020-01-03)](#040-2020-01-03)
|
53
|
+
- [Added](#added-18)
|
54
|
+
- [0.3.0 (2020-01-03)](#030-2020-01-03)
|
55
|
+
- [Added](#added-19)
|
56
|
+
- [Breaking Changes](#breaking-changes-3)
|
57
|
+
- [0.2.0 (2020-01-02)](#020-2020-01-02)
|
58
|
+
- [Added](#added-20)
|
59
|
+
- [0.1.0 (2019-12-26)](#010-2019-12-26)
|
60
|
+
- [Added](#added-21)
|
61
|
+
|
62
|
+
## Unreleased
|
63
|
+
|
64
|
+
<!--
|
65
|
+
### Added
|
66
|
+
### Breaking Changes
|
67
|
+
### Deprecated
|
68
|
+
### Removed
|
69
|
+
### Fixed
|
70
|
+
-->
|
71
|
+
|
72
|
+
4.0.0 (2021-02-22)
|
73
|
+
------------------
|
74
|
+
|
75
|
+
### Added
|
76
|
+
|
77
|
+
* [#40](https://github.com/serradura/kind/pull/40) - Add `Kind.of_class?` to verify if a given value is a `Class`.
|
78
|
+
|
79
|
+
* [#40](https://github.com/serradura/kind/pull/40) - Add `Kind.of_module?` to verify if a given value is a `Module`.
|
80
|
+
|
81
|
+
* [#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.
|
82
|
+
```ruby
|
83
|
+
Kind.of_module_or_class(String) # String
|
84
|
+
Kind.of_module_or_class(1) # Kind::Error (1 expected to be a kind of Module/Class)
|
85
|
+
```
|
86
|
+
|
87
|
+
* [#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.
|
88
|
+
```ruby
|
89
|
+
Kind.respond_to('', :upcase) # ""
|
90
|
+
Kind.respond_to('', :upcase, :strip) # ""
|
91
|
+
|
92
|
+
Kind.respond_to(1, :upcase) # expected 1 to respond to :upcase
|
93
|
+
Kind.respond_to(2, :to_s, :upcase) # expected 2 to respond to :upcase
|
94
|
+
```
|
95
|
+
|
96
|
+
* [#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.
|
97
|
+
```ruby
|
98
|
+
Kind::Try.(' foo ', :strip) # "foo"
|
99
|
+
Kind::Try.({a: 1}, :[], :a) # 1
|
100
|
+
Kind::Try.({a: 1}, :[], :b) # nil
|
101
|
+
Kind::Try.({a: 1}, :fetch, :b, 2) # 2
|
102
|
+
|
103
|
+
Kind::Try.(:symbol, :strip) # nil
|
104
|
+
Kind::Try.(:symbol, :fetch, :b, 2) # nil
|
105
|
+
|
106
|
+
# It raises an exception if the method name isn't a string or a symbol
|
107
|
+
Kind::Try.({a: 1}, 1, :a) # TypeError (1 is not a symbol nor a string)
|
108
|
+
```
|
109
|
+
|
110
|
+
* [#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.
|
111
|
+
|
112
|
+
* [#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.
|
113
|
+
```ruby
|
114
|
+
# All of the methods used with the Kind::String can be used with any other type checker module.
|
115
|
+
|
116
|
+
# Kind::<Type>.name
|
117
|
+
# Kind::<Type>.kind
|
118
|
+
# The type checker can return its kind and its name
|
119
|
+
Kind::String.name # "String"
|
120
|
+
Kind::String.kind # ::String
|
121
|
+
|
122
|
+
# Kind::<Type>.===
|
123
|
+
# Can check if a given value is an instance of its kind.
|
124
|
+
Kind::String === 'foo' # true
|
125
|
+
Kind::String === :foo # false
|
126
|
+
|
127
|
+
# Kind::<Type>.value?(value)
|
128
|
+
# Can check if a given value is an instance of its kind.
|
129
|
+
Kind::String.value?('foo') # true
|
130
|
+
Kind::String.value?(:foo) # false
|
131
|
+
|
132
|
+
# If it doesn't receive an argument, a lambda will be returned and it will know how to do the type verification.
|
133
|
+
[1, 2, 'foo', 3, 'Bar'].select?(&Kind::String.value?) # ["foo", "bar"]
|
134
|
+
|
135
|
+
# Kind::<Type>.or_nil(value)
|
136
|
+
# Can return nil if the given value isn't an instance of its kind
|
137
|
+
Kind::String.or_nil('foo') # "foo"
|
138
|
+
Kind::String.or_nil(:foo) # nil
|
139
|
+
|
140
|
+
# Kind::<Type>.or_undefined(value)
|
141
|
+
# Can return Kind::Undefined if the given value isn't an instance of its kind
|
142
|
+
Kind::String.or_undefined('foo') # "foo"
|
143
|
+
Kind::String.or_undefined(:foo) # Kind::Undefined
|
144
|
+
|
145
|
+
# Kind::<Type>.or(fallback, value)
|
146
|
+
# Can return a fallback if the given value isn't an instance of its kind
|
147
|
+
Kind::String.or(nil, 'foo') # "foo"
|
148
|
+
Kind::String.or(nil, :foo) # nil
|
149
|
+
|
150
|
+
# 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.
|
151
|
+
[1, 2, 'foo', 3, 'Bar'].map(&Kind::String.or('')) # ["", "", "foo", "", "Bar"]
|
152
|
+
[1, 2, 'foo', 3, 'Bar'].map(&Kind::String.or(nil)) # [nil, nil, "foo", nil, "Bar"]
|
153
|
+
|
154
|
+
# An error will be raised if the fallback didn't have the expected kind or if not nil / Kind::Undefined.
|
155
|
+
[1, 2, 'foo', 3, 'Bar'].map(&Kind::String.or(:foo)) # Kind::Error (:foo expected to be a kind of String)
|
156
|
+
|
157
|
+
# Kind::<Type>[value]
|
158
|
+
# Will raise Kind::Error if the given value isn't an instance of the expected kind
|
159
|
+
Kind::String['foo'] # "foo"
|
160
|
+
Kind::String[:foo ] # Kind::Error (:foo expected to be a kind of String)
|
161
|
+
```
|
162
|
+
* List of all type checkers:
|
163
|
+
* **Core:**
|
164
|
+
* `Kind::Array`
|
165
|
+
* `Kind::Class`
|
166
|
+
* `Kind::Comparable`
|
167
|
+
* `Kind::Enumerable`
|
168
|
+
* `Kind::Enumerator`
|
169
|
+
* `Kind::File`
|
170
|
+
* `Kind::Float`
|
171
|
+
* `Kind::Hash`
|
172
|
+
* `Kind::Integer`
|
173
|
+
* `Kind::IO`
|
174
|
+
* `Kind::Method`
|
175
|
+
* `Kind::Module`
|
176
|
+
* `Kind::Numeric`
|
177
|
+
* `Kind::Proc`
|
178
|
+
* `Kind::Queue`
|
179
|
+
* `Kind::Range`
|
180
|
+
* `Kind::Regexp`
|
181
|
+
* `Kind::String`
|
182
|
+
* `Kind::Struct`
|
183
|
+
* `Kind::Symbol`
|
184
|
+
* `Kind::Time`
|
185
|
+
* **Custom:**
|
186
|
+
* `Kind::Boolean`
|
187
|
+
* `Kind::Callable`
|
188
|
+
* `Kind::Lambda`
|
189
|
+
* **Stdlib:**
|
190
|
+
* `Kind::OpenStruct`
|
191
|
+
* `Kind::Set`
|
192
|
+
|
193
|
+
* [#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.
|
194
|
+
```ruby
|
195
|
+
# Example using a class (an object which responds to .=== and has the .name method):
|
196
|
+
# This object will have all of the default methods that a standard type checker (e.g: Kind::String) has.
|
197
|
+
kind_of_string = Kind::Of(String)
|
198
|
+
|
199
|
+
kind_of_string[''] # ""
|
200
|
+
kind_of_string[{}] # Kind::Error ({} expected to be a kind of String)
|
201
|
+
|
202
|
+
# Example using a lambda (an object which responds to .===) and a hash with the kind name.
|
203
|
+
|
204
|
+
PositiveInteger = Kind::Of(-> value { value.kind_of?(Integer) && value > 0 }, name: 'PositiveInteger')
|
205
|
+
|
206
|
+
# PositiveInteger.name
|
207
|
+
# PositiveInteger.kind
|
208
|
+
# The type checker can return its kind and its name
|
209
|
+
PositiveInteger.name # "PositiveInteger"
|
210
|
+
PositiveInteger.kind # #<Proc:0x0000.... >
|
211
|
+
|
212
|
+
# PositiveInteger.===
|
213
|
+
# Can check if a given value is an instance of its kind.
|
214
|
+
PositiveInteger === 1 # true
|
215
|
+
PositiveInteger === 0 # false
|
216
|
+
|
217
|
+
# PositiveInteger.value?(value)
|
218
|
+
# Can check if a given value is an instance of its kind.
|
219
|
+
PositiveInteger.value?(1) # true
|
220
|
+
PositiveInteger.value?(-1) # false
|
221
|
+
|
222
|
+
# If it doesn't receive an argument, a lambda will be returned and it will know how to do the type verification.
|
223
|
+
[1, 2, 0, 3, -1].select?(&PositiveInteger.value?) # [1, 2, 3]
|
224
|
+
|
225
|
+
# PositiveInteger.or_nil(value)
|
226
|
+
# Can return nil if the given value isn't an instance of its kind
|
227
|
+
PositiveInteger.or_nil(1) # 1
|
228
|
+
PositiveInteger.or_nil(0) # nil
|
229
|
+
|
230
|
+
# PositiveInteger.or_undefined(value)
|
231
|
+
# Can return Kind::Undefined if the given value isn't an instance of its kind
|
232
|
+
PositiveInteger.or_undefined(2) # 2
|
233
|
+
PositiveInteger.or_undefined(-1) # Kind::Undefined
|
234
|
+
|
235
|
+
# PositiveInteger.or(fallback, value)
|
236
|
+
# Can return a fallback if the given value isn't an instance of its kind
|
237
|
+
PositiveInteger.or(nil, 1) # 1
|
238
|
+
PositiveInteger.or(nil, 0) # nil
|
239
|
+
|
240
|
+
# 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.
|
241
|
+
[1, 2, 0, 3, -1].map(&PositiveInteger.or(1)) # [1, 2, 1, 3, 1]
|
242
|
+
[1, 2, 0, 3, -1].map(&PositiveInteger.or(nil)) # [1, 2, nil, 3, nil]
|
243
|
+
|
244
|
+
# An error will be raised if the fallback didn't have the expected kind or if not nil / Kind::Undefined.
|
245
|
+
[1, 2, 0, 3, -1].map(&PositiveInteger.or(:foo)) # Kind::Error (:foo expected to be a kind of PositiveInteger)
|
246
|
+
|
247
|
+
# PositiveInteger[value]
|
248
|
+
# Will raise Kind::Error if the given value isn't an instance of the expected kind
|
249
|
+
PositiveInteger[1] # 1
|
250
|
+
PositiveInteger[:foo] # Kind::Error (:foo expected to be a kind of PositiveInteger)
|
251
|
+
```
|
252
|
+
* [#40](https://github.com/serradura/kind/pull/40), [#41](https://github.com/serradura/kind/pull/40) - Add type checkers methods.
|
253
|
+
```ruby
|
254
|
+
# All of the methods used with the Kind::String? can be used with any other type checker method.
|
255
|
+
|
256
|
+
# Kind::<Type>?(*values)
|
257
|
+
# Can check if a given value (one or many) is an instance of its kind.
|
258
|
+
Kind::String?('foo') # true
|
259
|
+
Kind::String?('foo', 'bar') # true
|
260
|
+
Kind::String?('foo', :bar) # false
|
261
|
+
|
262
|
+
# If it doesn't receive an argument, a lambda will be returned and it will know how to do the type verification.
|
263
|
+
[1, 2, 'foo', 3, 'Bar'].select?(&Kind::String?) # ["foo", "bar"]
|
264
|
+
```
|
265
|
+
* List of all type checkers:
|
266
|
+
* **Core:**
|
267
|
+
* `Kind::Array?`
|
268
|
+
* `Kind::Class?`
|
269
|
+
* `Kind::Comparable?`
|
270
|
+
* `Kind::Enumerable?`
|
271
|
+
* `Kind::Enumerator?`
|
272
|
+
* `Kind::File?`
|
273
|
+
* `Kind::Float?`
|
274
|
+
* `Kind::Hash?`
|
275
|
+
* `Kind::Integer?`
|
276
|
+
* `Kind::IO?`
|
277
|
+
* `Kind::Method?`
|
278
|
+
* `Kind::Module?`
|
279
|
+
* `Kind::Numeric?`
|
280
|
+
* `Kind::Proc?`
|
281
|
+
* `Kind::Queue?`
|
282
|
+
* `Kind::Range?`
|
283
|
+
* `Kind::Regexp?`
|
284
|
+
* `Kind::String?`
|
285
|
+
* `Kind::Struct?`
|
286
|
+
* `Kind::Symbol?`
|
287
|
+
* `Kind::Time?`
|
288
|
+
* **Custom:**
|
289
|
+
* `Kind::Boolean?`
|
290
|
+
* `Kind::Callable?`
|
291
|
+
* `Kind::Lambda?`
|
292
|
+
* **Stdlib:**
|
293
|
+
* `Kind::OpenStruct?`
|
294
|
+
* `Kind::Set?`
|
295
|
+
|
296
|
+
* [#41](https://github.com/serradura/kind/pull/41) - Make `Kind::Dig.call` extract values from regular objects.
|
297
|
+
```ruby
|
298
|
+
class Person
|
299
|
+
attr_reader :name
|
300
|
+
|
301
|
+
def initialize(name)
|
302
|
+
@name = name
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
person = Person.new('Rodrigo')
|
307
|
+
|
308
|
+
Kind::Dig.(person, [:name]) # "Rodrigo"
|
309
|
+
|
310
|
+
Kind::Dig.({people: [person]}, [:people, 0, :name]) # "Rodrigo"
|
311
|
+
```
|
312
|
+
|
313
|
+
* [#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`.
|
314
|
+
```ruby
|
315
|
+
Kind::Presence.(true) # true
|
316
|
+
Kind::Presence.('foo') # "foo"
|
317
|
+
Kind::Presence.([1, 2]) # [1, 2]
|
318
|
+
Kind::Presence.({a: 3}) # {a: 3}
|
319
|
+
Kind::Presence.(Set.new([4])) # #<Set: {4}>
|
320
|
+
|
321
|
+
Kind::Presence.('') # nil
|
322
|
+
Kind::Presence.(' ') # nil
|
323
|
+
Kind::Presence.("\t\n\r") # nil
|
324
|
+
Kind::Presence.("\u00a0") # nil
|
325
|
+
|
326
|
+
Kind::Presence.([]) # nil
|
327
|
+
Kind::Presence.({}) # nil
|
328
|
+
Kind::Presence.(Set.new) # nil
|
329
|
+
|
330
|
+
Kind::Presence.(nil) # nil
|
331
|
+
Kind::Presence.(false) # nil
|
332
|
+
|
333
|
+
# nil will be returned if the given object responds to the method blank? and this method result is true.
|
334
|
+
MyObject = Struct.new(:is_blank) do
|
335
|
+
def blank?
|
336
|
+
is_blank
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
my_object = MyObject.new
|
341
|
+
|
342
|
+
my_object.is_blank = true
|
343
|
+
|
344
|
+
Kind::Presence.(my_object) # nil
|
345
|
+
|
346
|
+
my_object.is_blank = false
|
347
|
+
|
348
|
+
Kind::Presence.(my_object) # #<struct MyObject is_blank=false>
|
349
|
+
```
|
350
|
+
|
351
|
+
* [#41](https://github.com/serradura/kind/pull/41) - Add `Kind::Maybe#presence`, this method will return None if the wrapped value wasn't present.
|
352
|
+
```ruby
|
353
|
+
result1 = Kind::Maybe(Hash).wrap(foo: '').dig(:foo).presence
|
354
|
+
result1.none? # true
|
355
|
+
result1.value # nil
|
356
|
+
|
357
|
+
result2 = Kind::Maybe(Hash).wrap(foo: 'bar').dig(:foo).presence
|
358
|
+
result2.none? # false
|
359
|
+
result2.value # "bar"
|
360
|
+
```
|
361
|
+
|
362
|
+
* [#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.
|
363
|
+
```ruby
|
364
|
+
Kind::Maybe.wrap { 2 / 0 } # #<Kind::Maybe::None:0x0000... @value=#<ZeroDivisionError: divided by 0>>
|
365
|
+
|
366
|
+
Kind::Maybe(Numeric).wrap(2) { |number| number / 0 } # #<Kind::Maybe::None:0x0000... @value=#<ZeroDivisionError: divided by 0>>
|
367
|
+
```
|
368
|
+
|
369
|
+
* [#41](https://github.com/serradura/kind/pull/41) - Make `Kind::Maybe#map` intercept StandardError exceptions.
|
370
|
+
* Now the `#map` and `#then` methods will intercept any StandardError and return None with the exception or their values.
|
371
|
+
* 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.
|
372
|
+
* If an exception (StandardError) is returned by the methods `#then`, `#map` it will be resolved as None.
|
373
|
+
```ruby
|
374
|
+
# Handling StandardError exceptions
|
375
|
+
result1 = Kind::Maybe[2].map { |number| number / 0 }
|
376
|
+
result1.none? # true
|
377
|
+
result1.value # #<ZeroDivisionError: divided by 0>
|
378
|
+
|
379
|
+
result2 = Kind::Maybe[3].then { |number| number / 0 }
|
380
|
+
result2.none? # true
|
381
|
+
result2.value # #<ZeroDivisionError: divided by 0>
|
382
|
+
|
383
|
+
# Leaking StandardError exceptions
|
384
|
+
Kind::Maybe[2].map! { |number| number / 0 } # ZeroDivisionError (divided by 0)
|
385
|
+
|
386
|
+
Kind::Maybe[2].then! { |number| number / 0 } # ZeroDivisionError (divided by 0)
|
387
|
+
```
|
388
|
+
|
389
|
+
* [#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.
|
390
|
+
```ruby
|
391
|
+
# Using built-in type checkers
|
392
|
+
Kind::String.value(1, default: '') # ""
|
393
|
+
Kind::String.value('1', default: '') # "1"
|
394
|
+
|
395
|
+
Kind::String.value('1', default: 1) # Kind::Error (1 expected to be a kind of String)
|
396
|
+
|
397
|
+
# Using custom type checkers
|
398
|
+
PositiveInteger = Kind::Of(-> value { value.kind_of?(Integer) && value > 0 }, name: 'PositiveInteger')
|
399
|
+
|
400
|
+
PositiveInteger.value(0, default: 1) # 1
|
401
|
+
PositiveInteger.value(2, default: 1) # 2
|
402
|
+
|
403
|
+
PositiveInteger.value(-1, default: 0) # Kind::Error (0 expected to be a kind of PositiveInteger)
|
404
|
+
```
|
405
|
+
|
406
|
+
* [#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.
|
407
|
+
```ruby
|
408
|
+
Kind::Array.value_or_empty({}) # []
|
409
|
+
Kind::Array.value_or_empty({}).frozen? # true
|
410
|
+
```
|
411
|
+
|
412
|
+
* [#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.
|
413
|
+
```ruby
|
414
|
+
Kind.value(String, '1', default: '') # "1"
|
415
|
+
|
416
|
+
Kind.value(String, 1, default: '') # ""
|
417
|
+
|
418
|
+
Kind.value(String, 1, default: 2) # Kind::Error (2 expected to be a kind of String)
|
419
|
+
```
|
420
|
+
|
421
|
+
* [#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:
|
422
|
+
```ruby
|
423
|
+
['', [], {}, '1', [2]].map(&Kind::Presence) # [nil, nil, nil, "1", [2]]
|
424
|
+
```
|
425
|
+
|
426
|
+
* [#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.
|
427
|
+
```ruby
|
428
|
+
some_number = Kind::Some(2)
|
429
|
+
|
430
|
+
Kind::Maybe(Numeric)[some_number] # #<Kind::Maybe::Some:0x0000... @value=2>
|
431
|
+
|
432
|
+
Kind::Maybe(Numeric).new(some_number) # #<Kind::Maybe::Some:0x0000... @value=2>
|
433
|
+
|
434
|
+
Kind::Maybe(Numeric).wrap(some_number) # #<Kind::Maybe::Some:0x0000... @value=2>
|
435
|
+
|
436
|
+
Kind::Maybe(Numeric).wrap { some_number } # #<Kind::Maybe::Some:0x0000... @value=2>
|
437
|
+
|
438
|
+
Kind::Maybe(Numeric).wrap(some_number) { |number| number / 2 } # #<Kind::Maybe::Some:0x0000... @value=1>
|
439
|
+
```
|
440
|
+
|
441
|
+
* [#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.
|
442
|
+
```ruby
|
443
|
+
Kind::Maybe(Numeric).wrap('2') { |number| number / 0 } # #<Kind::Maybe::None:0x0000... @value=nil>
|
444
|
+
|
445
|
+
Kind::Maybe(Numeric).wrap(2) { |number| number / 0 } # #<Kind::Maybe::None:0x0000... @value=#<ZeroDivisionError: divided by 0>>
|
446
|
+
```
|
447
|
+
|
448
|
+
* [#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.
|
449
|
+
```ruby
|
450
|
+
person_name = ->(params) do
|
451
|
+
Kind::Maybe(Hash)
|
452
|
+
.wrap(params)
|
453
|
+
.then { |hash| hash.values_at(:first_name, :last_name) }
|
454
|
+
.then { |names| names.map(&Kind::Presence).tap(&:compact!) }
|
455
|
+
.check { |names| names.size == 2 }
|
456
|
+
.then { |(first_name, last_name)| "#{first_name} #{last_name}" }
|
457
|
+
.value_or { 'John Doe' }
|
458
|
+
end
|
459
|
+
|
460
|
+
person_name.('') # "John Doe"
|
461
|
+
person_name.(nil) # "John Doe"
|
462
|
+
person_name.(last_name: 'Serradura') # "John Doe"
|
463
|
+
person_name.(first_name: 'Rodrigo') # "John Doe"
|
464
|
+
|
465
|
+
person_name.(first_name: 'Rodrigo', last_name: 'Serradura') # "Rodrigo Serradura"
|
466
|
+
```
|
467
|
+
|
468
|
+
* [#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.
|
469
|
+
```ruby
|
470
|
+
results = [
|
471
|
+
{ person: {} },
|
472
|
+
{ person: { name: 'Foo Bar'} },
|
473
|
+
{ person: { name: 'Rodrigo Serradura'} },
|
474
|
+
].map(&Kind::Dig[:person, :name])
|
475
|
+
|
476
|
+
p results # [nil, "Foo Bar", "Rodrigo Serradura"],
|
477
|
+
```
|
478
|
+
|
479
|
+
* [#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.
|
480
|
+
```ruby
|
481
|
+
results =
|
482
|
+
[
|
483
|
+
{},
|
484
|
+
{name: 'Foo Bar'},
|
485
|
+
{name: 'Rodrigo Serradura'},
|
486
|
+
].map(&Kind::Try[:fetch, :name, 'John Doe'])
|
487
|
+
|
488
|
+
p results # ["John Doe", "Foo Bar", "Rodrigo Serradura"]
|
489
|
+
```
|
490
|
+
|
491
|
+
### Deprecated
|
492
|
+
|
493
|
+
* [#40](https://github.com/serradura/kind/pull/40) - Deprecate `Kind::Is.call`
|
494
|
+
|
495
|
+
* [#40](https://github.com/serradura/kind/pull/40) - Deprecate `Kind::Of.call`
|
496
|
+
|
497
|
+
* [#40](https://github.com/serradura/kind/pull/40) - Deprecate `Kind::Types.add`.
|
498
|
+
|
499
|
+
* [#40](https://github.com/serradura/kind/pull/40) - Deprecate `Kind::Of::<Type>` and `Kind::Is::<Type>` modules.
|
500
|
+
|
501
|
+
* [#40](https://github.com/serradura/kind/pull/40) - Deprecate `Kind::Checker`, `Kind::Checker::Protocol`, `Kind::Checker::Factory`.
|
502
|
+
|
503
|
+
* [#40](https://github.com/serradura/kind/pull/40) - Deprecate the invocation of `Kind.is` without arguments.
|
504
|
+
|
505
|
+
* [#40](https://github.com/serradura/kind/pull/40) - Deprecate the invocation of `Kind.of` without arguments.
|
506
|
+
|
507
|
+
* [#40](https://github.com/serradura/kind/pull/40) - Deprecate the invocation of `Kind.of` with a single argument (the kind).
|
508
|
+
|
509
|
+
### Fixed
|
510
|
+
|
511
|
+
* [#40](https://github.com/serradura/kind/pull/40) - Make `Kind::Maybe.try!()` raises an error if it was called without a block or arguments.
|
512
|
+
|
513
|
+
[⬆️ Back to Top](#changelog-)
|
514
|
+
|
515
|
+
3.1.0 (2020-07-08)
|
516
|
+
------------------
|
517
|
+
|
518
|
+
### Added
|
519
|
+
|
520
|
+
* [#33](https://github.com/serradura/kind/pull/33) - Add new type checker.
|
521
|
+
- `Kind::Of::OpenStruct`, `Kind::Is::OpenStruct`
|
522
|
+
|
523
|
+
* [#33](https://github.com/serradura/kind/pull/33) - Add `Kind::Maybe::Result#dig`. It extracts the nested value in a sequence of objects, if any step returns `nil` the operation will stop and `None` will be returned, otherwise a `Some` will be returned with the final value.
|
524
|
+
```ruby
|
525
|
+
class User
|
526
|
+
def self.find_by(id:)
|
527
|
+
return :user_1 if id == 1
|
528
|
+
end
|
529
|
+
end
|
530
|
+
|
531
|
+
Kind::Optional(Hash).wrap(user: { id: 2 }).dig(:user).value # {:id=>2}
|
532
|
+
|
533
|
+
# --
|
534
|
+
|
535
|
+
user_id = Kind::Optional(Hash).wrap(user: { id: 1 }).dig(:user, :id)
|
536
|
+
|
537
|
+
user_id.then { |id| User.find_by(id: id) }.value # :user_id
|
538
|
+
```
|
539
|
+
|
540
|
+
* [#33](https://github.com/serradura/kind/pull/33) - Add the utility module `Kind::Dig`. It has the same behavior of Ruby dig methods ([Hash](https://ruby-doc.org/core-2.3.0/Hash.html#method-i-dig), [Array](https://ruby-doc.org/core-2.3.0/Array.html#method-i-dig), [Struct](https://ruby-doc.org/core-2.3.0/Struct.html#method-i-dig), [OpenStruct](https://ruby-doc.org/stdlib-2.3.0/libdoc/ostruct/rdoc/OpenStruct.html#method-i-dig)), but it will not raise an error if some step can't be digged.
|
541
|
+
```ruby
|
542
|
+
s = Struct.new(:a, :b).new(101, 102)
|
543
|
+
o = OpenStruct.new(c: 103, d: 104)
|
544
|
+
d = { struct: s, ostruct: o, data: [s, o]}
|
545
|
+
|
546
|
+
Kind::Dig.(s, [:a]) # 101
|
547
|
+
Kind::Dig.(o, [:c]) # 103
|
548
|
+
|
549
|
+
Kind::Dig.(d, [:struct, :b]) # 102
|
550
|
+
Kind::Dig.(d, [:data, 0, :b]) # 102
|
551
|
+
Kind::Dig.(d, [:data, 0, 'b']) # 102
|
552
|
+
|
553
|
+
Kind::Dig.(d, [:ostruct, :d]) # 104
|
554
|
+
Kind::Dig.(d, [:data, 1, :d]) # 104
|
555
|
+
Kind::Dig.(d, [:data, 1, 'd']) # 104
|
556
|
+
|
557
|
+
Kind::Dig.(d, [:struct, :f]) # nil
|
558
|
+
Kind::Dig.(d, [:ostruct, :f]) # nil
|
559
|
+
Kind::Dig.(d, [:data, 0, :f]) # nil
|
560
|
+
Kind::Dig.(d, [:data, 1, :f]) # nil
|
561
|
+
```
|
562
|
+
|
563
|
+
[⬆️ Back to Top](#changelog-)
|
564
|
+
|
565
|
+
3.0.0 (2020-06-25)
|
566
|
+
------------------
|
567
|
+
|
568
|
+
### Breaking Changes
|
569
|
+
|
570
|
+
* [#31](https://github.com/serradura/kind/pull/31) - Change the `Kind::Maybe::Result#try()` behavior.
|
571
|
+
- If you don't want to use the methods `#map`/`#then` to access some value inside of the monad, you could use the `#try` method to do this. It 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. So, if the value wasn't `nil` or `Kind::Undefined` a `Some` will be returned.
|
572
|
+
```ruby
|
573
|
+
# Examples using Kind::Maybe
|
574
|
+
|
575
|
+
Kind::Maybe['foo'].try(:upcase).value # "FOO"
|
576
|
+
|
577
|
+
Kind::Maybe[{}].try(:fetch, :number, 0).value # 0
|
578
|
+
|
579
|
+
Kind::Maybe[{number: 1}].try(:fetch, :number).value # 1
|
580
|
+
|
581
|
+
Kind::Maybe[' foo '].try { |value| value.strip }.value # "foo"
|
582
|
+
|
583
|
+
# Examples using Kind::Optional
|
584
|
+
|
585
|
+
Kind::Optional[1].try(:strip).value_or('') # ""
|
586
|
+
|
587
|
+
Kind::Optional[' Rodrigo '].try(:strip).value_or("") # 'Rodrigo'
|
588
|
+
```
|
589
|
+
|
590
|
+
### Added
|
591
|
+
|
592
|
+
* [#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.
|
593
|
+
```ruby
|
594
|
+
Kind::Maybe[{}].try(:upcase) # => #<Kind::Maybe::None:0x0000... @value=nil>
|
595
|
+
|
596
|
+
Kind::Maybe[{}].try!(:upcase) # => NoMethodError (undefined method `upcase' for {}:Hash)
|
597
|
+
```
|
598
|
+
|
599
|
+
[⬆️ Back to Top](#changelog-)
|
600
|
+
|
601
|
+
2.3.0 (2020-06-24)
|
602
|
+
------------------
|
603
|
+
|
604
|
+
### Added
|
605
|
+
|
606
|
+
* [#30](https://github.com/serradura/kind/pull/30) - Add `Kind::Maybe.wrap()` as an alias for `Kind::Maybe.new()`.
|
607
|
+
|
608
|
+
* [#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.
|
609
|
+
```ruby
|
610
|
+
Double = ->(arg) do
|
611
|
+
Kind::Optional(Numeric)
|
612
|
+
.wrap(arg)
|
613
|
+
.then { |number| number * 2 }
|
614
|
+
end
|
615
|
+
```
|
616
|
+
|
617
|
+
[⬆️ Back to Top](#changelog-)
|
618
|
+
|
619
|
+
2.2.0 (2020-06-23)
|
620
|
+
------------------
|
621
|
+
|
622
|
+
### Added
|
623
|
+
|
624
|
+
* [#29](https://github.com/serradura/kind/pull/29) - Improve the comparison of values with `Kind::Undefined`.
|
625
|
+
- 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.
|
626
|
+
|
627
|
+
[⬆️ Back to Top](#changelog-)
|
628
|
+
|
629
|
+
2.1.0 (2020-05-12)
|
630
|
+
------------------
|
631
|
+
|
632
|
+
### Added
|
633
|
+
|
634
|
+
* [#28](https://github.com/serradura/kind/pull/28) - Allow passing multiple arguments to `Kind.of.<Type>.instance?(*args)`
|
635
|
+
|
636
|
+
* [#28](https://github.com/serradura/kind/pull/28) - Allow passing multiple arguments to `Kind.of.<Type>?(*args)`
|
637
|
+
|
638
|
+
* [#28](https://github.com/serradura/kind/pull/28) - Add `Kind::Some()` and `Kind::None()`. e.g:
|
639
|
+
```ruby
|
640
|
+
Double = ->(arg) do
|
641
|
+
number = Kind::Of::Numeric.or_nil(arg)
|
642
|
+
|
643
|
+
Kind::Optional[number].then { |number| number * 2 }
|
644
|
+
end
|
645
|
+
|
646
|
+
Add = -> params do
|
647
|
+
a, b = Kind::Of::Hash(params, or: Empty::HASH).values_at(:a, :b)
|
648
|
+
|
649
|
+
return Kind::None unless Kind::Of::Numeric?(a, b)
|
650
|
+
|
651
|
+
Kind::Some(a + b)
|
652
|
+
end
|
653
|
+
|
654
|
+
Kind::Optional[a: 1, b: 2].then(&Add).value_or(0) # 3
|
655
|
+
|
656
|
+
Add.({}).some? # false
|
657
|
+
|
658
|
+
Add.(a: 1, b: '2').some? # false
|
659
|
+
|
660
|
+
Add.(a: 2, b: 2).then(&Double).value # 8
|
661
|
+
```
|
662
|
+
|
663
|
+
* [#28](https://github.com/serradura/kind/pull/28) - Add `Kind.of?(<Type>, *args)` to check if one or many values are the expected kind.
|
664
|
+
```ruby
|
665
|
+
Kind.of?(Numeric, 1, 2.0, 3) # true
|
666
|
+
Kind.of?(Numeric, 1, '2', 3) # false
|
667
|
+
```
|
668
|
+
|
669
|
+
* [#28](https://github.com/serradura/kind/pull/28) - Make the `Kind.of?(<Type>)` returns a lambda that knows how to do the type verification.
|
670
|
+
```ruby
|
671
|
+
[1, '2', 3].select(&Kind.of?(Numeric)) # [1, 3]
|
672
|
+
```
|
673
|
+
|
674
|
+
### Breaking Changes
|
675
|
+
|
676
|
+
* [#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.
|
677
|
+
```ruby
|
678
|
+
[1, 2, 3].map(&Kind::Of::Numeric) # [1, 2, 3]
|
679
|
+
|
680
|
+
[1, '2', 3].map(&Kind::Of::Numeric) # Kind::Error ("2" expected to be a kind of Numeric)
|
681
|
+
|
682
|
+
[1, '2', 3].select(&Kind::Of::Numeric?) # [1, 3]
|
683
|
+
```
|
684
|
+
|
685
|
+
[⬆️ Back to Top](#changelog-)
|
686
|
+
|
687
|
+
2.0.0 (2020-05-07)
|
688
|
+
------------------
|
689
|
+
|
690
|
+
### Added
|
691
|
+
|
692
|
+
* [#24](https://github.com/serradura/kind/pull/24) - Improve the `kind: { is: }` validation to check the inheritance of *classes*/*modules*.
|
693
|
+
|
694
|
+
### Breaking Changes
|
695
|
+
|
696
|
+
* [#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)`.
|
697
|
+
|
698
|
+
### Removed
|
699
|
+
|
700
|
+
* [#24](https://github.com/serradura/kind/pull/24) - Remove `kind: { is_a: }` from `Kind::Validator`.
|
701
|
+
* [#24](https://github.com/serradura/kind/pull/24) - Remove `kind: { klass: }` from `Kind::Validator`.
|
702
|
+
|
703
|
+
[⬆️ Back to Top](#changelog-)
|
704
|
+
|
705
|
+
1.9.0 (2020-05-06)
|
706
|
+
------------------
|
707
|
+
|
708
|
+
### Added
|
709
|
+
|
710
|
+
* [#23](https://github.com/serradura/kind/pull/23) - Add `Kind.of.<Type>.to_proc` as an alias for `Kind.of.<Type>.instance?`.
|
711
|
+
```ruby
|
712
|
+
collection = [
|
713
|
+
{number: 1},
|
714
|
+
'number 0',
|
715
|
+
{number: 2},
|
716
|
+
[0],
|
717
|
+
]
|
718
|
+
|
719
|
+
collection
|
720
|
+
.select(&Kind.of.Hash)
|
721
|
+
.reduce(0) { |total, item| total + item[:number] }
|
722
|
+
```
|
723
|
+
|
724
|
+
* [#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).
|
725
|
+
```ruby
|
726
|
+
require 'kind/active_model/validation'
|
727
|
+
|
728
|
+
class Person
|
729
|
+
include ActiveModel::Validations
|
730
|
+
|
731
|
+
attr_reader :name, :age
|
732
|
+
|
733
|
+
validates :name, kind: { of: String }
|
734
|
+
validates :age, kind: { of: Integer }
|
735
|
+
|
736
|
+
def initialize(name:, age:)
|
737
|
+
@name, @age = name, age
|
738
|
+
end
|
739
|
+
end
|
740
|
+
|
741
|
+
person = Person.new(name: 'John', age: '21')
|
742
|
+
|
743
|
+
person.valid? # false
|
744
|
+
|
745
|
+
person.errors[:age] # ['must be a kind of: Integer']
|
746
|
+
```
|
747
|
+
|
748
|
+
[⬆️ Back to Top](#changelog-)
|
749
|
+
|
750
|
+
1.8.0 (2020-05-03)
|
751
|
+
------------------
|
752
|
+
|
753
|
+
### Added
|
754
|
+
|
755
|
+
* [#22](https://github.com/serradura/kind/pull/22) - `Kind.of.<Type>.instance?`returns a lambda when called without an argument.
|
756
|
+
```ruby
|
757
|
+
collection = [
|
758
|
+
{number: 1},
|
759
|
+
'number 0',
|
760
|
+
{number: 2},
|
761
|
+
[0],
|
762
|
+
]
|
763
|
+
|
764
|
+
collection
|
765
|
+
.select(&Kind::Of::Hash.instance?)
|
766
|
+
.reduce(0) { |total, item| total + item[:number] }
|
767
|
+
```
|
768
|
+
|
769
|
+
* [#22](https://github.com/serradura/kind/pull/22) - Add new methods `.as_optional`, `.as_maybe` in the type checkers.
|
770
|
+
```ruby
|
771
|
+
def person_name(params)
|
772
|
+
Kind::Of::Hash
|
773
|
+
.as_optional(params)
|
774
|
+
.map { |data| data.values_at(:first_name, :last_name).compact }
|
775
|
+
.map { |first, last| "#{first} #{last}" if first && last }
|
776
|
+
.value_or { 'John Doe' }
|
777
|
+
end
|
778
|
+
|
779
|
+
person_name('') # "John Doe"
|
780
|
+
person_name(nil) # "John Doe"
|
781
|
+
person_name(first_name: 'Rodrigo') # "John Doe"
|
782
|
+
person_name(last_name: 'Serradura') # "John Doe"
|
783
|
+
person_name(first_name: 'Rodrigo', last_name: 'Serradura') # "Rodrigo Serradura"
|
784
|
+
|
785
|
+
# A lambda will be returned if these methods receive only one argument
|
786
|
+
|
787
|
+
collection = [
|
788
|
+
{number: 1},
|
789
|
+
'number 0',
|
790
|
+
{number: 2},
|
791
|
+
[0],
|
792
|
+
]
|
793
|
+
|
794
|
+
collection
|
795
|
+
.map(&Kind.of.Hash.as_optional)
|
796
|
+
.select(&:some?)
|
797
|
+
.reduce(0) { |total, item| total + item.value[:number] }
|
798
|
+
```
|
799
|
+
|
800
|
+
[⬆️ Back to Top](#changelog-)
|
801
|
+
|
802
|
+
1.7.0 (2020-05-03)
|
803
|
+
------------------
|
804
|
+
|
805
|
+
### Fixed
|
806
|
+
|
807
|
+
* [#20](https://github.com/serradura/kind/pull/20) - Fix the verification of modules using `Kind.is()`.
|
808
|
+
|
809
|
+
[⬆️ Back to Top](#changelog-)
|
810
|
+
|
811
|
+
1.6.0 (2020-04-17)
|
812
|
+
------------------
|
813
|
+
|
814
|
+
### Added
|
815
|
+
|
816
|
+
* [#19](https://github.com/serradura/kind/pull/19) - Add aliases to perform the strict type verification (in registered type checkers).
|
817
|
+
```ruby
|
818
|
+
# Kind.of.<Type>[]
|
819
|
+
|
820
|
+
Kind.of.Hash[nil] # raise Kind::Error, "nil expected to be a kind of Hash"
|
821
|
+
Kind.of.Hash[''] # raise Kind::Error, "'' expected to be a kind of Hash"
|
822
|
+
Kind.of.Hash[a: 1] # {a: 1}
|
823
|
+
Kind.of.Hash['', or: {}] # {}
|
824
|
+
|
825
|
+
# Kind.of.<Type>.instance()
|
826
|
+
|
827
|
+
Kind.of.Array.instance(nil) # raise Kind::Error, "nil expected to be a kind of Array"
|
828
|
+
Kind.of.Array.instance('') # raise Kind::Error, "'' expected to be a kind of Array"
|
829
|
+
Kind.of.Array.instance([]) # []
|
830
|
+
Kind.of.Array.instance('', or: []) # []
|
831
|
+
```
|
832
|
+
|
833
|
+
* [#19](https://github.com/serradura/kind/pull/19) - Add `.or_undefined` method for any type checker.
|
834
|
+
```ruby
|
835
|
+
Kind.of.String.or_undefined(nil) # Kind::Undefined
|
836
|
+
Kind.of.String.or_undefined("something") # "something"
|
837
|
+
```
|
838
|
+
|
839
|
+
* [#19](https://github.com/serradura/kind/pull/19) - Allow a dynamical verification of types.
|
840
|
+
```ruby
|
841
|
+
class User
|
842
|
+
end
|
843
|
+
|
844
|
+
class AdminUser < User
|
845
|
+
end
|
846
|
+
|
847
|
+
Kind.of(User, User.new) # #<User:0x0000...>
|
848
|
+
Kind.of(User, {}) # Kind::Error ({} expected to be a kind of User)
|
849
|
+
```
|
850
|
+
|
851
|
+
* [#19](https://github.com/serradura/kind/pull/19) - Allow the creation of type checkers dynamically (without register one).
|
852
|
+
```ruby
|
853
|
+
class User
|
854
|
+
end
|
855
|
+
|
856
|
+
kind_of_user = Kind.of(User)
|
857
|
+
|
858
|
+
kind_of_user[{}] # Kind::Error ({} expected to be a kind of User)
|
859
|
+
kind_of_user[User.new] # #<User:0x0000...>
|
860
|
+
|
861
|
+
kind_of_user.instance({}) # Kind::Error ({} expected to be a kind of User)
|
862
|
+
kind_of_user.instance(User.new) # #<User:0x0000...>
|
863
|
+
|
864
|
+
kind_of_user.instance?({}) # false
|
865
|
+
kind_of_user.instance?(User.new) # true
|
866
|
+
|
867
|
+
kind_of_user.class?(Hash) # false
|
868
|
+
kind_of_user.class?(User) # true
|
869
|
+
|
870
|
+
kind_of_user.or_undefined({}) # Kind::Undefined
|
871
|
+
kind_of_user.or_undefined(User.new) # #<User:0x0000...>
|
872
|
+
```
|
873
|
+
|
874
|
+
* [#19](https://github.com/serradura/kind/pull/19) - Add a new type checkers.
|
875
|
+
- `Kind::Of::Set`
|
876
|
+
- `Kind::Of::Maybe`, `Kind::Of::Optional`
|
877
|
+
|
878
|
+
* [#19](https://github.com/serradura/kind/pull/19) - Add `Kind::Empty` with several constants having empty frozen objects.
|
879
|
+
```ruby
|
880
|
+
Kind::Empty::SET
|
881
|
+
Kind::Empty::HASH
|
882
|
+
Kind::Empty::ARRAY
|
883
|
+
Kind::Empty::STRING
|
884
|
+
|
885
|
+
# If there isn't any constant named as Empty, the gem will use it to create an alias for Kind::Empty.
|
886
|
+
|
887
|
+
Empty::SET == Kind::Empty::SET
|
888
|
+
Empty::HASH == Kind::Empty::HASH
|
889
|
+
Empty::ARRAY == Kind::Empty::ARRAY
|
890
|
+
Empty::STRING == Kind::Empty::STRING
|
891
|
+
```
|
892
|
+
|
893
|
+
### Changes
|
894
|
+
|
895
|
+
* [#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"`
|
896
|
+
```ruby
|
897
|
+
Kind::Undefined.to_s # "Kind::Undefined"
|
898
|
+
Kind::Undefined.inspect # "Kind::Undefined"
|
899
|
+
```
|
900
|
+
|
901
|
+
[⬆️ Back to Top](#changelog-)
|
902
|
+
|
903
|
+
1.5.0 (2020-04-12)
|
904
|
+
------------------
|
905
|
+
|
906
|
+
### Added
|
907
|
+
|
908
|
+
* [#18](https://github.com/serradura/kind/pull/18) - Refactor `Kind::Maybe`.
|
909
|
+
|
910
|
+
* [#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`.
|
911
|
+
```ruby
|
912
|
+
Kind::Maybe::Value.some?(1) # true
|
913
|
+
Kind::Maybe::Value.some?(nil) # false
|
914
|
+
Kind::Maybe::Value.some?(Kind::Undefined) # false
|
915
|
+
|
916
|
+
Kind::Maybe::Value.none?(1) # false
|
917
|
+
Kind::Maybe::Value.none?(nil) # true
|
918
|
+
Kind::Maybe::Value.none?(Kind::Undefined) # true
|
919
|
+
```
|
920
|
+
|
921
|
+
[⬆️ Back to Top](#changelog-)
|
922
|
+
|
923
|
+
1.4.0 (2020-04-12)
|
924
|
+
------------------
|
925
|
+
|
926
|
+
### Added
|
927
|
+
|
928
|
+
* [#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`.
|
929
|
+
|
930
|
+
[⬆️ Back to Top](#changelog-)
|
931
|
+
|
932
|
+
1.3.0 (2020-04-12)
|
933
|
+
------------------
|
934
|
+
|
935
|
+
### Added
|
936
|
+
|
937
|
+
* [#16](https://github.com/serradura/kind/pull/16) - Add a new special type checkers.
|
938
|
+
- `Kind::Of::Callable` for check if the given object respond to `call`.
|
939
|
+
- `Kind::Is::Callable` if the given value is a `class`, it will verifies if its `public_instance_methods.include?(:call)`.
|
940
|
+
|
941
|
+
[⬆️ Back to Top](#changelog-)
|
942
|
+
|
943
|
+
1.2.0 (2020-04-12)
|
944
|
+
------------------
|
945
|
+
|
946
|
+
### Added
|
947
|
+
|
948
|
+
* [#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.
|
949
|
+
```ruby
|
950
|
+
# Some value
|
951
|
+
|
952
|
+
optional =
|
953
|
+
Kind::Optional.new(2)
|
954
|
+
.map { |value| value * 2 }
|
955
|
+
.map { |value| value * 2 }
|
956
|
+
|
957
|
+
puts optional.value # 8
|
958
|
+
puts optional.some? # true
|
959
|
+
puts optional.none? # false
|
960
|
+
|
961
|
+
puts optional.value_or(0) # 8
|
962
|
+
puts optional.value_or { 0 } # 8
|
963
|
+
|
964
|
+
# None value
|
965
|
+
|
966
|
+
even_number = Kind::Optional.new(3).map { |n| n if n.even? }
|
967
|
+
|
968
|
+
even_number.none? # true
|
969
|
+
|
970
|
+
even_number.value_or(0) # 0
|
971
|
+
|
972
|
+
# Utility method
|
973
|
+
|
974
|
+
# Kind::Optional#try
|
975
|
+
# You could use the `#try` method to perform a method of the wrapped object and return its value.
|
976
|
+
|
977
|
+
Kind::Optional.new(' Rodrigo ').try(:strip) # "Rodrigo"
|
978
|
+
|
979
|
+
# Method aliases
|
980
|
+
|
981
|
+
# Kind::Optional[] is an alias for Kind::Optional.new
|
982
|
+
Kind::Optional[2].map { |n| n if n.even? }.value_or(0) # 2
|
983
|
+
|
984
|
+
# Kind::Optional::Result#then is an alias for Kind::Optional::Result#map
|
985
|
+
Kind::Optional[1].then { |n| n if n.even? }.value_or(0) # 0
|
986
|
+
```
|
987
|
+
|
988
|
+
* [#15](https://github.com/serradura/kind/pull/15) - Add new methods to `Kind::Undefined`.
|
989
|
+
```ruby
|
990
|
+
Kind::Undefined.to_s # 'Undefined'
|
991
|
+
Kind::Undefined.inspect # 'Undefined'
|
992
|
+
|
993
|
+
Kind::Undefined.clone # #<Kind::Undefined:0x0000...>
|
994
|
+
Kind::Undefined.dup # #<Kind::Undefined:0x0000...>
|
995
|
+
|
996
|
+
Kind::Undefined.clone == Kind::Undefined # true
|
997
|
+
Kind::Undefined.clone === Kind::Undefined # true
|
998
|
+
|
999
|
+
Kind::Undefined.dup == Kind::Undefined # true
|
1000
|
+
Kind::Undefined.dup === Kind::Undefined # true
|
1001
|
+
|
1002
|
+
value = Kind::Undefined
|
1003
|
+
|
1004
|
+
Kind::Undefined.default(value, 1) # 1
|
1005
|
+
```
|
1006
|
+
|
1007
|
+
[⬆️ Back to Top](#changelog-)
|
1008
|
+
|
1009
|
+
1.1.0 (2020-04-09)
|
1010
|
+
------------------
|
1011
|
+
|
1012
|
+
### Added
|
1013
|
+
|
1014
|
+
* [#14](https://github.com/serradura/kind/pull/14) - Add `Kind::Undefined` representing an undefined value to contrast with `nil`.
|
1015
|
+
|
1016
|
+
### Fixed
|
1017
|
+
|
1018
|
+
* [#14](https://github.com/serradura/kind/pull/14) - Raise a `Kind::Error` if `nil` is the argument of any strict type checker.
|
1019
|
+
```ruby
|
1020
|
+
Kind.of.Hash(nil) # raise Kind::Error, "nil expected to be a kind of Hash"
|
1021
|
+
```
|
1022
|
+
|
1023
|
+
[⬆️ Back to Top](#changelog-)
|
1024
|
+
|
1025
|
+
1.0.0 (2020-03-16)
|
1026
|
+
------------------
|
1027
|
+
|
1028
|
+
### Added
|
1029
|
+
|
1030
|
+
* [#12](https://github.com/serradura/kind/pull/12) - Register type checkers respecting their namespaces.
|
1031
|
+
```ruby
|
1032
|
+
module Account
|
1033
|
+
class User
|
1034
|
+
Kind::Types.add(self)
|
1035
|
+
end
|
1036
|
+
end
|
1037
|
+
|
1038
|
+
module Account
|
1039
|
+
class User
|
1040
|
+
class Membership
|
1041
|
+
Kind::Types.add(self)
|
1042
|
+
end
|
1043
|
+
end
|
1044
|
+
end
|
1045
|
+
|
1046
|
+
account_user = Account::User.new
|
1047
|
+
|
1048
|
+
Kind.of.Account::User(account_user) # #<Account::User:0x0000...>
|
1049
|
+
Kind.of.Account::User({}) # Kind::Error ({} expected to be a kind of Account::User)
|
1050
|
+
|
1051
|
+
Kind.of.Account::User.or_nil({}) # nil
|
1052
|
+
|
1053
|
+
Kind.of.Account::User.instance?({}) # false
|
1054
|
+
Kind.of.Account::User.instance?(account_user) # true
|
1055
|
+
|
1056
|
+
Kind.of.Account::User.class?(Hash) # false
|
1057
|
+
Kind.of.Account::User.class?(Account::User) # true
|
1058
|
+
|
1059
|
+
# ---
|
1060
|
+
|
1061
|
+
membership = Account::User::Membership.new
|
1062
|
+
|
1063
|
+
Kind.of.Account::User::Membership(membership) # #<Account::User::Membership:0x0000...>
|
1064
|
+
Kind.of.Account::User::Membership({}) # Kind::Error ({} expected to be a kind of Account::User::Membership)
|
1065
|
+
|
1066
|
+
Kind.of.Account::User::Membership.or_nil({}) # nil
|
1067
|
+
|
1068
|
+
Kind.of.Account::User::Membership.instance?({}) # false
|
1069
|
+
Kind.of.Account::User::Membership.instance?(membership) # true
|
1070
|
+
|
1071
|
+
Kind.of.Account::User::Membership.class?(Hash) # false
|
1072
|
+
Kind.of.Account::User::Membership.class?(Account::User::Membership) # true
|
1073
|
+
```
|
1074
|
+
|
1075
|
+
[⬆️ Back to Top](#changelog-)
|
1076
|
+
|
1077
|
+
0.6.0 (2020-01-06)
|
1078
|
+
------------------
|
1079
|
+
|
1080
|
+
### Added
|
1081
|
+
|
1082
|
+
* [#11](https://github.com/serradura/kind/pull/11) - Register the `Queue` (`Thread::Queue`) type checker. This registering creates:
|
1083
|
+
- `Kind::Of::Queue`, `Kind::Is::Queue`
|
1084
|
+
|
1085
|
+
[⬆️ Back to Top](#changelog-)
|
1086
|
+
|
1087
|
+
0.5.0 (2020-01-04)
|
1088
|
+
------------------
|
1089
|
+
|
1090
|
+
### Added
|
1091
|
+
|
1092
|
+
* [#4](https://github.com/serradura/kind/pull/4) - Allow defining a default value when the verified object is `nil`.
|
1093
|
+
```ruby
|
1094
|
+
Kind.of.Hash(nil, or: {}) # {}
|
1095
|
+
```
|
1096
|
+
|
1097
|
+
[⬆️ Back to Top](#changelog-)
|
1098
|
+
|
1099
|
+
0.4.0 (2020-01-03)
|
1100
|
+
------------------
|
1101
|
+
|
1102
|
+
### Added
|
1103
|
+
|
1104
|
+
* [#3](https://github.com/serradura/kind/pull/3) - Require `2.2.0` as the minimum Ruby version.
|
1105
|
+
|
1106
|
+
[⬆️ Back to Top](#changelog-)
|
1107
|
+
|
1108
|
+
0.3.0 (2020-01-03)
|
1109
|
+
------------------
|
1110
|
+
|
1111
|
+
### Added
|
1112
|
+
|
1113
|
+
* [#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)
|
1114
|
+
```ruby
|
1115
|
+
class User
|
1116
|
+
end
|
1117
|
+
|
1118
|
+
user = User.new
|
1119
|
+
|
1120
|
+
UserKind = Kind::Checker.new(User)
|
1121
|
+
|
1122
|
+
UserKind.class?(User) # true
|
1123
|
+
UserKind.class?(String) # false
|
1124
|
+
|
1125
|
+
UserKind.instance?(user) # true
|
1126
|
+
UserKind.instance?(1) # false
|
1127
|
+
|
1128
|
+
UserKind.or_nil(user) # #<User:0x0000...>
|
1129
|
+
UserKind.or_nil(1) # nil
|
1130
|
+
```
|
1131
|
+
|
1132
|
+
### Breaking Changes
|
1133
|
+
|
1134
|
+
* [#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.
|
1135
|
+
|
1136
|
+
[⬆️ Back to Top](#changelog-)
|
1137
|
+
|
1138
|
+
0.2.0 (2020-01-02)
|
1139
|
+
------------------
|
1140
|
+
|
1141
|
+
### Added
|
1142
|
+
|
1143
|
+
* [#1](https://github.com/serradura/kind/pull/1) - Register type checkers for several Ruby classes/modules. (PR: #1)
|
1144
|
+
- **Classes:**
|
1145
|
+
- `Kind::Of::Symbol` , `Kind::Is::Symbol`
|
1146
|
+
- `Kind::Of::Numeric` , `Kind::Is::Numeric`
|
1147
|
+
- `Kind::Of::Integer` , `Kind::Is::Integer`
|
1148
|
+
- `Kind::Of::Float` , `Kind::Is::Float`
|
1149
|
+
- `Kind::Of::Regexp` , `Kind::Is::Regexp`
|
1150
|
+
- `Kind::Of::Time` , `Kind::Is::Time`
|
1151
|
+
- `Kind::Of::Array` , `Kind::Is::Array`
|
1152
|
+
- `Kind::Of::Range` , `Kind::Is::Range`
|
1153
|
+
- `Kind::Of::Hash` , `Kind::Is::Hash`
|
1154
|
+
- `Kind::Of::Struct` , `Kind::Is::Struct`
|
1155
|
+
- `Kind::Of::Enumerator`, `Kind::Is::Enumerator`
|
1156
|
+
- `Kind::Of::Method` , `Kind::Is::Method`
|
1157
|
+
- `Kind::Of::Proc` , `Kind::Is::Proc`
|
1158
|
+
- `Kind::Of::IO` , `Kind::Is::IO`
|
1159
|
+
- `Kind::Of::File` , `Kind::Is::File`
|
1160
|
+
- **Modules:**
|
1161
|
+
- `Kind::Of::Enumerable`, `Kind::Is::Enumerable`
|
1162
|
+
- `Kind::Of::Comparable`, `Kind::Is::Comparable`
|
1163
|
+
|
1164
|
+
* [#1](https://github.com/serradura/kind/pull/1) - Create special type checkers.
|
1165
|
+
- `Kind::Of::Boolean` for check if the given object is `true` or `false`.
|
1166
|
+
- `Kind::Of::Lambda` for check if the given object is a `lambda`.
|
1167
|
+
- `Kind::Of::Module` for check if the given object is a *module*.
|
1168
|
+
|
1169
|
+
[⬆️ Back to Top](#changelog-)
|
1170
|
+
|
1171
|
+
0.1.0 (2019-12-26)
|
1172
|
+
------------------
|
1173
|
+
|
1174
|
+
### Added
|
1175
|
+
|
1176
|
+
* Require `2.3.0` as the minimum Ruby version.
|
1177
|
+
|
1178
|
+
* `Kind::Error` for defining type checkers errors.
|
1179
|
+
|
1180
|
+
* `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.
|
1181
|
+
```ruby
|
1182
|
+
Kind::Of.(String, '') # ''
|
1183
|
+
Kind::Of.(String, 1) # Kind::Error (1 expected to be a kind of String)
|
1184
|
+
```
|
1185
|
+
|
1186
|
+
* `Kind::Of::Class()` for check if the given object is a *class*.
|
1187
|
+
|
1188
|
+
* `Kind::Is.call()` for check if the first kind is equal or a parent class/module of the second one.
|
1189
|
+
```ruby
|
1190
|
+
Kind::Is.(String, String) # true
|
1191
|
+
Kind::Is.(Symbol, String) # false
|
1192
|
+
```
|
1193
|
+
|
1194
|
+
* `Kind.of` is a shortcut for `Kind::Of`.
|
1195
|
+
|
1196
|
+
* `Kind.is` is a shortcut for `Kind::Is`.
|
1197
|
+
|
1198
|
+
* `Kind::Types.add` allows the registering of new type checkers.
|
1199
|
+
```ruby
|
1200
|
+
# Registering Symbol
|
1201
|
+
|
1202
|
+
Kind::Type.add(Symbol)
|
1203
|
+
|
1204
|
+
# Adds a method in the Kind::Is module
|
1205
|
+
|
1206
|
+
class MySymbol < Symbol
|
1207
|
+
end
|
1208
|
+
|
1209
|
+
Kind.is.Symbol(Symbol) # true
|
1210
|
+
Kind.is.Symbol(MySymbol) # true
|
1211
|
+
Kind.is.Symbol(String) # false
|
1212
|
+
|
1213
|
+
# Adds a method in the Kind::Of module
|
1214
|
+
|
1215
|
+
Kind.of.Symbol(:a) # :a
|
1216
|
+
Kind.of.Symbol(1) # Kind::Error (1 expected to be a kind of Symbol)
|
1217
|
+
|
1218
|
+
# Creates a module in Kind::Of with type checking methods related to the given kind.
|
1219
|
+
|
1220
|
+
Kind::Of::Symbol.class?(Symbol) # true
|
1221
|
+
Kind::Of::Symbol.instance?(:a) # true
|
1222
|
+
Kind::Of::Symbol.or_nil(:b) # :b
|
1223
|
+
Kind::Of::Symbol.or_nil(1) # nil
|
1224
|
+
```
|
1225
|
+
|
1226
|
+
* Register the `String` and `Hash` type checkers. This registering creates:
|
1227
|
+
- `Kind::Of::Hash`, `Kind::Is::Hash`
|
1228
|
+
- `Kind::Of::String`, `Kind::Is::String`
|
1229
|
+
|
1230
|
+
[⬆️ Back to Top](#changelog-)
|