kind 5.6.0 → 5.9.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/.github/workflows/ci.yml +27 -0
- data/.gitignore +1 -0
- data/.vscode/settings.json +8 -0
- data/CHANGELOG.md +269 -33
- data/Gemfile +1 -1
- data/README.md +12 -15
- data/bin/prepare_coverage +27 -0
- data/bin/test +76 -0
- data/lib/kind/__lib__/assert_hash.rb +88 -0
- data/lib/kind/__lib__/strict.rb +44 -2
- data/lib/kind/any.rb +37 -0
- data/lib/kind/basic.rb +15 -3
- data/lib/kind/enum/methods.rb +1 -1
- data/lib/kind/enum.rb +39 -31
- data/lib/kind/objects/object.rb +5 -0
- data/lib/kind/strict/disabled.rb +21 -3
- data/lib/kind/version.rb +1 -1
- metadata +11 -8
- data/.travis.sh +0 -77
- data/.travis.yml +0 -35
- data/test.sh +0 -11
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 195bae736a96e62b9320b209bc7845d6e8c39714342ccb34dfe5bf1ea7c169d8
|
|
4
|
+
data.tar.gz: 2cbf9ba591a62456ff1faf3f8e8e8b1052b9f2c61d96a9a8df62b7ba595a5ac4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 37e37d949dda2c0bbe11642742473200ff42d4300d63642819532fd32beec8485c953588ad100b2c771ec0e8528281d5535180aa21ceb1e53dfe45f992ad7141
|
|
7
|
+
data.tar.gz: 93e92d5db75442cb9c637924d731eec70f7324d50f9c2da91100b1bc916ef8a8ab8c7ea1bbf7590107141a1fc9e81181f51bc5c2848500f0ed7bc940adbaa36f
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
|
|
2
|
+
name: build
|
|
3
|
+
on: [pull_request]
|
|
4
|
+
jobs:
|
|
5
|
+
test:
|
|
6
|
+
runs-on: ubuntu-latest
|
|
7
|
+
strategy:
|
|
8
|
+
matrix:
|
|
9
|
+
ruby: [2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 3.0]
|
|
10
|
+
steps:
|
|
11
|
+
- uses: actions/checkout@v2
|
|
12
|
+
- uses: ruby/setup-ruby@v1
|
|
13
|
+
with:
|
|
14
|
+
ruby-version: ${{ matrix.ruby }}
|
|
15
|
+
bundler-cache: true
|
|
16
|
+
- name: Test and generate coverage
|
|
17
|
+
run: bin/test
|
|
18
|
+
- name: Format coverage
|
|
19
|
+
if: ${{ matrix.ruby >= 3 }}
|
|
20
|
+
run: bin/prepare_coverage
|
|
21
|
+
- uses: paambaati/codeclimate-action@v2.7.5
|
|
22
|
+
if: ${{ matrix.ruby >= 3 }}
|
|
23
|
+
env:
|
|
24
|
+
CC_TEST_REPORTER_ID: 9561ceed21b6724aea8063e82e5700bc8266e962978089594bf2d8f8ca5ffc94
|
|
25
|
+
with:
|
|
26
|
+
debug: true
|
|
27
|
+
coverageLocations: coverage/.resultset.json:simplecov
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -3,83 +3,91 @@
|
|
|
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
|
-
- [5.
|
|
6
|
+
- [5.9.0 (2021-09-22)](#590-2021-09-22)
|
|
7
7
|
- [Added](#added)
|
|
8
|
-
- [5.
|
|
8
|
+
- [5.8.1 (2021-09-22)](#581-2021-09-22)
|
|
9
|
+
- [Fixed](#fixed)
|
|
10
|
+
- [5.8.0 (2021-09-22)](#580-2021-09-22)
|
|
9
11
|
- [Added](#added-1)
|
|
12
|
+
- [5.7.0 (2021-06-22)](#570-2021-06-22)
|
|
13
|
+
- [Added](#added-2)
|
|
14
|
+
- [5.6.0 (2021-05-14)](#560-2021-05-14)
|
|
15
|
+
- [Added](#added-3)
|
|
16
|
+
- [5.5.0 (2021-04-05)](#550-2021-04-05)
|
|
17
|
+
- [Added](#added-4)
|
|
10
18
|
- [5.4.1 (2021-03-26)](#541-2021-03-26)
|
|
11
|
-
- [Fixed](#fixed)
|
|
19
|
+
- [Fixed](#fixed-1)
|
|
12
20
|
- [5.4.0 (2021-03-25)](#540-2021-03-25)
|
|
13
|
-
- [Added](#added-
|
|
21
|
+
- [Added](#added-5)
|
|
14
22
|
- [5.3.0 (2021-03-23)](#530-2021-03-23)
|
|
15
|
-
- [Added](#added-
|
|
23
|
+
- [Added](#added-6)
|
|
16
24
|
- [5.2.0 (2021-03-17)](#520-2021-03-17)
|
|
17
|
-
- [Added](#added-
|
|
25
|
+
- [Added](#added-7)
|
|
18
26
|
- [Deprecated](#deprecated)
|
|
19
27
|
- [Changes](#changes)
|
|
20
28
|
- [5.1.0 (2021-02-23)](#510-2021-02-23)
|
|
21
|
-
- [Added](#added-
|
|
29
|
+
- [Added](#added-8)
|
|
22
30
|
- [Deprecated](#deprecated-1)
|
|
23
31
|
- [5.0.0 (2021-02-22)](#500-2021-02-22)
|
|
24
32
|
- [Breaking Changes](#breaking-changes)
|
|
25
33
|
- [Removed](#removed)
|
|
26
34
|
- [4.1.0 (2021-02-22)](#410-2021-02-22)
|
|
27
|
-
- [Added](#added-
|
|
35
|
+
- [Added](#added-9)
|
|
28
36
|
- [4.0.0 (2021-02-22)](#400-2021-02-22)
|
|
29
|
-
- [Added](#added-
|
|
37
|
+
- [Added](#added-10)
|
|
30
38
|
- [Deprecated](#deprecated-2)
|
|
31
|
-
- [Fixed](#fixed-
|
|
39
|
+
- [Fixed](#fixed-2)
|
|
32
40
|
- [3.1.0 (2020-07-08)](#310-2020-07-08)
|
|
33
|
-
- [Added](#added-
|
|
41
|
+
- [Added](#added-11)
|
|
34
42
|
- [3.0.0 (2020-06-25)](#300-2020-06-25)
|
|
35
43
|
- [Breaking Changes](#breaking-changes-1)
|
|
36
|
-
- [Added](#added-
|
|
44
|
+
- [Added](#added-12)
|
|
37
45
|
- [2.3.0 (2020-06-24)](#230-2020-06-24)
|
|
38
|
-
- [Added](#added-
|
|
46
|
+
- [Added](#added-13)
|
|
39
47
|
- [2.2.0 (2020-06-23)](#220-2020-06-23)
|
|
40
|
-
- [Added](#added-
|
|
48
|
+
- [Added](#added-14)
|
|
41
49
|
- [2.1.0 (2020-05-12)](#210-2020-05-12)
|
|
42
|
-
- [Added](#added-
|
|
50
|
+
- [Added](#added-15)
|
|
43
51
|
- [Breaking Changes](#breaking-changes-2)
|
|
44
52
|
- [2.0.0 (2020-05-07)](#200-2020-05-07)
|
|
45
|
-
- [Added](#added-
|
|
53
|
+
- [Added](#added-16)
|
|
46
54
|
- [Breaking Changes](#breaking-changes-3)
|
|
47
55
|
- [Removed](#removed-1)
|
|
48
56
|
- [1.9.0 (2020-05-06)](#190-2020-05-06)
|
|
49
|
-
- [Added](#added-
|
|
57
|
+
- [Added](#added-17)
|
|
50
58
|
- [1.8.0 (2020-05-03)](#180-2020-05-03)
|
|
51
|
-
- [Added](#added-
|
|
59
|
+
- [Added](#added-18)
|
|
52
60
|
- [1.7.0 (2020-05-03)](#170-2020-05-03)
|
|
53
|
-
- [Fixed](#fixed-
|
|
61
|
+
- [Fixed](#fixed-3)
|
|
54
62
|
- [1.6.0 (2020-04-17)](#160-2020-04-17)
|
|
55
|
-
- [Added](#added-
|
|
63
|
+
- [Added](#added-19)
|
|
56
64
|
- [Changes](#changes-1)
|
|
57
65
|
- [1.5.0 (2020-04-12)](#150-2020-04-12)
|
|
58
|
-
- [Added](#added-
|
|
66
|
+
- [Added](#added-20)
|
|
59
67
|
- [1.4.0 (2020-04-12)](#140-2020-04-12)
|
|
60
|
-
- [Added](#added-
|
|
68
|
+
- [Added](#added-21)
|
|
61
69
|
- [1.3.0 (2020-04-12)](#130-2020-04-12)
|
|
62
|
-
- [Added](#added-
|
|
70
|
+
- [Added](#added-22)
|
|
63
71
|
- [1.2.0 (2020-04-12)](#120-2020-04-12)
|
|
64
|
-
- [Added](#added-
|
|
72
|
+
- [Added](#added-23)
|
|
65
73
|
- [1.1.0 (2020-04-09)](#110-2020-04-09)
|
|
66
|
-
- [Added](#added-
|
|
67
|
-
- [Fixed](#fixed-
|
|
74
|
+
- [Added](#added-24)
|
|
75
|
+
- [Fixed](#fixed-4)
|
|
68
76
|
- [1.0.0 (2020-03-16)](#100-2020-03-16)
|
|
69
|
-
- [Added](#added-
|
|
77
|
+
- [Added](#added-25)
|
|
70
78
|
- [0.6.0 (2020-01-06)](#060-2020-01-06)
|
|
71
|
-
- [Added](#added-
|
|
79
|
+
- [Added](#added-26)
|
|
72
80
|
- [0.5.0 (2020-01-04)](#050-2020-01-04)
|
|
73
|
-
- [Added](#added-
|
|
81
|
+
- [Added](#added-27)
|
|
74
82
|
- [0.4.0 (2020-01-03)](#040-2020-01-03)
|
|
75
|
-
- [Added](#added-
|
|
83
|
+
- [Added](#added-28)
|
|
76
84
|
- [0.3.0 (2020-01-03)](#030-2020-01-03)
|
|
77
|
-
- [Added](#added-
|
|
85
|
+
- [Added](#added-29)
|
|
78
86
|
- [Breaking Changes](#breaking-changes-4)
|
|
79
87
|
- [0.2.0 (2020-01-02)](#020-2020-01-02)
|
|
80
|
-
- [Added](#added-
|
|
88
|
+
- [Added](#added-30)
|
|
81
89
|
- [0.1.0 (2019-12-26)](#010-2019-12-26)
|
|
82
|
-
- [Added](#added-
|
|
90
|
+
- [Added](#added-31)
|
|
83
91
|
|
|
84
92
|
## Unreleased
|
|
85
93
|
|
|
@@ -91,6 +99,234 @@ This project follows [semver 2.0.0](http://semver.org/spec/v2.0.0.html) and the
|
|
|
91
99
|
### Fixed
|
|
92
100
|
-->
|
|
93
101
|
|
|
102
|
+
5.9.0 (2021-09-22)
|
|
103
|
+
------------------
|
|
104
|
+
|
|
105
|
+
### Added
|
|
106
|
+
|
|
107
|
+
* [#68](https://github.com/serradura/kind/pull/68) - Add `Kind.object(name:, &block)` to create `Kind::Objects`.
|
|
108
|
+
```ruby
|
|
109
|
+
PositiveInteger = Kind.object(name: 'PositiveInteger') do |value|
|
|
110
|
+
value.kind_of?(Integer) && value > 0
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# PositiveInteger.name
|
|
114
|
+
# PositiveInteger.kind
|
|
115
|
+
# The type handler can return its kind and its name
|
|
116
|
+
PositiveInteger.name # "PositiveInteger"
|
|
117
|
+
PositiveInteger.kind # #<Proc:0x0000.... >
|
|
118
|
+
|
|
119
|
+
# PositiveInteger.===
|
|
120
|
+
# Can check if a given value is an instance of its kind.
|
|
121
|
+
PositiveInteger === 1 # true
|
|
122
|
+
PositiveInteger === 0 # false
|
|
123
|
+
|
|
124
|
+
# PositiveInteger.value?(value)
|
|
125
|
+
# Can check if a given value is an instance of its kind.
|
|
126
|
+
PositiveInteger.value?(1) # true
|
|
127
|
+
PositiveInteger.value?(-1) # false
|
|
128
|
+
|
|
129
|
+
# If it doesn't receive an argument, a lambda will be returned and it will know how to do the type verification.
|
|
130
|
+
[1, 2, 0, 3, -1].select(&PositiveInteger.value?) # [1, 2, 3]
|
|
131
|
+
|
|
132
|
+
# PositiveInteger.or_nil(value)
|
|
133
|
+
# Can return nil if the given value isn't an instance of its kind
|
|
134
|
+
PositiveInteger.or_nil(1) # 1
|
|
135
|
+
PositiveInteger.or_nil(0) # nil
|
|
136
|
+
|
|
137
|
+
# PositiveInteger.or_undefined(value)
|
|
138
|
+
# Can return Kind::Undefined if the given value isn't an instance of its kind
|
|
139
|
+
PositiveInteger.or_undefined(2) # 2
|
|
140
|
+
PositiveInteger.or_undefined(-1) # Kind::Undefined
|
|
141
|
+
|
|
142
|
+
# PositiveInteger.or(fallback, value)
|
|
143
|
+
# Can return a fallback if the given value isn't an instance of its kind
|
|
144
|
+
PositiveInteger.or(nil, 1) # 1
|
|
145
|
+
PositiveInteger.or(nil, 0) # nil
|
|
146
|
+
|
|
147
|
+
# If it doesn't receive a second argument (the value), it will return a callable that knows how to expose an instance of the expected type or a fallback if the given value was wrong.
|
|
148
|
+
[1, 2, 0, 3, -1].map(&PositiveInteger.or(1)) # [1, 2, 1, 3, 1]
|
|
149
|
+
[1, 2, 0, 3, -1].map(&PositiveInteger.or(nil)) # [1, 2, nil, 3, nil]
|
|
150
|
+
|
|
151
|
+
# An error will be raised if the fallback didn't have the expected kind or if not nil / Kind::Undefined.
|
|
152
|
+
[1, 2, 0, 3, -1].map(&PositiveInteger.or(:foo)) # Kind::Error (:foo expected to be a kind of PositiveInteger)
|
|
153
|
+
|
|
154
|
+
# PositiveInteger[value]
|
|
155
|
+
# Will raise Kind::Error if the given value isn't an instance of the expected kind
|
|
156
|
+
PositiveInteger[1] # 1
|
|
157
|
+
PositiveInteger[:foo] # Kind::Error (:foo expected to be a kind of PositiveInteger)
|
|
158
|
+
|
|
159
|
+
# PositiveInteger.value(arg, default:)
|
|
160
|
+
# 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.
|
|
161
|
+
PositiveInteger.value(2, default: 1) # 2
|
|
162
|
+
|
|
163
|
+
PositiveInteger.value('1', default: 1) # 1
|
|
164
|
+
|
|
165
|
+
PositiveInteger.value('1', default: 0) # Kind::Error (0 expected to be a kind of PositiveInteger)
|
|
166
|
+
|
|
167
|
+
# PositiveInteger.maybe
|
|
168
|
+
# This method returns a typed Kind::Maybe.
|
|
169
|
+
PositiveInteger.maybe(0).value_or(1) # 1
|
|
170
|
+
|
|
171
|
+
PositiveInteger.maybe(2).value_or(1) # 2
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
[⬆️ Back to Top](#changelog-)
|
|
175
|
+
|
|
176
|
+
5.8.1 (2021-09-22)
|
|
177
|
+
------------------
|
|
178
|
+
|
|
179
|
+
### Fixed
|
|
180
|
+
|
|
181
|
+
* [#67](https://github.com/serradura/kind/pull/67) - Make `Kind.assert_hash!(some_hash, schema:)` works with a `Kind::Any` instance.
|
|
182
|
+
```ruby
|
|
183
|
+
require 'kind/any'
|
|
184
|
+
|
|
185
|
+
Level = Kind::Any[:low, :high]
|
|
186
|
+
|
|
187
|
+
Kind.assert_hash!({level: :medium}, schema: {level: Level})
|
|
188
|
+
# Kind::Error (The key :status has an invalid value. Expected: Kind::Any[:low, :high])
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
[⬆️ Back to Top](#changelog-)
|
|
192
|
+
|
|
193
|
+
5.8.0 (2021-09-22)
|
|
194
|
+
------------------
|
|
195
|
+
|
|
196
|
+
### Added
|
|
197
|
+
|
|
198
|
+
* [#66](https://github.com/serradura/kind/pull/66) - Add `Kind::Any` to make easier the verification of a value in a list (array) of expected values.
|
|
199
|
+
```ruby
|
|
200
|
+
require 'kind/any'
|
|
201
|
+
|
|
202
|
+
Level = Kind::Any[:low, :high] # or Kind::Any.new([:low, :high])
|
|
203
|
+
|
|
204
|
+
Level === :low # true
|
|
205
|
+
Level === :high # true
|
|
206
|
+
|
|
207
|
+
Level === :foo # false
|
|
208
|
+
|
|
209
|
+
Level[:low] # :low
|
|
210
|
+
Level[:high] # :high
|
|
211
|
+
|
|
212
|
+
Level[:foo] # Kind::Error (:foo expected to be a kind of Kind::Any[:low, :high])
|
|
213
|
+
|
|
214
|
+
level_or_any_symbol = # (Kind::Any[:low, :high] | Symbol)
|
|
215
|
+
|
|
216
|
+
Level.name # 'Kind::Any[:low, :high]'
|
|
217
|
+
Level.inspect # 'Kind::Any[:low, :high]'
|
|
218
|
+
|
|
219
|
+
Level.values # [:low, :high]
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
* [#66](https://github.com/serradura/kind/pull/66) - Make `Kind.assert_hash!(hash, schema:)` works with a `Kind::Object`.
|
|
223
|
+
```ruby
|
|
224
|
+
require 'kind/enum'
|
|
225
|
+
|
|
226
|
+
module Level
|
|
227
|
+
include Kind::Enum.from_array([:low, :medium, :high], use_index_as_value: false)
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
Level.keys # ["low", "medium", "high"]
|
|
231
|
+
Level.values # [:low, :medium, :high]
|
|
232
|
+
|
|
233
|
+
# ---
|
|
234
|
+
|
|
235
|
+
module Status
|
|
236
|
+
include Kind::Enum.from_array([:open, :closed], use_index_as_value: true)
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
Status.keys # ["open", "closed"]
|
|
240
|
+
Status.values # [0, 1]
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
* [#66](https://github.com/serradura/kind/pull/66) - Make `Kind.assert_hash!(hash, schema:)` works with a `Kind::Object`.
|
|
244
|
+
```ruby
|
|
245
|
+
FilledString = begin
|
|
246
|
+
filled_string = ->(value) {value.is_a?(String) && value.present?}
|
|
247
|
+
|
|
248
|
+
Kind[filled_string, name: 'FilledString']
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
Kind.assert_hash!(some_hash, schema: {
|
|
252
|
+
string: FilledString,
|
|
253
|
+
callable: Kind::Callable,
|
|
254
|
+
})
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
* [#66](https://github.com/serradura/kind/pull/66) - Improve the exception messages of `Kind.assert_hash!(hash, schema:)`.
|
|
258
|
+
```ruby
|
|
259
|
+
Kind.assert_hash!({status: 1}, schema: {status: Kind::String | Symbol})
|
|
260
|
+
# Kind::Error (The key :status has an invalid value. Expected: (String | Symbol))
|
|
261
|
+
|
|
262
|
+
Kind.assert_hash!({status: 'closed'}, schema: {status: 'active'})
|
|
263
|
+
# Kind::Error (The key :status has an invalid value. Expected: active, Given: closed)
|
|
264
|
+
|
|
265
|
+
Kind.assert_hash!({callable: 1}, schema: {callable: Kind::Callable})
|
|
266
|
+
# Kind::Error (The key :callable has an invalid value. Expected: Callable)
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
* [#66](https://github.com/serradura/kind/pull/66) - Make `Kind.assert_hash!(hash, **options)` raises an error if the given hash be empty.
|
|
270
|
+
```ruby
|
|
271
|
+
Kind.assert_hash!({}, keys: []) # ArgumentError (hash can't be empty)
|
|
272
|
+
Kind.assert_hash!({}, schema: {}) # ArgumentError (hash can't be empty)
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
[⬆️ Back to Top](#changelog-)
|
|
276
|
+
|
|
277
|
+
5.7.0 (2021-06-22)
|
|
278
|
+
------------------
|
|
279
|
+
|
|
280
|
+
### Added
|
|
281
|
+
|
|
282
|
+
* [#58](https://github.com/serradura/kind/pull/58) - Add `Add Kind.assert_hash!(hash, keys:)`, you can use the `require_all:` option to check if the hashes have the same keys.
|
|
283
|
+
```ruby
|
|
284
|
+
h1 = {a: 1, b: 1}
|
|
285
|
+
|
|
286
|
+
Kind.assert_hash!(h1, keys: [:a, :b])
|
|
287
|
+
Kind.assert_hash!(h1, keys: [:a]) # ArgumentError (Unknown key: :b. Valid keys are: :a)
|
|
288
|
+
|
|
289
|
+
# --
|
|
290
|
+
|
|
291
|
+
h2 = {'a' => 1, 'b' => 2}
|
|
292
|
+
|
|
293
|
+
Kind.assert_hash!(h2, keys: ['a', 'b'])
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
* [#58](https://github.com/serradura/kind/pull/58) - Add `Add Kind.assert_hash!(hash, schema:)`, you can use the `require_all:` option to check if the hashes have the same keys.
|
|
297
|
+
```ruby
|
|
298
|
+
hash = {hash: {}, array: [], number: 1, string: 'foo', email: 'bar@bar.com', null: nil}
|
|
299
|
+
|
|
300
|
+
Kind.assert_hash!(hash, schema: {
|
|
301
|
+
hash: {},
|
|
302
|
+
array: [],
|
|
303
|
+
email: 'bar@bar.com',
|
|
304
|
+
string: 'foo',
|
|
305
|
+
number: 1,
|
|
306
|
+
null: nil
|
|
307
|
+
})
|
|
308
|
+
|
|
309
|
+
Kind.assert_hash!(hash, schema: {
|
|
310
|
+
hash: Enumerable,
|
|
311
|
+
array: Enumerable,
|
|
312
|
+
email: /\A.+@.+\..+\z/,
|
|
313
|
+
string: String
|
|
314
|
+
})
|
|
315
|
+
|
|
316
|
+
Kind.assert_hash!(hash, schema: {
|
|
317
|
+
hash: Hash,
|
|
318
|
+
array: Array,
|
|
319
|
+
email: String,
|
|
320
|
+
string: String
|
|
321
|
+
})
|
|
322
|
+
|
|
323
|
+
Kind.assert_hash!(h1, schema: {
|
|
324
|
+
email: ->(value) { value.is_a?(String) && value.include?('@') }
|
|
325
|
+
})
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
[⬆️ Back to Top](#changelog-)
|
|
329
|
+
|
|
94
330
|
5.6.0 (2021-05-14)
|
|
95
331
|
------------------
|
|
96
332
|
|
data/Gemfile
CHANGED
data/README.md
CHANGED
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
<img alt="Gem" src="https://img.shields.io/gem/v/kind.svg?style=flat-square">
|
|
9
9
|
</a>
|
|
10
10
|
|
|
11
|
-
<a href="https://
|
|
12
|
-
<img alt="Build Status" src="https://
|
|
11
|
+
<a href="https://github.com/serradura/kind/actions/workflows/ci.yml">
|
|
12
|
+
<img alt="Build Status" src="https://github.com/serradura/kind/actions/workflows/ci.yml/badge.svg">
|
|
13
13
|
</a>
|
|
14
14
|
|
|
15
15
|
<br />
|
|
@@ -42,7 +42,7 @@ So, I invite you to check out these features to see how they could be useful for
|
|
|
42
42
|
Version | Documentation
|
|
43
43
|
---------- | -------------
|
|
44
44
|
unreleased | https://github.com/serradura/kind/blob/main/README.md
|
|
45
|
-
5.
|
|
45
|
+
5.9.0 | https://github.com/serradura/kind/blob/v5.x/README.md
|
|
46
46
|
4.1.0 | https://github.com/serradura/kind/blob/v4.x/README.md
|
|
47
47
|
3.1.0 | https://github.com/serradura/kind/blob/v3.x/README.md
|
|
48
48
|
2.3.0 | https://github.com/serradura/kind/blob/v2.x/README.md
|
|
@@ -69,7 +69,7 @@ unreleased | https://github.com/serradura/kind/blob/main/README.md
|
|
|
69
69
|
- [Creating type handlers](#creating-type-handlers)
|
|
70
70
|
- [Dynamic creation](#dynamic-creation)
|
|
71
71
|
- [Using a class or a module](#using-a-class-or-a-module)
|
|
72
|
-
- [Using
|
|
72
|
+
- [Using Kind.object(name:, &block) ===](#using-kindobjectname-block-)
|
|
73
73
|
- [Kind::<Type> object](#kindtype-object)
|
|
74
74
|
- [Utility methods](#utility-methods)
|
|
75
75
|
- [Kind.of_class?()](#kindof_class)
|
|
@@ -125,7 +125,7 @@ unreleased | https://github.com/serradura/kind/blob/main/README.md
|
|
|
125
125
|
| kind | branch | ruby | activemodel |
|
|
126
126
|
| -------------- | ------- | ------------------ | -------------- |
|
|
127
127
|
| unreleased | main | >= 2.1.0, <= 3.0.0 | >= 3.2, < 7.0 |
|
|
128
|
-
| 5.
|
|
128
|
+
| 5.9.0 | v5.x | >= 2.1.0, <= 3.0.0 | >= 3.2, < 7.0 |
|
|
129
129
|
| 4.1.0 | v4.x | >= 2.2.0, <= 3.0.0 | >= 3.2, < 7.0 |
|
|
130
130
|
| 3.1.0 | v3.x | >= 2.2.0, <= 2.7 | >= 3.2, < 7.0 |
|
|
131
131
|
| 2.3.0 | v2.x | >= 2.2.0, <= 2.7 | >= 3.2, <= 6.0 |
|
|
@@ -393,7 +393,7 @@ end
|
|
|
393
393
|
|
|
394
394
|
user = User.new
|
|
395
395
|
|
|
396
|
-
kind_of_user = Kind
|
|
396
|
+
kind_of_user = Kind[User]
|
|
397
397
|
|
|
398
398
|
# kind_of_user.name
|
|
399
399
|
# kind_of_user.kind
|
|
@@ -412,7 +412,7 @@ kind_of_user.value?('') # false
|
|
|
412
412
|
kind_of_user.value?(User.new) # true
|
|
413
413
|
|
|
414
414
|
# If it doesn't receive an argument, a lambda will be returned and it will know how to do the type verification.
|
|
415
|
-
[0, User.new].select
|
|
415
|
+
[0, User.new].select(&kind_of_user.value?) # [#<User:0x0000.... >]
|
|
416
416
|
|
|
417
417
|
# kind_of_user.or_nil(value)
|
|
418
418
|
# Can return nil if the given value isn't an instance of its kind
|
|
@@ -455,15 +455,12 @@ kind_of_user.maybe('1').value_or(User.new) # #<User:0x0000...>
|
|
|
455
455
|
|
|
456
456
|
[⬆️ Back to Top](#table-of-contents-)
|
|
457
457
|
|
|
458
|
-
##### Using
|
|
459
|
-
|
|
460
|
-
Example using a lambda (an object which responds to .===) and a hash with the kind name.
|
|
458
|
+
##### Using Kind.object(name:, &block) ===
|
|
461
459
|
|
|
462
460
|
```ruby
|
|
463
|
-
PositiveInteger = Kind
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
)
|
|
461
|
+
PositiveInteger = Kind.object(name: 'PositiveInteger') do |value|
|
|
462
|
+
value.kind_of?(Integer) && value > 0
|
|
463
|
+
end
|
|
467
464
|
|
|
468
465
|
# PositiveInteger.name
|
|
469
466
|
# PositiveInteger.kind
|
|
@@ -482,7 +479,7 @@ PositiveInteger.value?(1) # true
|
|
|
482
479
|
PositiveInteger.value?(-1) # false
|
|
483
480
|
|
|
484
481
|
# If it doesn't receive an argument, a lambda will be returned and it will know how to do the type verification.
|
|
485
|
-
[1, 2, 0, 3, -1].select
|
|
482
|
+
[1, 2, 0, 3, -1].select(&PositiveInteger.value?) # [1, 2, 3]
|
|
486
483
|
|
|
487
484
|
# PositiveInteger.or_nil(value)
|
|
488
485
|
# Can return nil if the given value isn't an instance of its kind
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
# Borrowed from https://gist.github.com/qortex/7e7c49f3731391a91ee898336183acef
|
|
4
|
+
|
|
5
|
+
# Temporary hack to get CodeClimate to work with SimpleCov 0.18 JSON format until issue is fixed
|
|
6
|
+
# upstream: https://github.com/codeclimate/test-reporter/issues/413
|
|
7
|
+
|
|
8
|
+
require "json"
|
|
9
|
+
|
|
10
|
+
filename = "coverage/.resultset.json"
|
|
11
|
+
contents = JSON.parse(File.read(filename))
|
|
12
|
+
|
|
13
|
+
def remove_lines_key(obj)
|
|
14
|
+
case obj
|
|
15
|
+
when Hash
|
|
16
|
+
obj.transform_values do |val|
|
|
17
|
+
val.is_a?(Hash) && val.key?("lines") ? val["lines"] : remove_lines_key(val)
|
|
18
|
+
end
|
|
19
|
+
else
|
|
20
|
+
obj
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# overwrite
|
|
25
|
+
File.write(filename, JSON.generate(remove_lines_key(contents)))
|
|
26
|
+
|
|
27
|
+
puts Dir['coverage/.*.json']
|
data/bin/test
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
set -e
|
|
4
|
+
|
|
5
|
+
RUBY_V=$(ruby -v)
|
|
6
|
+
|
|
7
|
+
function reset_gemfile_and_test {
|
|
8
|
+
rm Gemfile.lock
|
|
9
|
+
|
|
10
|
+
eval "$1 bundle update"
|
|
11
|
+
eval "$1 bundle exec rake test"
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function test_with_activemodel {
|
|
15
|
+
reset_gemfile_and_test "ACTIVEMODEL_VERSION=$1"
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function run_tests_by_modules {
|
|
19
|
+
rm Gemfile.lock
|
|
20
|
+
|
|
21
|
+
bundle update
|
|
22
|
+
|
|
23
|
+
eval "KIND_BASIC=t bundle exec rake test TEST='test/kind/{basic/*_test,basic_test}.rb'"
|
|
24
|
+
eval "KIND_BASIC=t bundle exec rake test TEST='test/kind/enum_test.rb'"
|
|
25
|
+
eval "KIND_BASIC=t bundle exec rake test TEST='test/kind/presence_test.rb'"
|
|
26
|
+
eval "KIND_BASIC=t bundle exec rake test TEST='test/kind/dig_test.rb'"
|
|
27
|
+
eval "KIND_BASIC=t bundle exec rake test TEST='test/kind/try_test.rb'"
|
|
28
|
+
eval "KIND_BASIC=t bundle exec rake test TEST='test/kind/maybe_test.rb'"
|
|
29
|
+
eval "KIND_BASIC=t bundle exec rake test TEST='test/kind/immutable_attributes_test.rb'"
|
|
30
|
+
eval "KIND_BASIC=t bundle exec rake test TEST='test/kind/function_test.rb'"
|
|
31
|
+
eval "KIND_BASIC=t bundle exec rake test TEST='test/kind/action_test.rb'"
|
|
32
|
+
eval "KIND_BASIC=t bundle exec rake test TEST='test/kind/{functional/*_test,functional_test}.rb'"
|
|
33
|
+
eval "KIND_BASIC=t bundle exec rake test TEST='test/kind/either/*_test.rb'"
|
|
34
|
+
eval "KIND_BASIC=t bundle exec rake test TEST='test/kind/result/*_test.rb'"
|
|
35
|
+
|
|
36
|
+
eval "KIND_STRICT=t bundle exec rake test TEST='test/kind/strict_disabled_test.rb'"
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
RUBY_2_12345="ruby 2.[12345]."
|
|
40
|
+
RUBY_2_2345="ruby 2.[2345]."
|
|
41
|
+
RUBY_2_1234="ruby 2.[1234]."
|
|
42
|
+
RUBY_2_567="ruby 2.[567]."
|
|
43
|
+
RUBY_2_12="ruby 2.[12]."
|
|
44
|
+
RUBY_3_X="ruby 3.0."
|
|
45
|
+
|
|
46
|
+
if [[ $RUBY_V =~ $RUBY_2_12345 ]]; then
|
|
47
|
+
if [[ $RUBY_V =~ $RUBY_2_12 ]]; then
|
|
48
|
+
test_with_activemodel "3.2"
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
if [[ $RUBY_V =~ $RUBY_2_2345 ]]; then
|
|
52
|
+
test_with_activemodel "4.0"
|
|
53
|
+
test_with_activemodel "4.1"
|
|
54
|
+
test_with_activemodel "4.2"
|
|
55
|
+
test_with_activemodel "5.0"
|
|
56
|
+
test_with_activemodel "5.1"
|
|
57
|
+
test_with_activemodel "5.2"
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
if [[ $RUBY_V =~ $RUBY_2_1234 ]]; then
|
|
61
|
+
run_tests_by_modules
|
|
62
|
+
|
|
63
|
+
reset_gemfile_and_test
|
|
64
|
+
fi
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
if [[ $RUBY_V =~ $RUBY_2_567 ]] || [[ $RUBY_V =~ $RUBY_3_X ]]; then
|
|
68
|
+
gem install bundler -v ">= 2" --no-doc
|
|
69
|
+
|
|
70
|
+
test_with_activemodel "6.0"
|
|
71
|
+
test_with_activemodel "6.1"
|
|
72
|
+
|
|
73
|
+
run_tests_by_modules
|
|
74
|
+
|
|
75
|
+
reset_gemfile_and_test
|
|
76
|
+
fi
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Kind
|
|
4
|
+
module AssertHash
|
|
5
|
+
module Keys
|
|
6
|
+
def self.require_all(keys, hash)
|
|
7
|
+
expected_keys = keys - hash.keys
|
|
8
|
+
|
|
9
|
+
unless expected_keys.empty?
|
|
10
|
+
raise KeyError.new("#{hash.inspect} expected to have these keys: #{expected_keys}")
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
unexpected_keys = hash.keys - keys
|
|
14
|
+
|
|
15
|
+
unless unexpected_keys.empty?
|
|
16
|
+
raise KeyError.new("#{hash.inspect} expected to NOT have these keys: #{unexpected_keys}")
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
hash
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
module Schema
|
|
24
|
+
extend self
|
|
25
|
+
|
|
26
|
+
KindAny = ->(value) { defined?(Kind::Any) ? Kind::Any === value : false }
|
|
27
|
+
KindObject = ->(value) { defined?(Kind::Object) ? Kind::Object === value : false }
|
|
28
|
+
KindUnionType = ->(value) { defined?(Kind::UnionType) ? Kind::UnionType === value : false }
|
|
29
|
+
|
|
30
|
+
def any(hash, spec)
|
|
31
|
+
spec.each do |key, expected|
|
|
32
|
+
value = hash[key]
|
|
33
|
+
error_message = "The key #{key.inspect} has an invalid value"
|
|
34
|
+
|
|
35
|
+
case expected
|
|
36
|
+
when KindAny, KindObject, KindUnionType then assert_kind_object(expected, value, error_message)
|
|
37
|
+
when ::Module then assert_kind_of(expected, value, error_message)
|
|
38
|
+
when ::Proc then assert(expected.call(value), error_message)
|
|
39
|
+
when ::Regexp then assert_match(expected, value, error_message)
|
|
40
|
+
when ::NilClass then assert_nil(value, error_message)
|
|
41
|
+
else assert_equal(expected, value, error_message)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
hash
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def all(hash, spec)
|
|
49
|
+
Keys.require_all(spec.keys, hash)
|
|
50
|
+
|
|
51
|
+
any(hash, spec)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
def assert_equal(expected, value, message)
|
|
57
|
+
raise_kind_error("#{message}. Expected: #{expected.inspect}, Given: #{value.inspect}") if expected != value
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def assert(value, message)
|
|
61
|
+
raise_kind_error(message) unless value
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def assert_nil(value, message)
|
|
65
|
+
raise_kind_error("#{message}. Expected: nil") unless value.nil?
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def assert_match(expected, value, message)
|
|
69
|
+
STRICT.kind_of(String, value)
|
|
70
|
+
|
|
71
|
+
raise_kind_error("#{message}. Expected: #{expected.inspect}") if value !~ expected
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def assert_kind_of(expected, value, message)
|
|
75
|
+
raise_kind_error("#{message}. Expected: #{expected.inspect}") unless expected === value
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def assert_kind_object(expected, value, message)
|
|
79
|
+
raise_kind_error("#{message}. Expected: #{expected.name}") unless expected === value
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def raise_kind_error(message)
|
|
84
|
+
raise Error.new(message)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
data/lib/kind/__lib__/strict.rb
CHANGED
|
@@ -6,14 +6,16 @@ module Kind
|
|
|
6
6
|
module STRICT
|
|
7
7
|
extend self
|
|
8
8
|
|
|
9
|
+
require 'kind/__lib__/assert_hash'
|
|
10
|
+
|
|
9
11
|
def error(kind_name, value, label = nil) # :nodoc:
|
|
10
12
|
raise Error.new(kind_name, value, label: label)
|
|
11
13
|
end
|
|
12
14
|
|
|
13
|
-
def object_is_a(kind, value, label = nil) # :nodoc:
|
|
15
|
+
def object_is_a(kind, value, label = nil, expected = nil) # :nodoc:
|
|
14
16
|
return value if kind === value
|
|
15
17
|
|
|
16
|
-
error(kind.name, value, label)
|
|
18
|
+
error(expected || kind.name, value, label)
|
|
17
19
|
end
|
|
18
20
|
|
|
19
21
|
def kind_of(kind, value, kind_name = nil) # :nodoc:
|
|
@@ -43,6 +45,46 @@ module Kind
|
|
|
43
45
|
|
|
44
46
|
raise Error.new("#{label_text}expected to not be nil")
|
|
45
47
|
end
|
|
48
|
+
|
|
49
|
+
def in!(list, value)
|
|
50
|
+
return value if list.include?(value)
|
|
51
|
+
|
|
52
|
+
raise Error.new("#{value} expected to be included in #{list.inspect}")
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def assert_hash!(hash, options)
|
|
56
|
+
check_keys = options.key?(:keys)
|
|
57
|
+
check_schema = options.key?(:schema)
|
|
58
|
+
|
|
59
|
+
raise ArgumentError, ':keys or :schema is missing' if !check_keys && !check_schema
|
|
60
|
+
raise ArgumentError, "hash can't be empty" if hash.empty?
|
|
61
|
+
|
|
62
|
+
require_all = options[:require_all]
|
|
63
|
+
|
|
64
|
+
return assert_hash_keys!(hash, options[:keys], require_all) if check_keys
|
|
65
|
+
|
|
66
|
+
assert_hash_schema!(hash, options[:schema], require_all)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
private
|
|
70
|
+
|
|
71
|
+
def assert_hash_keys!(hash, arg, require_all)
|
|
72
|
+
keys = Array(arg)
|
|
73
|
+
|
|
74
|
+
AssertHash::Keys.require_all(keys, hash) if require_all
|
|
75
|
+
|
|
76
|
+
hash.each_key do |k|
|
|
77
|
+
unless keys.include?(k)
|
|
78
|
+
raise ArgumentError.new("Unknown key: #{k.inspect}. Valid keys are: #{keys.map(&:inspect).join(', ')}")
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def assert_hash_schema!(hash, schema, require_all)
|
|
84
|
+
return AssertHash::Schema.all(hash, schema) if require_all
|
|
85
|
+
|
|
86
|
+
AssertHash::Schema.any(hash, schema)
|
|
87
|
+
end
|
|
46
88
|
end
|
|
47
89
|
|
|
48
90
|
private_constant :STRICT
|
data/lib/kind/any.rb
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Kind
|
|
4
|
+
class Any
|
|
5
|
+
FilledArray = ->(value) {value.is_a?(::Array) && !value.empty?}
|
|
6
|
+
|
|
7
|
+
singleton_class.send(:alias_method, :[], :new)
|
|
8
|
+
|
|
9
|
+
attr_reader :values
|
|
10
|
+
|
|
11
|
+
def initialize(*args)
|
|
12
|
+
array = args.size == 1 ? args[0] : args
|
|
13
|
+
|
|
14
|
+
@values = Kind.of(FilledArray, array, expected: 'filled array')
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def ===(other)
|
|
18
|
+
@values.any? { |value| value == other }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def [](value, label: nil)
|
|
22
|
+
STRICT.object_is_a(self, value, label)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def |(another_kind)
|
|
26
|
+
UnionType[self] | another_kind
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def name
|
|
30
|
+
"Kind::Any#{@values}"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
alias inspect name
|
|
34
|
+
|
|
35
|
+
private_constant :FilledArray
|
|
36
|
+
end
|
|
37
|
+
end
|
data/lib/kind/basic.rb
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
require 'kind/version'
|
|
4
4
|
|
|
5
|
-
require 'kind/__lib__/kind'
|
|
6
5
|
require 'kind/__lib__/undefined'
|
|
6
|
+
require 'kind/__lib__/kind'
|
|
7
7
|
|
|
8
8
|
require 'kind/basic/undefined'
|
|
9
9
|
require 'kind/basic/error'
|
|
@@ -48,8 +48,8 @@ module Kind
|
|
|
48
48
|
KIND.interface?(method_names, value)
|
|
49
49
|
end
|
|
50
50
|
|
|
51
|
-
def of(kind, value, label: nil)
|
|
52
|
-
STRICT.object_is_a(kind, value, label)
|
|
51
|
+
def of(kind, value, label: nil, expected: nil)
|
|
52
|
+
STRICT.object_is_a(kind, value, label, expected)
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
alias_method :of!, :of
|
|
@@ -80,4 +80,16 @@ module Kind
|
|
|
80
80
|
def or_nil(kind, value)
|
|
81
81
|
return value if kind === value
|
|
82
82
|
end
|
|
83
|
+
|
|
84
|
+
def in!(list, value)
|
|
85
|
+
STRICT.in!(list, value)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def include!(value, list)
|
|
89
|
+
STRICT.in!(list, value)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def assert_hash!(hash, **kargs)
|
|
93
|
+
STRICT.assert_hash!(hash, kargs)
|
|
94
|
+
end
|
|
83
95
|
end
|
data/lib/kind/enum/methods.rb
CHANGED
data/lib/kind/enum.rb
CHANGED
|
@@ -11,50 +11,58 @@ module Kind
|
|
|
11
11
|
extend self
|
|
12
12
|
|
|
13
13
|
def values(input)
|
|
14
|
-
|
|
14
|
+
__create(input)
|
|
15
|
+
end
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
when ::Array then create_from_array(input)
|
|
20
|
-
else raise ArgumentError, 'use an array or hash to define a Kind::Enum'
|
|
21
|
-
end
|
|
17
|
+
def from_array(input, use_index_as_value:)
|
|
18
|
+
__create(input, use_index_as_value)
|
|
19
|
+
end
|
|
22
20
|
|
|
23
|
-
|
|
21
|
+
private
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
memo[item.value] = item
|
|
28
|
-
memo[item.to_sym] = item
|
|
29
|
-
end
|
|
23
|
+
def __create(input, use_index_as_value = true)
|
|
24
|
+
enum_module = ::Module.new
|
|
30
25
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
26
|
+
enum_items =
|
|
27
|
+
case input
|
|
28
|
+
when ::Hash then __create_from_hash(input)
|
|
29
|
+
when ::Array then __create_from_array(input, use_index_as_value)
|
|
30
|
+
else raise ArgumentError, 'use an array or hash to define a Kind::Enum'
|
|
31
|
+
end
|
|
37
32
|
|
|
38
|
-
|
|
39
|
-
:ENUM__VALS, :ENUM__REFS, :ENUM__ITEMS)
|
|
33
|
+
enum_items.each { |item| enum_module.const_set(item.name, item) }
|
|
40
34
|
|
|
41
|
-
|
|
35
|
+
enum_map = enum_items.each_with_object({}) do |item, memo|
|
|
36
|
+
memo[item.to_s] = item
|
|
37
|
+
memo[item.value] = item
|
|
38
|
+
memo[item.to_sym] = item
|
|
39
|
+
end
|
|
42
40
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
41
|
+
enum_module.const_set(:ENUM__MAP, enum_map)
|
|
42
|
+
enum_module.const_set(:ENUM__HASH, enum_items.map(&:to_ary).to_h.freeze)
|
|
43
|
+
enum_module.const_set(:ENUM__KEYS, ::Set.new(enum_items.map(&:key)).freeze)
|
|
44
|
+
enum_module.const_set(:ENUM__VALS, ::Set.new(enum_items.map(&:value)).freeze)
|
|
45
|
+
enum_module.const_set(:ENUM__REFS, ::Set.new(enum_map.keys))
|
|
46
|
+
enum_module.const_set(:ENUM__ITEMS, enum_items.freeze)
|
|
46
47
|
|
|
47
|
-
|
|
48
|
+
enum_module.send(:private_constant, :ENUM__MAP, :ENUM__HASH, :ENUM__KEYS,
|
|
49
|
+
:ENUM__VALS, :ENUM__REFS, :ENUM__ITEMS)
|
|
50
|
+
|
|
51
|
+
enum_module.module_eval(METHODS)
|
|
52
|
+
|
|
53
|
+
enum_module.extend(enum_module)
|
|
54
|
+
enum_module
|
|
55
|
+
end
|
|
48
56
|
|
|
49
|
-
def
|
|
50
|
-
input.map { |key, value|
|
|
57
|
+
def __create_from_hash(input)
|
|
58
|
+
input.map { |key, value| __item(key, value) }
|
|
51
59
|
end
|
|
52
60
|
|
|
53
|
-
def
|
|
54
|
-
input.map.with_index { |key, index|
|
|
61
|
+
def __create_from_array(input, use_index_as_value)
|
|
62
|
+
input.map.with_index { |key, index| use_index_as_value ? __item(key, index) : __item(key, key) }
|
|
55
63
|
end
|
|
56
64
|
|
|
57
|
-
def
|
|
65
|
+
def __item(key, value)
|
|
58
66
|
return Item.new(key, value) if key.respond_to?(:to_sym)
|
|
59
67
|
|
|
60
68
|
raise ArgumentError, 'use a string or symbol to define a Kind::Enum item'
|
data/lib/kind/objects/object.rb
CHANGED
|
@@ -46,6 +46,11 @@ module Kind
|
|
|
46
46
|
Object::Instance.new(kind, opt)
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
+
# Kind.object(name:,&block)
|
|
50
|
+
def self.object(name:, &block)
|
|
51
|
+
self[block, name: name]
|
|
52
|
+
end
|
|
53
|
+
|
|
49
54
|
# Kind::Of()
|
|
50
55
|
def self.Of(*args)
|
|
51
56
|
warn '[DEPRECATION] Kind::Of() is deprecated; use Kind[] instead. ' \
|
data/lib/kind/strict/disabled.rb
CHANGED
|
@@ -3,11 +3,17 @@
|
|
|
3
3
|
module Kind
|
|
4
4
|
module STRICT
|
|
5
5
|
[
|
|
6
|
-
:object_is_a,
|
|
7
|
-
:
|
|
6
|
+
:object_is_a,
|
|
7
|
+
:class!,
|
|
8
|
+
:kind_of,
|
|
9
|
+
:module_or_class,
|
|
10
|
+
:module!,
|
|
11
|
+
:not_nil,
|
|
12
|
+
:in!,
|
|
13
|
+
:assert_hash!
|
|
8
14
|
].each { |method_name| remove_method(method_name) }
|
|
9
15
|
|
|
10
|
-
def object_is_a(_kind, value, _label = nil) # :nodoc:
|
|
16
|
+
def object_is_a(_kind, value, _label = nil, _expected = nil) # :nodoc:
|
|
11
17
|
value
|
|
12
18
|
end
|
|
13
19
|
|
|
@@ -30,5 +36,17 @@ module Kind
|
|
|
30
36
|
def not_nil(value, label) # :nodoc:
|
|
31
37
|
value
|
|
32
38
|
end
|
|
39
|
+
|
|
40
|
+
def in!(list, value) # :nodoc:
|
|
41
|
+
value
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def assert_hash!(hash, _options) # :nodoc:
|
|
45
|
+
hash
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def assert_hash!(hash, _options) # :nodoc:
|
|
49
|
+
hash
|
|
50
|
+
end
|
|
33
51
|
end
|
|
34
52
|
end
|
data/lib/kind/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kind
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 5.
|
|
4
|
+
version: 5.9.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Rodrigo Serradura
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2021-
|
|
11
|
+
date: 2021-09-22 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: A development toolkit for Ruby with several small/cohesive abstractions
|
|
14
14
|
(monads, enums, business logic, data validation...) to empower your development
|
|
@@ -19,10 +19,10 @@ executables: []
|
|
|
19
19
|
extensions: []
|
|
20
20
|
extra_rdoc_files: []
|
|
21
21
|
files:
|
|
22
|
+
- ".github/workflows/ci.yml"
|
|
22
23
|
- ".gitignore"
|
|
23
24
|
- ".tool-versions"
|
|
24
|
-
- ".
|
|
25
|
-
- ".travis.yml"
|
|
25
|
+
- ".vscode/settings.json"
|
|
26
26
|
- CHANGELOG.md
|
|
27
27
|
- CODE_OF_CONDUCT.md
|
|
28
28
|
- Gemfile
|
|
@@ -30,10 +30,13 @@ files:
|
|
|
30
30
|
- README.md
|
|
31
31
|
- Rakefile
|
|
32
32
|
- bin/console
|
|
33
|
+
- bin/prepare_coverage
|
|
33
34
|
- bin/setup
|
|
35
|
+
- bin/test
|
|
34
36
|
- kind.gemspec
|
|
35
37
|
- lib/kind.rb
|
|
36
38
|
- lib/kind/__lib__/action_steps.rb
|
|
39
|
+
- lib/kind/__lib__/assert_hash.rb
|
|
37
40
|
- lib/kind/__lib__/attributes.rb
|
|
38
41
|
- lib/kind/__lib__/kind.rb
|
|
39
42
|
- lib/kind/__lib__/of.rb
|
|
@@ -41,6 +44,7 @@ files:
|
|
|
41
44
|
- lib/kind/__lib__/undefined.rb
|
|
42
45
|
- lib/kind/action.rb
|
|
43
46
|
- lib/kind/active_model/validation.rb
|
|
47
|
+
- lib/kind/any.rb
|
|
44
48
|
- lib/kind/basic.rb
|
|
45
49
|
- lib/kind/basic/error.rb
|
|
46
50
|
- lib/kind/basic/undefined.rb
|
|
@@ -119,14 +123,13 @@ files:
|
|
|
119
123
|
- lib/kind/try.rb
|
|
120
124
|
- lib/kind/validator.rb
|
|
121
125
|
- lib/kind/version.rb
|
|
122
|
-
- test.sh
|
|
123
126
|
homepage: https://github.com/serradura/kind
|
|
124
127
|
licenses:
|
|
125
128
|
- MIT
|
|
126
129
|
metadata:
|
|
127
130
|
homepage_uri: https://github.com/serradura/kind
|
|
128
131
|
source_code_uri: https://github.com/serradura/kind
|
|
129
|
-
post_install_message:
|
|
132
|
+
post_install_message:
|
|
130
133
|
rdoc_options: []
|
|
131
134
|
require_paths:
|
|
132
135
|
- lib
|
|
@@ -142,7 +145,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
142
145
|
version: '0'
|
|
143
146
|
requirements: []
|
|
144
147
|
rubygems_version: 3.2.11
|
|
145
|
-
signing_key:
|
|
148
|
+
signing_key:
|
|
146
149
|
specification_version: 4
|
|
147
150
|
summary: A development toolkit for Ruby with several small/cohesive abstractions to
|
|
148
151
|
empower your development workflow.
|
data/.travis.sh
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
|
|
3
|
-
RUBY_V=$(ruby -v)
|
|
4
|
-
|
|
5
|
-
function run_basic_tests {
|
|
6
|
-
if [ ! -z "$1" ]; then
|
|
7
|
-
bundle_cmd="bundle _$1_"
|
|
8
|
-
else
|
|
9
|
-
bundle_cmd="bundle"
|
|
10
|
-
fi
|
|
11
|
-
|
|
12
|
-
eval "KIND_BASIC=t $bundle_cmd exec rake test TEST='test/kind/{basic/*_test,basic_test}.rb'"
|
|
13
|
-
eval "KIND_BASIC=t $bundle_cmd exec rake test TEST='test/kind/enum_test.rb'"
|
|
14
|
-
eval "KIND_BASIC=t $bundle_cmd exec rake test TEST='test/kind/presence_test.rb'"
|
|
15
|
-
eval "KIND_BASIC=t $bundle_cmd exec rake test TEST='test/kind/dig_test.rb'"
|
|
16
|
-
eval "KIND_BASIC=t $bundle_cmd exec rake test TEST='test/kind/try_test.rb'"
|
|
17
|
-
eval "KIND_BASIC=t $bundle_cmd exec rake test TEST='test/kind/maybe_test.rb'"
|
|
18
|
-
eval "KIND_BASIC=t $bundle_cmd exec rake test TEST='test/kind/immutable_attributes_test.rb'"
|
|
19
|
-
eval "KIND_BASIC=t $bundle_cmd exec rake test TEST='test/kind/function_test.rb'"
|
|
20
|
-
eval "KIND_BASIC=t $bundle_cmd exec rake test TEST='test/kind/action_test.rb'"
|
|
21
|
-
eval "KIND_BASIC=t $bundle_cmd exec rake test TEST='test/kind/{functional/*_test,functional_test}.rb'"
|
|
22
|
-
eval "KIND_BASIC=t $bundle_cmd exec rake test TEST='test/kind/either/*_test.rb'"
|
|
23
|
-
eval "KIND_BASIC=t $bundle_cmd exec rake test TEST='test/kind/result/*_test.rb'"
|
|
24
|
-
|
|
25
|
-
eval "KIND_STRICT=t $bundle_cmd exec rake test TEST='test/kind/strict_disabled_test.rb'"
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function run_with_bundler {
|
|
29
|
-
rm Gemfile.lock
|
|
30
|
-
|
|
31
|
-
if [ ! -z "$1" ]; then
|
|
32
|
-
bundle_cmd="bundle _$1_"
|
|
33
|
-
else
|
|
34
|
-
bundle_cmd="bundle"
|
|
35
|
-
fi
|
|
36
|
-
|
|
37
|
-
eval "$2 $bundle_cmd update"
|
|
38
|
-
eval "$2 $bundle_cmd exec rake test"
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function run_with_am_version_and_bundler {
|
|
42
|
-
run_with_bundler "$2" "ACTIVEMODEL_VERSION=$1"
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
RUBY_2_12="ruby 2.[12]."
|
|
46
|
-
RUBY_2_2345="ruby 2.[2345]."
|
|
47
|
-
RUBY_2_12345="ruby 2.[12345]."
|
|
48
|
-
RUBY_2_567="ruby 2.[567]."
|
|
49
|
-
RUBY_3_0="ruby 3.0."
|
|
50
|
-
|
|
51
|
-
if [[ $RUBY_V =~ $RUBY_2_12 ]]; then
|
|
52
|
-
run_with_am_version_and_bundler "3.2" "$BUNDLER_V1"
|
|
53
|
-
fi
|
|
54
|
-
|
|
55
|
-
if [[ $RUBY_V =~ $RUBY_2_2345 ]]; then
|
|
56
|
-
run_with_am_version_and_bundler "4.0" "$BUNDLER_V1"
|
|
57
|
-
run_with_am_version_and_bundler "4.1" "$BUNDLER_V1"
|
|
58
|
-
run_with_am_version_and_bundler "4.2" "$BUNDLER_V1"
|
|
59
|
-
run_with_am_version_and_bundler "5.0" "$BUNDLER_V1"
|
|
60
|
-
run_with_am_version_and_bundler "5.1" "$BUNDLER_V1"
|
|
61
|
-
run_with_am_version_and_bundler "5.2" "$BUNDLER_V1"
|
|
62
|
-
fi
|
|
63
|
-
|
|
64
|
-
if [[ $RUBY_V =~ $RUBY_2_12345 ]]; then
|
|
65
|
-
run_basic_tests "$BUNDLER_V1"
|
|
66
|
-
run_with_bundler "$BUNDLER_V1"
|
|
67
|
-
fi
|
|
68
|
-
|
|
69
|
-
if [[ $RUBY_V =~ $RUBY_2_567 ]] || [[ $RUBY_V =~ $RUBY_3_0 ]]; then
|
|
70
|
-
gem install bundler -v ">= 2" --no-doc
|
|
71
|
-
|
|
72
|
-
run_with_am_version_and_bundler "6.0"
|
|
73
|
-
run_with_am_version_and_bundler "6.1"
|
|
74
|
-
|
|
75
|
-
run_basic_tests
|
|
76
|
-
run_with_bundler
|
|
77
|
-
fi
|
data/.travis.yml
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
language: ruby
|
|
3
|
-
|
|
4
|
-
cache:
|
|
5
|
-
bundler: true
|
|
6
|
-
directories:
|
|
7
|
-
- /home/travis/.rvm/
|
|
8
|
-
|
|
9
|
-
rvm:
|
|
10
|
-
- 2.1.10
|
|
11
|
-
- 2.2.2
|
|
12
|
-
- 2.3.0
|
|
13
|
-
- 2.4.0
|
|
14
|
-
- 2.5.0
|
|
15
|
-
- 2.6.0
|
|
16
|
-
- 2.7.0
|
|
17
|
-
- 3.0.0
|
|
18
|
-
|
|
19
|
-
env:
|
|
20
|
-
- BUNDLER_V1="1.17.3"
|
|
21
|
-
|
|
22
|
-
before_install:
|
|
23
|
-
- gem install bundler -v "$BUNDLER_V1"
|
|
24
|
-
|
|
25
|
-
install: bundle install --jobs=3 --retry=3
|
|
26
|
-
|
|
27
|
-
before_script:
|
|
28
|
-
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
|
|
29
|
-
- chmod +x ./cc-test-reporter
|
|
30
|
-
- "./cc-test-reporter before-build"
|
|
31
|
-
|
|
32
|
-
script: "./.travis.sh"
|
|
33
|
-
|
|
34
|
-
after_success:
|
|
35
|
-
- "./cc-test-reporter after-build -t simplecov"
|