kind 4.0.0 → 5.3.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 -1
- data/.travis.sh +39 -7
- data/.travis.yml +1 -2
- data/CHANGELOG.md +486 -28
- data/Gemfile +13 -6
- data/README.md +153 -49
- data/kind.gemspec +1 -1
- data/lib/kind.rb +2 -84
- data/lib/kind/__lib__/action_steps.rb +57 -0
- data/lib/kind/__lib__/attributes.rb +66 -0
- data/lib/kind/__lib__/kind.rb +51 -0
- data/lib/kind/__lib__/of.rb +17 -0
- data/lib/kind/__lib__/strict.rb +49 -0
- data/lib/kind/__lib__/undefined.rb +14 -0
- data/lib/kind/action.rb +127 -0
- data/lib/kind/active_model/validation.rb +3 -4
- data/lib/kind/basic.rb +79 -0
- data/lib/kind/basic/error.rb +29 -0
- data/lib/kind/{undefined.rb → basic/undefined.rb} +6 -1
- data/lib/kind/dig.rb +21 -5
- data/lib/kind/either.rb +30 -0
- data/lib/kind/either/left.rb +29 -0
- data/lib/kind/either/methods.rb +17 -0
- data/lib/kind/either/monad.rb +65 -0
- data/lib/kind/either/monad/wrapper.rb +19 -0
- data/lib/kind/either/right.rb +38 -0
- data/lib/kind/empty.rb +2 -2
- data/lib/kind/empty/constant.rb +7 -0
- data/lib/kind/enum.rb +63 -0
- data/lib/kind/enum/item.rb +40 -0
- data/lib/kind/enum/methods.rb +72 -0
- data/lib/kind/function.rb +45 -0
- data/lib/kind/functional.rb +89 -0
- data/lib/kind/functional/action.rb +90 -0
- data/lib/kind/immutable_attributes.rb +34 -0
- data/lib/kind/immutable_attributes/initializer.rb +70 -0
- data/lib/kind/immutable_attributes/reader.rb +38 -0
- data/lib/kind/maybe.rb +37 -12
- data/lib/kind/maybe/methods.rb +21 -0
- data/lib/kind/maybe/monad.rb +82 -0
- data/lib/kind/maybe/monad/wrapper.rb +19 -0
- data/lib/kind/maybe/none.rb +12 -19
- data/lib/kind/maybe/some.rb +68 -26
- data/lib/kind/maybe/typed.rb +11 -5
- data/lib/kind/maybe/{wrappable.rb → wrapper.rb} +9 -7
- data/lib/kind/monad.rb +22 -0
- data/lib/kind/monads.rb +5 -0
- data/lib/kind/objects.rb +17 -0
- data/lib/kind/objects/basic_object.rb +43 -0
- data/lib/kind/objects/modules.rb +32 -0
- data/lib/kind/{type_checkers → objects/modules}/core/array.rb +3 -1
- data/lib/kind/{type_checkers → objects/modules}/core/class.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/comparable.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/enumerable.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/enumerator.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/file.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/float.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/hash.rb +3 -1
- data/lib/kind/{type_checkers → objects/modules}/core/integer.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/io.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/method.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/module.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/numeric.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/proc.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/queue.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/range.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/regexp.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/string.rb +3 -1
- data/lib/kind/{type_checkers → objects/modules}/core/struct.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/symbol.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/time.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/custom/boolean.rb +2 -2
- data/lib/kind/{type_checkers → objects/modules}/custom/callable.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/custom/lambda.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/stdlib/open_struct.rb +3 -1
- data/lib/kind/{type_checkers → objects/modules}/stdlib/set.rb +3 -1
- data/lib/kind/objects/nil.rb +17 -0
- data/lib/kind/objects/not_nil.rb +9 -0
- data/lib/kind/objects/object.rb +56 -0
- data/lib/kind/objects/respond_to.rb +30 -0
- data/lib/kind/objects/union_type.rb +44 -0
- data/lib/kind/presence.rb +4 -2
- data/lib/kind/result.rb +31 -0
- data/lib/kind/result/abstract.rb +53 -0
- data/lib/kind/result/failure.rb +33 -0
- data/lib/kind/result/methods.rb +17 -0
- data/lib/kind/result/monad.rb +74 -0
- data/lib/kind/result/monad/wrapper.rb +19 -0
- data/lib/kind/result/success.rb +53 -0
- data/lib/kind/strict/disabled.rb +34 -0
- data/lib/kind/try.rb +21 -11
- data/lib/kind/validator.rb +111 -0
- data/lib/kind/version.rb +1 -1
- metadata +78 -48
- data/lib/kind/active_model/kind_validator.rb +0 -96
- data/lib/kind/core.rb +0 -9
- data/lib/kind/core/deprecation.rb +0 -29
- data/lib/kind/core/kind.rb +0 -61
- data/lib/kind/core/undefined.rb +0 -7
- data/lib/kind/deprecations/built_in_type_checkers.rb +0 -23
- data/lib/kind/deprecations/checker.rb +0 -16
- data/lib/kind/deprecations/checker/factory.rb +0 -31
- data/lib/kind/deprecations/checker/protocol.rb +0 -73
- data/lib/kind/deprecations/is.rb +0 -35
- data/lib/kind/deprecations/of.rb +0 -258
- data/lib/kind/deprecations/types.rb +0 -121
- data/lib/kind/error.rb +0 -15
- data/lib/kind/maybe/result.rb +0 -51
- data/lib/kind/type_checker.rb +0 -73
- data/lib/kind/type_checkers.rb +0 -30
data/Gemfile
CHANGED
@@ -18,24 +18,31 @@ activemodel = case activemodel_version
|
|
18
18
|
|
19
19
|
simplecov_version =
|
20
20
|
case RUBY_VERSION
|
21
|
-
when /\A2.[
|
21
|
+
when /\A2.[123]/ then '0.17.1'
|
22
22
|
when /\A2.4/ then '~> 0.18.5'
|
23
23
|
else '~> 0.19'
|
24
24
|
end
|
25
25
|
|
26
|
+
is_ruby_2_1 = RUBY_VERSION <= '2.2.0'
|
27
|
+
|
28
|
+
minitest_version =
|
29
|
+
if activemodel_version
|
30
|
+
activemodel_version < '4.1' ? '~> 4.2' : '~> 5.0'
|
31
|
+
else
|
32
|
+
is_ruby_2_1 ? '~> 4.2' : '~> 5.0'
|
33
|
+
end
|
34
|
+
|
26
35
|
group :test do
|
27
36
|
if activemodel_version
|
28
37
|
gem 'activesupport', activemodel, require: false
|
29
|
-
gem 'activemodel', activemodel, require: false
|
30
|
-
gem 'minitest', activemodel_version < '4.1' ? '~> 4.2' : '~> 5.0'
|
31
|
-
else
|
32
|
-
gem 'minitest', '~> 5.0'
|
38
|
+
gem 'activemodel' , activemodel, require: false
|
33
39
|
end
|
34
40
|
|
41
|
+
gem 'minitest' , minitest_version
|
35
42
|
gem 'simplecov', simplecov_version, require: false
|
36
43
|
end
|
37
44
|
|
38
|
-
gem 'rake', '~> 13.0'
|
45
|
+
gem 'rake', is_ruby_2_1 ? '~> 12.3' : '~> 13.0'
|
39
46
|
|
40
47
|
# Specify your gem's dependencies in type_validator.gemspec
|
41
48
|
gemspec
|
data/README.md
CHANGED
@@ -1,12 +1,9 @@
|
|
1
1
|
<p align="center">
|
2
2
|
<h1 align="center">🤷 kind</h1>
|
3
3
|
<p align="center"><i>A simple type system (at runtime) for Ruby - free of dependencies.</i></p>
|
4
|
-
<br>
|
5
4
|
</p>
|
6
5
|
|
7
6
|
<p align="center">
|
8
|
-
<img src="https://img.shields.io/badge/ruby->%3D%202.2.0-ruby.svg?colorA=99004d&colorB=cc0066" alt="Ruby">
|
9
|
-
|
10
7
|
<a href="https://rubygems.org/gems/kind">
|
11
8
|
<img alt="Gem" src="https://img.shields.io/gem/v/kind.svg?style=flat-square">
|
12
9
|
</a>
|
@@ -15,6 +12,14 @@
|
|
15
12
|
<img alt="Build Status" src="https://travis-ci.com/serradura/kind.svg?branch=master">
|
16
13
|
</a>
|
17
14
|
|
15
|
+
<br />
|
16
|
+
|
17
|
+
<img src="https://img.shields.io/badge/ruby%20%3E=%202.1,%20%3C%203.1-ruby.svg?colorA=99004d&colorB=cc0066" alt="Ruby">
|
18
|
+
|
19
|
+
<img src="https://img.shields.io/badge/rails%20%3E=%203.2.0,%20%3C%207.0-rails.svg?colorA=8B0000&colorB=FF0000" alt="Rails">
|
20
|
+
|
21
|
+
<br />
|
22
|
+
|
18
23
|
<a href="https://codeclimate.com/github/serradura/kind/maintainability">
|
19
24
|
<img alt="Maintainability" src="https://api.codeclimate.com/v1/badges/711329decb2806ccac95/maintainability">
|
20
25
|
</a>
|
@@ -34,11 +39,12 @@ One of the goals of this project is to do simple type checking like `"some strin
|
|
34
39
|
|
35
40
|
Version | Documentation
|
36
41
|
---------- | -------------
|
37
|
-
unreleased | https://github.com/serradura/
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
+
unreleased | https://github.com/serradura/kind/blob/main/README.md
|
43
|
+
5.3.0 | https://github.com/serradura/kind/blob/v5.x/README.md
|
44
|
+
4.1.0 | https://github.com/serradura/kind/blob/v4.x/README.md
|
45
|
+
3.1.0 | https://github.com/serradura/kind/blob/v3.x/README.md
|
46
|
+
2.3.0 | https://github.com/serradura/kind/blob/v2.x/README.md
|
47
|
+
1.9.0 | https://github.com/serradura/kind/blob/v1.x/README.md
|
42
48
|
|
43
49
|
## Table of Contents <!-- omit in toc -->
|
44
50
|
- [Compatibility](#compatibility)
|
@@ -51,17 +57,18 @@ unreleased | https://github.com/serradura/u-case/blob/main/README.md
|
|
51
57
|
- [Kind::\<Type\>.or_undefined()](#kindtypeor_undefined)
|
52
58
|
- [Kind::\<Type\>.or()](#kindtypeor)
|
53
59
|
- [Kind::\<Type\>.value()](#kindtypevalue-1)
|
60
|
+
- [Kind::\<Type\>.maybe](#kindtypemaybe)
|
54
61
|
- [Kind::\<Type\>?](#kindtype-2)
|
55
|
-
- [Kind::{Array,Hash,String,Set}.
|
56
|
-
- [List of all type
|
62
|
+
- [Kind::{Array,Hash,String,Set}.empty_or()](#kindarrayhashstringsetempty_or)
|
63
|
+
- [List of all type handlers](#list-of-all-type-handlers)
|
57
64
|
- [Core](#core)
|
58
65
|
- [Stdlib](#stdlib)
|
59
66
|
- [Custom](#custom)
|
60
|
-
- [Creating type
|
67
|
+
- [Creating type handlers](#creating-type-handlers)
|
61
68
|
- [Dynamic creation](#dynamic-creation)
|
62
69
|
- [Using a class or a module](#using-a-class-or-a-module)
|
63
70
|
- [Using an object which responds to ===](#using-an-object-which-responds-to-)
|
64
|
-
- [Kind::<Type>
|
71
|
+
- [Kind::<Type> object](#kindtype-object)
|
65
72
|
- [Utility methods](#utility-methods)
|
66
73
|
- [Kind.of_class?()](#kindof_class)
|
67
74
|
- [Kind.of_module?()](#kindof_module)
|
@@ -92,11 +99,19 @@ unreleased | https://github.com/serradura/u-case/blob/main/README.md
|
|
92
99
|
- [Kind::Maybe#try!](#kindmaybetry-1)
|
93
100
|
- [Kind::Maybe#dig](#kindmaybedig)
|
94
101
|
- [Kind::Maybe#check](#kindmaybecheck)
|
102
|
+
- [Kind::Maybe#presence](#kindmaybepresence)
|
95
103
|
- [Kind::Empty](#kindempty)
|
104
|
+
- [Defining Empty as Kind::Empty an alias](#defining-empty-as-kindempty-an-alias)
|
96
105
|
- [Kind::Validator (ActiveModel::Validations)](#kindvalidator-activemodelvalidations)
|
97
106
|
- [Usage](#usage-1)
|
98
|
-
- [
|
99
|
-
- [
|
107
|
+
- [Object#===](#object)
|
108
|
+
- [Kind.is](#kindis-1)
|
109
|
+
- [Object#instance_of?](#objectinstance_of)
|
110
|
+
- [Object#respond_to?](#objectrespond_to)
|
111
|
+
- [Array.new.all? { |item| item.kind_of?(Class) }](#arraynewall--item-itemkind_ofclass-)
|
112
|
+
- [Array.new.all? { |item| expected_values.include?(item) }](#arraynewall--item-expected_valuesincludeitem-)
|
113
|
+
- [Defining the default validation strategy](#defining-the-default-validation-strategy)
|
114
|
+
- [Using the `allow_nil` and `strict` options](#using-the-allow_nil-and-strict-options)
|
100
115
|
- [Similar Projects](#similar-projects)
|
101
116
|
- [Development](#development)
|
102
117
|
- [Contributing](#contributing)
|
@@ -105,10 +120,11 @@ unreleased | https://github.com/serradura/u-case/blob/main/README.md
|
|
105
120
|
|
106
121
|
## Compatibility
|
107
122
|
|
108
|
-
|
|
123
|
+
| kind | branch | ruby | activemodel |
|
109
124
|
| -------------- | ------- | -------- | -------------- |
|
110
|
-
| unreleased | main | >= 2.
|
111
|
-
|
|
125
|
+
| unreleased | main | >= 2.1.0 | >= 3.2, <= 6.1 |
|
126
|
+
| 5.3.0 | v5.x | >= 2.1.0 | >= 3.2, <= 6.1 |
|
127
|
+
| 4.1.0 | v4.x | >= 2.2.0 | >= 3.2, <= 6.1 |
|
112
128
|
| 3.1.0 | v3.x | >= 2.2.0 | >= 3.2, <= 6.1 |
|
113
129
|
| 2.3.0 | v2.x | >= 2.2.0 | >= 3.2, <= 6.0 |
|
114
130
|
| 1.9.0 | v1.x | >= 2.2.0 | >= 3.2, <= 6.0 |
|
@@ -257,6 +273,39 @@ Kind::String.value('1', default: 1) # Kind::Error (1 expected to be a kind of S
|
|
257
273
|
|
258
274
|
[⬆️ Back to Top](#table-of-contents-)
|
259
275
|
|
276
|
+
### Kind::\<Type\>.maybe
|
277
|
+
|
278
|
+
This method exposes a [typed `Kind::Maybe`](#kindmaybetype) and using it will be possible to apply a sequence of operations in the case of the wrapped value has the expected kind.
|
279
|
+
|
280
|
+
```ruby
|
281
|
+
Double = ->(value) do
|
282
|
+
Kind::Numeric.maybe(value)
|
283
|
+
.then { |number| number * 2 }
|
284
|
+
.value_or(0)
|
285
|
+
end
|
286
|
+
|
287
|
+
Double.('2') # 0
|
288
|
+
Double.(2) # 4
|
289
|
+
```
|
290
|
+
|
291
|
+
If it is invoked without arguments, it returns the typed Maybe. But, if it receives arguments, it will behave like the `Kind::Maybe.wrap` method. e.g.
|
292
|
+
|
293
|
+
```ruby
|
294
|
+
Kind::Integer.maybe #<Kind::Maybe::Typed:0x0000... @kind=Kind::Integer>
|
295
|
+
|
296
|
+
Kind::Integer.maybe(0).some? # true
|
297
|
+
Kind::Integer.maybe { 1 }.some? # true
|
298
|
+
Kind::Integer.maybe(2) { |n| n * 2 }.some? # true
|
299
|
+
|
300
|
+
Kind::Integer.maybe { 2 / 0 }.none? # true
|
301
|
+
Kind::Integer.maybe(2) { |n| n / 0 }.none? # true
|
302
|
+
Kind::Integer.maybe('2') { |n| n * n }.none? # true
|
303
|
+
```
|
304
|
+
|
305
|
+
> **Note:** You can use `Kind::\<Type\>.optional` as an alias for `Kind::\<Type\>.maybe`.
|
306
|
+
|
307
|
+
[⬆️ Back to Top](#table-of-contents-)
|
308
|
+
|
260
309
|
### Kind::\<Type\>?
|
261
310
|
|
262
311
|
There is a second way to do a type verification and know if one or multiple values has the expected type. You can use the predicate kind methods (`Kind::Hash?`). e.g:
|
@@ -279,17 +328,17 @@ collection.select(&Kind::Enumerable?) # [{:number=>1}, {:number=>3}, [:number, 5
|
|
279
328
|
|
280
329
|
[⬆️ Back to Top](#table-of-contents-)
|
281
330
|
|
282
|
-
### Kind::{Array,Hash,String,Set}.
|
331
|
+
### Kind::{Array,Hash,String,Set}.empty_or()
|
283
332
|
|
284
|
-
This method is available for some type
|
333
|
+
This method is available for some type handlers (`Kind::Array`, `Kind::Hash`, `Kind::String`, `Kind::Set`), and it will return an empty frozen value if the given one hasn't the expected kind.
|
285
334
|
```ruby
|
286
|
-
Kind::Array.
|
287
|
-
Kind::Array.
|
335
|
+
Kind::Array.empty_or({}) # []
|
336
|
+
Kind::Array.empty_or({}).frozen? # true
|
288
337
|
```
|
289
338
|
|
290
339
|
[⬆️ Back to Top](#table-of-contents-)
|
291
340
|
|
292
|
-
### List of all type
|
341
|
+
### List of all type handlers
|
293
342
|
|
294
343
|
#### Core
|
295
344
|
|
@@ -328,9 +377,9 @@ Kind::Array.value_or_empty({}).frozen? # true
|
|
328
377
|
|
329
378
|
[⬆️ Back to Top](#table-of-contents-)
|
330
379
|
|
331
|
-
### Creating type
|
380
|
+
### Creating type handlers
|
332
381
|
|
333
|
-
There are two ways to do this, you can create type
|
382
|
+
There are two ways to do this, you can create type handlers dynamically or defining a module.
|
334
383
|
|
335
384
|
#### Dynamic creation
|
336
385
|
|
@@ -346,7 +395,7 @@ kind_of_user = Kind::Of(User)
|
|
346
395
|
|
347
396
|
# kind_of_user.name
|
348
397
|
# kind_of_user.kind
|
349
|
-
# The type
|
398
|
+
# The type handler can return its kind and its name
|
350
399
|
kind_of_user.name # "User"
|
351
400
|
kind_of_user.kind # User
|
352
401
|
|
@@ -396,6 +445,10 @@ kind_of_user.value(User.new, default: User.new) # #<User:0x0000...>
|
|
396
445
|
kind_of_user.value('1', default: User.new) # #<User:0x0000...>
|
397
446
|
|
398
447
|
kind_of_user.value('1', default: 1) # Kind::Error (1 expected to be a kind of User)
|
448
|
+
|
449
|
+
# kind_of_user.maybe
|
450
|
+
# This method returns a typed Kind::Maybe.
|
451
|
+
kind_of_user.maybe('1').value_or(User.new) # #<User:0x0000...>
|
399
452
|
```
|
400
453
|
|
401
454
|
[⬆️ Back to Top](#table-of-contents-)
|
@@ -412,7 +465,7 @@ PositiveInteger = Kind::Of(
|
|
412
465
|
|
413
466
|
# PositiveInteger.name
|
414
467
|
# PositiveInteger.kind
|
415
|
-
# The type
|
468
|
+
# The type handler can return its kind and its name
|
416
469
|
PositiveInteger.name # "PositiveInteger"
|
417
470
|
PositiveInteger.kind # #<Proc:0x0000.... >
|
418
471
|
|
@@ -463,13 +516,19 @@ PositiveInteger.value(2, default: 1) # 2
|
|
463
516
|
PositiveInteger.value('1', default: 1) # 1
|
464
517
|
|
465
518
|
PositiveInteger.value('1', default: 0) # Kind::Error (0 expected to be a kind of PositiveInteger)
|
519
|
+
|
520
|
+
# PositiveInteger.maybe
|
521
|
+
# This method returns a typed Kind::Maybe.
|
522
|
+
PositiveInteger.maybe(0).value_or(1) # 1
|
523
|
+
|
524
|
+
PositiveInteger.maybe(2).value_or(1) # 2
|
466
525
|
```
|
467
526
|
|
468
527
|
[⬆️ Back to Top](#table-of-contents-)
|
469
528
|
|
470
|
-
#### Kind::<Type>
|
529
|
+
#### Kind::<Type> object
|
471
530
|
|
472
|
-
The idea here is to create a type
|
531
|
+
The idea here is to create a type handler inside of the `Kind` namespace and to do this you will only need to use pure Ruby. e.g:
|
473
532
|
|
474
533
|
```ruby
|
475
534
|
class User
|
@@ -477,9 +536,9 @@ end
|
|
477
536
|
|
478
537
|
module Kind
|
479
538
|
module User
|
480
|
-
extend self,
|
539
|
+
extend self, ::Kind::Object
|
481
540
|
|
482
|
-
# Define the expected kind of this type
|
541
|
+
# Define the expected kind of this type handler.
|
483
542
|
def kind; ::User; end
|
484
543
|
end
|
485
544
|
|
@@ -489,7 +548,7 @@ module Kind
|
|
489
548
|
end
|
490
549
|
end
|
491
550
|
|
492
|
-
# Doing this you will have the same methods of a standard type
|
551
|
+
# Doing this you will have the same methods of a standard type handler (like: `Kind::Symbol`).
|
493
552
|
|
494
553
|
user = User.new
|
495
554
|
|
@@ -507,7 +566,7 @@ The advantages of this approach are:
|
|
507
566
|
|
508
567
|
The disadvantage is:
|
509
568
|
|
510
|
-
1. You could overwrite some standard type
|
569
|
+
1. You could overwrite some standard type handler or constant. I believe that this will be hard to happen, but must be your concern if you decide to use this kind of approach.
|
511
570
|
|
512
571
|
[⬆️ Back to Top](#table-of-contents-)
|
513
572
|
|
@@ -1099,7 +1158,7 @@ def person_name(params)
|
|
1099
1158
|
|
1100
1159
|
return default if names.size != 2
|
1101
1160
|
|
1102
|
-
first_name, last_name =
|
1161
|
+
first_name, last_name = names
|
1103
1162
|
|
1104
1163
|
"#{first_name} #{last_name}"
|
1105
1164
|
end
|
@@ -1126,7 +1185,7 @@ module PersonIntroduction1
|
|
1126
1185
|
end
|
1127
1186
|
|
1128
1187
|
def age(optional)
|
1129
|
-
optional.
|
1188
|
+
optional.dig(:age).value_or(0)
|
1130
1189
|
end
|
1131
1190
|
end
|
1132
1191
|
|
@@ -1336,6 +1395,18 @@ Kind::Maybe(Array)
|
|
1336
1395
|
|
1337
1396
|
[⬆️ Back to Top](#table-of-contents-)
|
1338
1397
|
|
1398
|
+
### Kind::Maybe#presence
|
1399
|
+
|
1400
|
+
This method will return None if the wrapped value wasn't present.
|
1401
|
+
|
1402
|
+
```ruby
|
1403
|
+
result = Kind::Maybe(Hash).wrap(foo: '').dig(:foo).presence
|
1404
|
+
result.none? # true
|
1405
|
+
result.value # nil
|
1406
|
+
```
|
1407
|
+
|
1408
|
+
[⬆️ Back to Top](#table-of-contents-)
|
1409
|
+
|
1339
1410
|
## Kind::Empty
|
1340
1411
|
|
1341
1412
|
When you define a method that has default arguments, for certain data types, you will always create a new object in memory. e.g:
|
@@ -1366,7 +1437,11 @@ def do_something(value, with_options: Kind::Empty::HASH)
|
|
1366
1437
|
end
|
1367
1438
|
```
|
1368
1439
|
|
1369
|
-
|
1440
|
+
### Defining Empty as Kind::Empty an alias
|
1441
|
+
|
1442
|
+
You can require `kind/empty/constant` to define `Empty` as a `Kind::Empty` alias. But, a `LoadError` will be raised if there is an already defined constant `Empty`.
|
1443
|
+
|
1444
|
+
So if you required this file, the previous example could be written like this:
|
1370
1445
|
|
1371
1446
|
```ruby
|
1372
1447
|
def do_something(value, with_options: Empty::HASH)
|
@@ -1374,7 +1449,7 @@ def do_something(value, with_options: Empty::HASH)
|
|
1374
1449
|
end
|
1375
1450
|
```
|
1376
1451
|
|
1377
|
-
Follows the list of constants
|
1452
|
+
Follows the list of constants if the alias was defined:
|
1378
1453
|
|
1379
1454
|
- `Empty::SET`
|
1380
1455
|
- `Empty::HASH`
|
@@ -1385,7 +1460,7 @@ Follows the list of constants, if the alias is available to be created:
|
|
1385
1460
|
|
1386
1461
|
## Kind::Validator (ActiveModel::Validations)
|
1387
1462
|
|
1388
|
-
This module enables the capability to validate types via [`ActiveModel::Validations >= 3.2, <
|
1463
|
+
This module enables the capability to validate types via [`ActiveModel::Validations >= 3.2, < 7.0`](https://api.rubyonrails.org/classes/ActiveModel/Validations.html). e.g
|
1389
1464
|
|
1390
1465
|
```ruby
|
1391
1466
|
class Person
|
@@ -1401,26 +1476,37 @@ And to make use of it, you will need to do an explicitly require. e.g:
|
|
1401
1476
|
|
1402
1477
|
```ruby
|
1403
1478
|
# In some Gemfile
|
1404
|
-
gem 'kind', require: 'kind/
|
1479
|
+
gem 'kind', require: 'kind/validator'
|
1405
1480
|
|
1406
1481
|
# In some .rb file
|
1407
|
-
require 'kind/
|
1482
|
+
require 'kind/validator'
|
1408
1483
|
```
|
1409
1484
|
|
1485
|
+
[⬆️ Back to Top](#table-of-contents-)
|
1486
|
+
|
1410
1487
|
### Usage
|
1411
1488
|
|
1412
|
-
|
1489
|
+
#### [Object#===](https://ruby-doc.org/core-3.0.0/Object.html#method-i-3D-3D-3D)
|
1413
1490
|
|
1414
1491
|
```ruby
|
1415
1492
|
validates :name, kind: { of: String }
|
1493
|
+
```
|
1416
1494
|
|
1417
|
-
|
1418
|
-
# is an instance of one of the classes/modules.
|
1495
|
+
Use an array to verify if the attribute is an instance of one of the classes/modules.
|
1419
1496
|
|
1497
|
+
```ruby
|
1420
1498
|
validates :status, kind: { of: [String, Symbol]}
|
1421
1499
|
```
|
1422
1500
|
|
1423
|
-
|
1501
|
+
Because of kind verification be made via `===` you can use type handlers as the expected kinds.
|
1502
|
+
|
1503
|
+
```ruby
|
1504
|
+
validates :alive, kind: Kind::Boolean
|
1505
|
+
```
|
1506
|
+
|
1507
|
+
[⬆️ Back to Top](#table-of-contents-)
|
1508
|
+
|
1509
|
+
#### [Kind.is](#verifying-the-kind-of-some-classmodule)
|
1424
1510
|
|
1425
1511
|
```ruby
|
1426
1512
|
#
|
@@ -1456,7 +1542,9 @@ validates :human_kind, kind: { is: Human }
|
|
1456
1542
|
validates :human_kind, kind: { is: [Person, User] }
|
1457
1543
|
```
|
1458
1544
|
|
1459
|
-
|
1545
|
+
[⬆️ Back to Top](#table-of-contents-)
|
1546
|
+
|
1547
|
+
#### [Object#instance_of?](https://ruby-doc.org/core-3.0.0/Object.html#method-i-instance_of-3F)
|
1460
1548
|
|
1461
1549
|
```ruby
|
1462
1550
|
validates :name, kind: { instance_of: String }
|
@@ -1467,13 +1555,23 @@ validates :name, kind: { instance_of: String }
|
|
1467
1555
|
validates :name, kind: { instance_of: [String, Symbol] }
|
1468
1556
|
```
|
1469
1557
|
|
1470
|
-
|
1558
|
+
[⬆️ Back to Top](#table-of-contents-)
|
1559
|
+
|
1560
|
+
#### [Object#respond_to?](https://ruby-doc.org/core-3.0.0/Object.html#method-i-respond_to-3F)
|
1471
1561
|
|
1472
1562
|
```ruby
|
1473
1563
|
validates :handler, kind: { respond_to: :call }
|
1474
1564
|
```
|
1475
1565
|
|
1476
|
-
|
1566
|
+
This validation can verify one or multiple methods.
|
1567
|
+
|
1568
|
+
```ruby
|
1569
|
+
validates :params, kind: { respond_to: [:[], :values_at] }
|
1570
|
+
```
|
1571
|
+
|
1572
|
+
[⬆️ Back to Top](#table-of-contents-)
|
1573
|
+
|
1574
|
+
#### Array.new.all? { |item| item.kind_of?(Class) }
|
1477
1575
|
|
1478
1576
|
```ruby
|
1479
1577
|
validates :account_types, kind: { array_of: String }
|
@@ -1484,7 +1582,9 @@ validates :account_types, kind: { array_of: String }
|
|
1484
1582
|
validates :account_types, kind: { array_of: [String, Symbol] }
|
1485
1583
|
```
|
1486
1584
|
|
1487
|
-
|
1585
|
+
[⬆️ Back to Top](#table-of-contents-)
|
1586
|
+
|
1587
|
+
#### Array.new.all? { |item| expected_values.include?(item) }
|
1488
1588
|
|
1489
1589
|
```ruby
|
1490
1590
|
# Verifies if the attribute value
|
@@ -1493,7 +1593,9 @@ validates :account_types, kind: { array_of: [String, Symbol] }
|
|
1493
1593
|
validates :account_types, kind: { array_with: ['foo', 'bar'] }
|
1494
1594
|
```
|
1495
1595
|
|
1496
|
-
|
1596
|
+
[⬆️ Back to Top](#table-of-contents-)
|
1597
|
+
|
1598
|
+
### Defining the default validation strategy
|
1497
1599
|
|
1498
1600
|
By default, you can define the attribute type directly (without a hash). e.g.
|
1499
1601
|
|
@@ -1515,7 +1617,9 @@ And these are the available options to define the default strategy:
|
|
1515
1617
|
- `kind_of` *(default)*
|
1516
1618
|
- `instance_of`
|
1517
1619
|
|
1518
|
-
|
1620
|
+
[⬆️ Back to Top](#table-of-contents-)
|
1621
|
+
|
1622
|
+
### Using the `allow_nil` and `strict` options
|
1519
1623
|
|
1520
1624
|
You can use the `allow_nil` option with any of the kind validations. e.g.
|
1521
1625
|
|