kind 4.0.0 → 4.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 62e657cbbdd2af4aebab8cde9f010744a0321c7fceff24f3574a2f9ac4c2a9ad
4
- data.tar.gz: c0f5690cef9d736b703ac2f1f75c23b30fccc309ad58c18972060074c8946d3b
3
+ metadata.gz: ffb9807682a295f94cb8e4076d32fc3217da97268e943e7d6b028b6de95ed765
4
+ data.tar.gz: 7b61164996c0d96853ad5a0cde9269ecd18bb489b483b46956a7fa2e9b9f2cd6
5
5
  SHA512:
6
- metadata.gz: 15281701426737bbf5c5cd4fa669ecb7c245fb520c1feb79d344d271f6552388111f75245babeffd4eadb3cd98120a3041a4d65959c78f0983ad167ce7060104
7
- data.tar.gz: 6bd17ee29bcbf1bda1273eebf7ef2999a74a0e55935622330b19a07efac4f0e448436eb26115042e828c1e7ed9e00c1435207ddbcb84bbd11dcb15a1371a2a3a
6
+ metadata.gz: 0f23b38b9f63d03638ded172c037b6ba9e048c397e9a31907850beca5151822c4983129e5726b777ccbdb30db18c8bcdfb9392c813c3e05546dfd33f97db9660
7
+ data.tar.gz: 3d7e663d65a591bff7bfeb152dd4e605948df7e95de15bb3632be0f52c747fd522041fc1be7678c8385cd9c0606a688abd203348e376ce264f3088d62ecb5f88
data/CHANGELOG.md CHANGED
@@ -3,61 +3,63 @@
3
3
  This project follows [semver 2.0.0](http://semver.org/spec/v2.0.0.html) and the recommendations of [keepachangelog.com](http://keepachangelog.com/).
4
4
 
5
5
  - [Unreleased](#unreleased)
6
- - [4.0.0 (2021-02-22)](#400-2021-02-22)
6
+ - [4.1.0 (2021-02-22)](#410-2021-02-22)
7
7
  - [Added](#added)
8
+ - [4.0.0 (2021-02-22)](#400-2021-02-22)
9
+ - [Added](#added-1)
8
10
  - [Deprecated](#deprecated)
9
11
  - [Fixed](#fixed)
10
12
  - [3.1.0 (2020-07-08)](#310-2020-07-08)
11
- - [Added](#added-1)
13
+ - [Added](#added-2)
12
14
  - [3.0.0 (2020-06-25)](#300-2020-06-25)
13
15
  - [Breaking Changes](#breaking-changes)
14
- - [Added](#added-2)
15
- - [2.3.0 (2020-06-24)](#230-2020-06-24)
16
16
  - [Added](#added-3)
17
- - [2.2.0 (2020-06-23)](#220-2020-06-23)
17
+ - [2.3.0 (2020-06-24)](#230-2020-06-24)
18
18
  - [Added](#added-4)
19
- - [2.1.0 (2020-05-12)](#210-2020-05-12)
19
+ - [2.2.0 (2020-06-23)](#220-2020-06-23)
20
20
  - [Added](#added-5)
21
+ - [2.1.0 (2020-05-12)](#210-2020-05-12)
22
+ - [Added](#added-6)
21
23
  - [Breaking Changes](#breaking-changes-1)
22
24
  - [2.0.0 (2020-05-07)](#200-2020-05-07)
23
- - [Added](#added-6)
25
+ - [Added](#added-7)
24
26
  - [Breaking Changes](#breaking-changes-2)
25
27
  - [Removed](#removed)
26
28
  - [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
29
  - [Added](#added-8)
30
+ - [1.8.0 (2020-05-03)](#180-2020-05-03)
31
+ - [Added](#added-9)
30
32
  - [1.7.0 (2020-05-03)](#170-2020-05-03)
31
33
  - [Fixed](#fixed-1)
32
34
  - [1.6.0 (2020-04-17)](#160-2020-04-17)
33
- - [Added](#added-9)
35
+ - [Added](#added-10)
34
36
  - [Changes](#changes)
35
37
  - [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
38
  - [Added](#added-11)
39
- - [1.3.0 (2020-04-12)](#130-2020-04-12)
39
+ - [1.4.0 (2020-04-12)](#140-2020-04-12)
40
40
  - [Added](#added-12)
41
- - [1.2.0 (2020-04-12)](#120-2020-04-12)
41
+ - [1.3.0 (2020-04-12)](#130-2020-04-12)
42
42
  - [Added](#added-13)
43
- - [1.1.0 (2020-04-09)](#110-2020-04-09)
43
+ - [1.2.0 (2020-04-12)](#120-2020-04-12)
44
44
  - [Added](#added-14)
45
+ - [1.1.0 (2020-04-09)](#110-2020-04-09)
46
+ - [Added](#added-15)
45
47
  - [Fixed](#fixed-2)
46
48
  - [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
49
  - [Added](#added-16)
50
- - [0.5.0 (2020-01-04)](#050-2020-01-04)
50
+ - [0.6.0 (2020-01-06)](#060-2020-01-06)
51
51
  - [Added](#added-17)
52
- - [0.4.0 (2020-01-03)](#040-2020-01-03)
52
+ - [0.5.0 (2020-01-04)](#050-2020-01-04)
53
53
  - [Added](#added-18)
54
- - [0.3.0 (2020-01-03)](#030-2020-01-03)
54
+ - [0.4.0 (2020-01-03)](#040-2020-01-03)
55
55
  - [Added](#added-19)
56
+ - [0.3.0 (2020-01-03)](#030-2020-01-03)
57
+ - [Added](#added-20)
56
58
  - [Breaking Changes](#breaking-changes-3)
57
59
  - [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
60
  - [Added](#added-21)
61
+ - [0.1.0 (2019-12-26)](#010-2019-12-26)
62
+ - [Added](#added-22)
61
63
 
62
64
  ## Unreleased
63
65
 
@@ -69,6 +71,41 @@ This project follows [semver 2.0.0](http://semver.org/spec/v2.0.0.html) and the
69
71
  ### Fixed
70
72
  -->
71
73
 
74
+ 4.1.0 (2021-02-22)
75
+ ------------------
76
+
77
+ ### Added
78
+
79
+ * [#43](https://github.com/serradura/kind/pull/43) - Make `Kind::Maybe::Typed` verify the kind of the value via `===`, because of this, now is possible to use type checkers in typed Maybes.
80
+ ```ruby
81
+ Kind::Maybe(Kind::Boolean).wrap(nil).value_or(false) # false
82
+
83
+ Kind::Maybe(Kind::Boolean).wrap(true).value_or(false) # true
84
+ ```
85
+
86
+ * [#43](https://github.com/serradura/kind/pull/43) - Add `Kind::<Type>.maybe` and `Kind::<Type>.optional`. This method returns a typed Maybe with the expected kind when it is invoked without arguments. But, if it receives arguments, it will behave like the `Kind::Maybe.wrap` method. e.g.
87
+ ```ruby
88
+ Kind::Integer.maybe #<Kind::Maybe::Typed:0x0000... @kind=Kind::Integer>
89
+
90
+ Kind::Integer.maybe(0).some? # true
91
+ Kind::Integer.maybe { 1 }.some? # true
92
+ Kind::Integer.maybe(2) { |n| n * 2 }.some? # true
93
+
94
+ Kind::Integer.maybe { 2 / 0 }.none? # true
95
+ Kind::Integer.maybe(2) { |n| n / 0 }.none? # true
96
+ Kind::Integer.maybe('2') { |n| n * n }.none? # true
97
+ ```
98
+
99
+ * [#43](https://github.com/serradura/kind/pull/43) - Make the `:respond_to` kind validation verify by one or multiple methods. e.g.
100
+ ```ruby
101
+ validates :params, kind: { respond_to: [:[], :values_at] }
102
+ ```
103
+
104
+ * [#43](https://github.com/serradura/kind/pull/43) - Make the `:of` kind validation verify the expected value kind using `===`, because of this, now is possible to use type checkers as expected kinds. e.g.
105
+ ```ruby
106
+ validates :alive, kind: Kind::Boolean
107
+ ```
108
+
72
109
  4.0.0 (2021-02-22)
73
110
  ------------------
74
111
 
data/README.md CHANGED
@@ -35,7 +35,7 @@ One of the goals of this project is to do simple type checking like `"some strin
35
35
  Version | Documentation
36
36
  ---------- | -------------
37
37
  unreleased | https://github.com/serradura/u-case/blob/main/README.md
38
- 4.0.0 | https://github.com/serradura/u-case/blob/v4.x/README.md
38
+ 4.1.0 | https://github.com/serradura/u-case/blob/v4.x/README.md
39
39
  3.1.0 | https://github.com/serradura/u-case/blob/v3.x/README.md
40
40
  2.3.0 | https://github.com/serradura/u-case/blob/v2.x/README.md
41
41
  1.9.0 | https://github.com/serradura/u-case/blob/v1.x/README.md
@@ -51,9 +51,10 @@ unreleased | https://github.com/serradura/u-case/blob/main/README.md
51
51
  - [Kind::\<Type\>.or_undefined()](#kindtypeor_undefined)
52
52
  - [Kind::\<Type\>.or()](#kindtypeor)
53
53
  - [Kind::\<Type\>.value()](#kindtypevalue-1)
54
+ - [Kind::\<Type\>.maybe](#kindtypemaybe)
54
55
  - [Kind::\<Type\>?](#kindtype-2)
55
56
  - [Kind::{Array,Hash,String,Set}.value_or_empty()](#kindarrayhashstringsetvalue_or_empty)
56
- - [List of all type checkers (Kind::<Type>)](#list-of-all-type-checkers-kindtype)
57
+ - [List of all type checkers](#list-of-all-type-checkers)
57
58
  - [Core](#core)
58
59
  - [Stdlib](#stdlib)
59
60
  - [Custom](#custom)
@@ -92,11 +93,18 @@ unreleased | https://github.com/serradura/u-case/blob/main/README.md
92
93
  - [Kind::Maybe#try!](#kindmaybetry-1)
93
94
  - [Kind::Maybe#dig](#kindmaybedig)
94
95
  - [Kind::Maybe#check](#kindmaybecheck)
96
+ - [Kind::Maybe#presence](#kindmaybepresence)
95
97
  - [Kind::Empty](#kindempty)
96
98
  - [Kind::Validator (ActiveModel::Validations)](#kindvalidator-activemodelvalidations)
97
99
  - [Usage](#usage-1)
98
- - [Defining the default validation strategy](#defining-the-default-validation-strategy)
99
- - [Using the `allow_nil` and `strict` options](#using-the-allow_nil-and-strict-options)
100
+ - [Object#===](#object)
101
+ - [Kind.is](#kindis-1)
102
+ - [Object#instance_of?](#objectinstance_of)
103
+ - [Object#respond_to?](#objectrespond_to)
104
+ - [Array.new.all? { |item| item.kind_of?(Class) }](#arraynewall--item-itemkind_ofclass-)
105
+ - [Array.new.all? { |item| expected_values.include?(item) }](#arraynewall--item-expected_valuesincludeitem-)
106
+ - [Defining the default validation strategy](#defining-the-default-validation-strategy)
107
+ - [Using the `allow_nil` and `strict` options](#using-the-allow_nil-and-strict-options)
100
108
  - [Similar Projects](#similar-projects)
101
109
  - [Development](#development)
102
110
  - [Contributing](#contributing)
@@ -108,7 +116,7 @@ unreleased | https://github.com/serradura/u-case/blob/main/README.md
108
116
  | u-case | branch | ruby | activemodel |
109
117
  | -------------- | ------- | -------- | -------------- |
110
118
  | unreleased | main | >= 2.2.0 | >= 3.2, <= 6.1 |
111
- | 4.0.0 | v4.x | >= 2.2.0 | >= 3.2, <= 6.1 |
119
+ | 4.1.0 | v4.x | >= 2.2.0 | >= 3.2, <= 6.1 |
112
120
  | 3.1.0 | v3.x | >= 2.2.0 | >= 3.2, <= 6.1 |
113
121
  | 2.3.0 | v2.x | >= 2.2.0 | >= 3.2, <= 6.0 |
114
122
  | 1.9.0 | v1.x | >= 2.2.0 | >= 3.2, <= 6.0 |
@@ -257,6 +265,39 @@ Kind::String.value('1', default: 1) # Kind::Error (1 expected to be a kind of S
257
265
 
258
266
  [⬆️ &nbsp;Back to Top](#table-of-contents-)
259
267
 
268
+ ### Kind::\<Type\>.maybe
269
+
270
+ 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.
271
+
272
+ ```ruby
273
+ Double = ->(value) do
274
+ Kind::Numeric.maybe(value)
275
+ .then { |number| number * 2 }
276
+ .value_or(0)
277
+ end
278
+
279
+ Double.('2') # 0
280
+ Double.(2) # 4
281
+ ```
282
+
283
+ 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.
284
+
285
+ ```ruby
286
+ Kind::Integer.maybe #<Kind::Maybe::Typed:0x0000... @kind=Kind::Integer>
287
+
288
+ Kind::Integer.maybe(0).some? # true
289
+ Kind::Integer.maybe { 1 }.some? # true
290
+ Kind::Integer.maybe(2) { |n| n * 2 }.some? # true
291
+
292
+ Kind::Integer.maybe { 2 / 0 }.none? # true
293
+ Kind::Integer.maybe(2) { |n| n / 0 }.none? # true
294
+ Kind::Integer.maybe('2') { |n| n * n }.none? # true
295
+ ```
296
+
297
+ > **Note:** You can use `Kind::\<Type\>.optional` as an alias for `Kind::\<Type\>.maybe`.
298
+
299
+ [⬆️ &nbsp;Back to Top](#table-of-contents-)
300
+
260
301
  ### Kind::\<Type\>?
261
302
 
262
303
  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:
@@ -289,7 +330,7 @@ Kind::Array.value_or_empty({}).frozen? # true
289
330
 
290
331
  [⬆️ &nbsp;Back to Top](#table-of-contents-)
291
332
 
292
- ### List of all type checkers (Kind::<Type>)
333
+ ### List of all type checkers
293
334
 
294
335
  #### Core
295
336
 
@@ -396,6 +437,10 @@ kind_of_user.value(User.new, default: User.new) # #<User:0x0000...>
396
437
  kind_of_user.value('1', default: User.new) # #<User:0x0000...>
397
438
 
398
439
  kind_of_user.value('1', default: 1) # Kind::Error (1 expected to be a kind of User)
440
+
441
+ # kind_of_user.maybe
442
+ # This method returns a typed Kind::Maybe.
443
+ kind_of_user.maybe('1').value_or(User.new) # #<User:0x0000...>
399
444
  ```
400
445
 
401
446
  [⬆️ &nbsp;Back to Top](#table-of-contents-)
@@ -463,6 +508,12 @@ PositiveInteger.value(2, default: 1) # 2
463
508
  PositiveInteger.value('1', default: 1) # 1
464
509
 
465
510
  PositiveInteger.value('1', default: 0) # Kind::Error (0 expected to be a kind of PositiveInteger)
511
+
512
+ # PositiveInteger.maybe
513
+ # This method returns a typed Kind::Maybe.
514
+ PositiveInteger.maybe(0).value_or(1) # 1
515
+
516
+ PositiveInteger.maybe(2).value_or(1) # 2
466
517
  ```
467
518
 
468
519
  [⬆️ &nbsp;Back to Top](#table-of-contents-)
@@ -1099,7 +1150,7 @@ def person_name(params)
1099
1150
 
1100
1151
  return default if names.size != 2
1101
1152
 
1102
- first_name, last_name = default
1153
+ first_name, last_name = names
1103
1154
 
1104
1155
  "#{first_name} #{last_name}"
1105
1156
  end
@@ -1126,7 +1177,7 @@ module PersonIntroduction1
1126
1177
  end
1127
1178
 
1128
1179
  def age(optional)
1129
- optional.map { |hash| hash[:age] }.value_or(0)
1180
+ optional.dig(:age).value_or(0)
1130
1181
  end
1131
1182
  end
1132
1183
 
@@ -1336,6 +1387,18 @@ Kind::Maybe(Array)
1336
1387
 
1337
1388
  [⬆️ &nbsp;Back to Top](#table-of-contents-)
1338
1389
 
1390
+ ### Kind::Maybe#presence
1391
+
1392
+ This method will return None if the wrapped value wasn't present.
1393
+
1394
+ ```ruby
1395
+ result = Kind::Maybe(Hash).wrap(foo: '').dig(:foo).presence
1396
+ result.none? # true
1397
+ result.value # nil
1398
+ ```
1399
+
1400
+ [⬆️ &nbsp;Back to Top](#table-of-contents-)
1401
+
1339
1402
  ## Kind::Empty
1340
1403
 
1341
1404
  When you define a method that has default arguments, for certain data types, you will always create a new object in memory. e.g:
@@ -1407,20 +1470,31 @@ gem 'kind', require: 'kind/active_model/validation'
1407
1470
  require 'kind/active_model/validation'
1408
1471
  ```
1409
1472
 
1473
+ [⬆️ &nbsp;Back to Top](#table-of-contents-)
1474
+
1410
1475
  ### Usage
1411
1476
 
1412
- **[Object#kind_of?](https://ruby-doc.org/core-2.6.4/Object.html#method-i-kind_of-3F)**
1477
+ #### [Object#===](https://ruby-doc.org/core-3.0.0/Object.html#method-i-3D-3D-3D)
1413
1478
 
1414
1479
  ```ruby
1415
1480
  validates :name, kind: { of: String }
1481
+ ```
1416
1482
 
1417
- # Use an array to verify if the attribute
1418
- # is an instance of one of the classes/modules.
1483
+ Use an array to verify if the attribute is an instance of one of the classes/modules.
1419
1484
 
1485
+ ```ruby
1420
1486
  validates :status, kind: { of: [String, Symbol]}
1421
1487
  ```
1422
1488
 
1423
- **[Kind.is](#verifying-the-kind-of-some-classmodule)**
1489
+ Because of kind verification be made via `===` you can use type checkers as the expected kinds.
1490
+
1491
+ ```ruby
1492
+ validates :alive, kind: Kind::Boolean
1493
+ ```
1494
+
1495
+ [⬆️ &nbsp;Back to Top](#table-of-contents-)
1496
+
1497
+ #### [Kind.is](#verifying-the-kind-of-some-classmodule)
1424
1498
 
1425
1499
  ```ruby
1426
1500
  #
@@ -1456,7 +1530,9 @@ validates :human_kind, kind: { is: Human }
1456
1530
  validates :human_kind, kind: { is: [Person, User] }
1457
1531
  ```
1458
1532
 
1459
- **[Object#instance_of?](https://ruby-doc.org/core-2.6.4/Object.html#method-i-instance_of-3F)**
1533
+ [⬆️ &nbsp;Back to Top](#table-of-contents-)
1534
+
1535
+ #### [Object#instance_of?](https://ruby-doc.org/core-3.0.0/Object.html#method-i-instance_of-3F)
1460
1536
 
1461
1537
  ```ruby
1462
1538
  validates :name, kind: { instance_of: String }
@@ -1467,13 +1543,23 @@ validates :name, kind: { instance_of: String }
1467
1543
  validates :name, kind: { instance_of: [String, Symbol] }
1468
1544
  ```
1469
1545
 
1470
- **[Object#respond_to?](https://ruby-doc.org/core-2.6.4/Object.html#method-i-respond_to-3F)**
1546
+ [⬆️ &nbsp;Back to Top](#table-of-contents-)
1547
+
1548
+ #### [Object#respond_to?](https://ruby-doc.org/core-3.0.0/Object.html#method-i-respond_to-3F)
1471
1549
 
1472
1550
  ```ruby
1473
1551
  validates :handler, kind: { respond_to: :call }
1474
1552
  ```
1475
1553
 
1476
- **Array.new.all? { |item| item.kind_of?(Class) }**
1554
+ This validation can verify one or multiple methods.
1555
+
1556
+ ```ruby
1557
+ validates :params, kind: { respond_to: [:[], :values_at] }
1558
+ ```
1559
+
1560
+ [⬆️ &nbsp;Back to Top](#table-of-contents-)
1561
+
1562
+ #### Array.new.all? { |item| item.kind_of?(Class) }
1477
1563
 
1478
1564
  ```ruby
1479
1565
  validates :account_types, kind: { array_of: String }
@@ -1484,7 +1570,9 @@ validates :account_types, kind: { array_of: String }
1484
1570
  validates :account_types, kind: { array_of: [String, Symbol] }
1485
1571
  ```
1486
1572
 
1487
- **Array.new.all? { |item| expected_values.include?(item) }**
1573
+ [⬆️ &nbsp;Back to Top](#table-of-contents-)
1574
+
1575
+ #### Array.new.all? { |item| expected_values.include?(item) }
1488
1576
 
1489
1577
  ```ruby
1490
1578
  # Verifies if the attribute value
@@ -1493,7 +1581,9 @@ validates :account_types, kind: { array_of: [String, Symbol] }
1493
1581
  validates :account_types, kind: { array_with: ['foo', 'bar'] }
1494
1582
  ```
1495
1583
 
1496
- #### Defining the default validation strategy
1584
+ [⬆️ &nbsp;Back to Top](#table-of-contents-)
1585
+
1586
+ ### Defining the default validation strategy
1497
1587
 
1498
1588
  By default, you can define the attribute type directly (without a hash). e.g.
1499
1589
 
@@ -1515,7 +1605,9 @@ And these are the available options to define the default strategy:
1515
1605
  - `kind_of` *(default)*
1516
1606
  - `instance_of`
1517
1607
 
1518
- #### Using the `allow_nil` and `strict` options
1608
+ [⬆️ &nbsp;Back to Top](#table-of-contents-)
1609
+
1610
+ ### Using the `allow_nil` and `strict` options
1519
1611
 
1520
1612
  You can use the `allow_nil` option with any of the kind validations. e.g.
1521
1613
 
data/lib/kind.rb CHANGED
@@ -12,10 +12,10 @@ require 'kind/dig'
12
12
  require 'kind/try'
13
13
  require 'kind/presence'
14
14
  require 'kind/undefined'
15
- require 'kind/type_checker'
15
+ require 'kind/maybe'
16
16
 
17
+ require 'kind/type_checker'
17
18
  require 'kind/type_checkers'
18
- require 'kind/maybe'
19
19
 
20
20
  require 'kind/deprecations/checker'
21
21
  require 'kind/deprecations/of'
@@ -59,7 +59,7 @@ module Kind
59
59
 
60
60
  return is?(expected, object) if UNDEFINED != object
61
61
 
62
- raise ArgumentError, 'wrong number of arguments (given 1, expected 2)'
62
+ WRONG_NUMBER_OF_ARGS.error!(given: 1, expected: 2)
63
63
  end
64
64
 
65
65
  def self.of(kind = UNDEFINED, object = UNDEFINED)
@@ -35,9 +35,9 @@ class KindValidator < ActiveModel::EachValidator
35
35
  def kind_of(expected, value)
36
36
  types = Array(expected)
37
37
 
38
- return if types.any? { |type| value.kind_of?(type) }
38
+ return if types.any? { |type| type === value }
39
39
 
40
- "must be a kind of: #{types.map { |klass| klass.name }.join(', ')}"
40
+ "must be a kind of: #{types.map { |type| type.name }.join(', ')}"
41
41
  end
42
42
 
43
43
  CLASS_OR_MODULE = 'Class/Module'.freeze
@@ -45,7 +45,7 @@ class KindValidator < ActiveModel::EachValidator
45
45
  def kind_is(expected, value)
46
46
  return kind_is_not(expected, value) unless expected.kind_of?(::Array)
47
47
 
48
- result = expected.map { |kind| kind_is_not(kind, value) }.compact
48
+ result = expected.map { |kind| kind_is_not(kind, value) }.tap(&:compact!)
49
49
 
50
50
  result.empty? || result.size < expected.size ? nil : result.join(', ')
51
51
  end
@@ -66,10 +66,17 @@ class KindValidator < ActiveModel::EachValidator
66
66
  end
67
67
  end
68
68
 
69
- def respond_to(method_name, value)
70
- return if value.respond_to?(method_name)
69
+ def respond_to(expected, value)
70
+ method_names = Array(expected)
71
71
 
72
- "must respond to the method `#{method_name}`"
72
+ expected_methods = method_names.select { |method_name| !value.respond_to?(method_name) }
73
+ expected_methods.map! { |method_name| "`#{method_name}`" }
74
+
75
+ return if expected_methods.empty?
76
+
77
+ methods = expected_methods.size == 1 ? 'method' : 'methods'
78
+
79
+ "must respond to the #{methods}: #{expected_methods.join(', ')}"
73
80
  end
74
81
 
75
82
  def instance_of(expected, value)
data/lib/kind/core.rb CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Kind
4
4
  module Core
5
+ require 'kind/core/wrong_number_of_args'
5
6
  require 'kind/core/deprecation'
6
7
  require 'kind/core/kind'
7
8
  require 'kind/core/undefined'
@@ -27,7 +27,7 @@ module Kind
27
27
  end
28
28
 
29
29
  def self.of_module?(value) # :nodoc:
30
- ::Module == value || (value.is_a?(::Module) && !of_class?(value))
30
+ ::Module == value || (value.kind_of?(::Module) && !of_class?(value))
31
31
  end
32
32
 
33
33
  def self.of_module_or_class!(value) # :nodoc:
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kind
4
+ module WRONG_NUMBER_OF_ARGS
5
+ def self.error!(given:, expected:)
6
+ raise ArgumentError, "wrong number of arguments (given #{given}, expected #{expected})"
7
+ end
8
+ end
9
+ end
data/lib/kind/dig.rb CHANGED
@@ -5,7 +5,7 @@ module Kind
5
5
  extend self
6
6
 
7
7
  def call(data, keys)
8
- return unless keys.is_a?(::Array)
8
+ return unless keys.kind_of?(::Array)
9
9
 
10
10
  keys.reduce(data) do |memo, key|
11
11
  value = get(memo, key)
@@ -23,7 +23,7 @@ module Kind
23
23
  alias_method :check, :map
24
24
 
25
25
  def try!(method_name = UNDEFINED, *args, &block)
26
- Kind::Symbol[method_name] if UNDEFINED != method_name
26
+ KIND.of!(::Symbol, method_name)if UNDEFINED != method_name
27
27
 
28
28
  self
29
29
  end
@@ -5,7 +5,7 @@ module Kind
5
5
  class Result
6
6
  attr_reader :value
7
7
 
8
- Value = ->(arg) { arg.kind_of?(::Kind::Maybe::Result) ? arg.value : arg } # :nodoc:
8
+ Value = ->(arg) { arg.kind_of?(Maybe::Result) ? arg.value : arg } # :nodoc:
9
9
 
10
10
  def initialize(arg)
11
11
  @value = Value.(arg)
@@ -58,7 +58,7 @@ module Kind
58
58
  private
59
59
 
60
60
  def __try_method__(method_name, args)
61
- __try_block__(Kind::Symbol[method_name].to_proc, args)
61
+ __try_block__(KIND.of!(::Symbol, method_name).to_proc, args)
62
62
  end
63
63
 
64
64
  def __try_block__(block, args)
@@ -12,7 +12,7 @@ module Kind
12
12
  def new(arg)
13
13
  value = Result::Value.(arg)
14
14
 
15
- value.kind_of?(@kind) ? Maybe.some(value) : Maybe.none
15
+ @kind === value ? Maybe.some(value) : Maybe.none
16
16
  end
17
17
 
18
18
  alias_method :[], :new
@@ -22,7 +22,7 @@ module Kind
22
22
  def __call_before_expose_the_arg_in_a_block(arg)
23
23
  value = Result::Value.(arg)
24
24
 
25
- value.kind_of?(@kind) ? value : Maybe.none
25
+ @kind === value ? value : Maybe.none
26
26
  end
27
27
  end
28
28
  end
@@ -3,8 +3,6 @@
3
3
  module Kind
4
4
  module Maybe
5
5
  module Wrappable
6
- WRONG_NUMBER_OF_ARGS = 'wrong number of arguments (given 0, expected 1)'.freeze
7
-
8
6
  def wrap(arg = UNDEFINED)
9
7
  if block_given?
10
8
  begin
@@ -12,14 +10,14 @@ module Kind
12
10
 
13
11
  input = __call_before_expose_the_arg_in_a_block(arg)
14
12
 
15
- input.kind_of?(Kind::Maybe::None) ? input : new(yield(input))
13
+ input.kind_of?(Maybe::None) ? input : new(yield(input))
16
14
  rescue StandardError => exception
17
15
  Maybe.__none__(exception)
18
16
  end
19
17
  else
20
18
  return new(arg) if UNDEFINED != arg
21
19
 
22
- raise ArgumentError, WRONG_NUMBER_OF_ARGS
20
+ WRONG_NUMBER_OF_ARGS.error!(given: 0, expected: 1)
23
21
  end
24
22
  end
25
23
 
data/lib/kind/try.rb CHANGED
@@ -11,8 +11,6 @@ module Kind
11
11
  end
12
12
 
13
13
  def self.[](*args)
14
- Array[args]
15
-
16
14
  method_name = args.shift
17
15
 
18
16
  ->(object) { call!(object, method_name, args) }
@@ -44,8 +44,22 @@ module Kind
44
44
  KIND.null?(value) ? value : self[value]
45
45
  end
46
46
 
47
+ def maybe(value = UNDEFINED, &block)
48
+ return __maybe[value] if UNDEFINED != value && !block
49
+ return __maybe.wrap(&block) if UNDEFINED == value && block
50
+ return __maybe.wrap(value, &block) if UNDEFINED != value && block
51
+
52
+ __maybe
53
+ end
54
+
55
+ alias optional maybe
56
+
47
57
  private
48
58
 
59
+ def __maybe
60
+ @__maybe ||= Maybe::Typed.new(self)
61
+ end
62
+
49
63
  def __or_func
50
64
  @__or_func ||= ->(tc, fb, value) { tc === value ? value : tc.or_null(fb) }.curry[self]
51
65
  end
data/lib/kind/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kind
4
- VERSION = '4.0.0'
4
+ VERSION = '4.1.0'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kind
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.0
4
+ version: 4.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rodrigo Serradura
@@ -37,6 +37,7 @@ files:
37
37
  - lib/kind/core/deprecation.rb
38
38
  - lib/kind/core/kind.rb
39
39
  - lib/kind/core/undefined.rb
40
+ - lib/kind/core/wrong_number_of_args.rb
40
41
  - lib/kind/deprecations/built_in_type_checkers.rb
41
42
  - lib/kind/deprecations/checker.rb
42
43
  - lib/kind/deprecations/checker/factory.rb