kind 4.0.0 → 5.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|