sleeping_king_studios-tools 1.0.0 → 1.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: b185f72aa8d793ad425987881f1a1df9a37f2a4d2778775258ffb01ee2ec6d20
4
- data.tar.gz: bdd496ed87a5fc539bdf25b33f7e9af22bb1f25a6f086b3fb29aad356591fb6a
3
+ metadata.gz: 1e0283e289b39463cacc292d923861867d3692aa582c11ea52e093d4a669db47
4
+ data.tar.gz: 6974c66896e0f0a0b9b464326529e8d093f1842d5242a289d559b6508b08f3b6
5
5
  SHA512:
6
- metadata.gz: e9a2cb6b86a351b4932119e60ac3f0688753183e3c6ae07ca485b105a80b0c64f7f3b75b94984b22add91b8b8ad7c1d83b4e54e57099c8f4d11d2acb1e7a2202
7
- data.tar.gz: 4e4ae31ab84ee0ad8e85d2397ec7af1085c6d2a16932ad24ca15fdbd35936f094673012672b457eeac2d76c17849a9ea19eeccb9deef58a7e86821aff9603fe0
6
+ metadata.gz: 207672541e0507cdb35887ef670cc300157c204ddf937ca21a7c1b0243cdde20d212c7daf76f2cd2c70d734f8676ef2e6c646d30f9304933be1db36126c9d2cb
7
+ data.tar.gz: 5177a4f97ffd28c60b8249f9a4c8a6eafea08dd5c8fe7833273b4274e1fbb59d48e12bcda042a40d2e7d91afb850ed9e583aeeb8f728eea64feeb30c7c9da95a
data/CHANGELOG.md CHANGED
@@ -1,15 +1,50 @@
1
1
  # Changelog
2
2
 
3
- ### 1.0.0
3
+ ## 1.1.0
4
4
 
5
- - Removed all deprecated code from pre-1.0 releases.
5
+ Files in the `Toolbox` are now autoloaded.
6
6
 
7
- #### Toolbox
7
+ ### Tools
8
+
9
+ Implemented `SleepingKingStudios::Tools::Assertions` with the following methods:
10
+
11
+ - `#assert`
12
+ - `#assert_boolean`
13
+ - `#assert_class`
14
+ - `#assert_instance_of`
15
+ - `#assert_matches`
16
+ - `#assert_name`
17
+
18
+ Each method raises an exception if its condition is not met. `Assertions` also defines equivalent `#validate` methods, which always raise an `ArgumentError`.
19
+
20
+ Added :deprecation_caller_depth option to CoreTools. When calling #deprecate with the default strategy of 'warn', will print the specified number of lines from the caller. The default value is 3.
21
+
22
+ ### Toolbelt
23
+
24
+ - Added `#assertions` to Toolbelt.
25
+
26
+ ### Toolbox
27
+
28
+ Implemented `SleepingKingStudios::Tools::Toolbox::Subclass`, which implements partial application for constructor parameters.
29
+
30
+ ## 1.0.2
31
+
32
+ Updated gem metadata.
33
+
34
+ ## 1.0.1
35
+
36
+ Added a missing `require 'set'` to Toolbox::Inflector::Rules.
37
+
38
+ ## 1.0.0
39
+
40
+ Removed all deprecated code from pre-1.0 releases.
41
+
42
+ ### Toolbox
8
43
 
9
44
  Added some Hash-like methods to ConstantMap - `#each_key`, `#each_value`,
10
45
  `#keys`, `#to_h`, and `#values`.
11
46
 
12
- ### 0.8.0
47
+ ## 0.8.0
13
48
 
14
49
  Last minor release before 1.0.0.
15
50
 
@@ -20,14 +55,14 @@ in version 1.0.0. Update dependent code accordingly.
20
55
  functionality is still available as
21
56
  SleepingKingStudios::Tools::Toolbox::SemanticVersion.
22
57
 
23
- #### Tools
58
+ ### Tools
24
59
 
25
60
  - Refactored all Tools modules to classes.
26
61
  - Removed StringTools::PluralInflector. It's functionality is now handled by
27
62
  Toolbox::Inflector.
28
63
  - Added support for deprecation strategy to CoreTools#deprecate.
29
64
 
30
- #### Toolbelt
65
+ ### Toolbelt
31
66
 
32
67
  - Refactored Toolbelt to reference Tools instances rather than classes.
33
68
  - Defined new abbreviated helpers #ary, #hsh, #int, #obj, #str.
@@ -36,36 +71,36 @@ in version 1.0.0. Update dependent code accordingly.
36
71
  - Deprecated old abbreviated helpers #array, #core, #hash, #integer, #object,
37
72
  #string.
38
73
 
39
- #### Toolbox
74
+ ### Toolbox
40
75
 
41
76
  - Deprecate Toolbox::Configuration. Use a struct instead.
42
77
  - Deprecate Toolbox::Delegator. Use the stdlib Forwardable module instead.
43
78
  - Implement Toolbox::Inflector, which serves as a delegate for StringTools.
44
79
 
45
- ### 0.7.1
80
+ ## 0.7.1
46
81
 
47
82
  - Implement CoreTools#empty_binding.
48
83
  - Implement HashTools#generate_binding.
49
84
 
50
- ### 0.7.0
85
+ ## 0.7.0
51
86
 
52
- #### Tools
87
+ ### Tools
53
88
 
54
89
  - Support symbol arguments to StringTools methods.
55
90
  - Implement StringTools#chain.
56
91
  - Implement StringTools#indent.
57
92
  - Implement StringTools#map_lines.
58
93
 
59
- #### Toolbox
94
+ ### Toolbox
60
95
 
61
96
  - Implement Toolbox::Configuration.
62
97
 
63
- #### Misc.
98
+ ### Misc.
64
99
 
65
100
  - IntegerTools#pluralize now accepts 2..3 arguments, and will automatically generate the plural string using StringTools#pluralize if an explicit plural is not given.
66
101
  - SleepingKingStudios::Tools::Toolbelt is now autoloaded from SleepingKingStudios::Tools.
67
102
 
68
- ### 0.6.0
103
+ ## 0.6.0
69
104
 
70
105
  - Implement HashTools#convert_keys_to_strings and #convert_keys_to_symbols.
71
106
  - Implement ObjectTools#dig.
@@ -75,69 +110,67 @@ in version 1.0.0. Update dependent code accordingly.
75
110
  - Implement Toolbox::Mixin.
76
111
  - Add support for Ruby 2.4.0.
77
112
 
78
- ### 0.5.0
113
+ ## 0.5.0
79
114
 
80
115
  - Implement CoreTools#require_each.
81
116
  - Implement StringTools#camelize.
82
117
  - Add an optional block argument to ArrayTools#humanize_list.
83
118
 
84
- #### Toolbox
119
+ ### Toolbox
85
120
 
86
121
  - Implement Delegator#delegate, Delegator#wrap_delegate.
87
122
  - Refactor SemanticVersion to the Toolbox namespace. Accessing SemanticVersion as Tools::SemanticVersion is now deprecated, use Tools::Toolbox::SemanticVersion.
88
123
 
89
- #### Identity Methods
124
+ ### Identity Methods
90
125
 
91
126
  - Implement a set of methods to classify objects by type: ArrayTools#array?, HashTools#hash?, IntegerTools#integer?, ObjectTools#object?, and StringTools#string?.
92
127
 
93
- #### Mutability Methods
128
+ ### Mutability Methods
94
129
 
95
130
  Implement #immutable? and #mutable? for ObjectTools, ArrayTools, and HashTools, which indicate whether or not a given object is mutable.
96
131
 
97
132
  Implement #deep_freeze for ObjectTools, ArrayTools, and HashTools which recursively freezes the object and any children (array items, hash keys, and hash values).
98
133
 
99
- ## Previous Releases
100
-
101
- ### 0.4.0
134
+ ## 0.4.0
102
135
 
103
- #### CoreTools
136
+ ### CoreTools
104
137
 
105
138
  Implement CoreTools#deprecate.
106
139
 
107
- #### IntegerTools
140
+ ### IntegerTools
108
141
 
109
142
  Implement #pluralize.
110
143
 
111
- #### StringTools
144
+ ### StringTools
112
145
 
113
146
  Implement #pluralize and #singularize. The previous behavior of #pluralize is deprecated; use IntegerTools#pluralize.
114
147
 
115
- ### 0.3.0
148
+ ## 0.3.0
116
149
 
117
150
  Implement ArrayTools#bisect and ArrayTools#splice.
118
151
 
119
- #### StringTools
152
+ ### StringTools
120
153
 
121
154
  Implement #underscore.
122
155
 
123
- ### 0.2.0
156
+ ## 0.2.0
124
157
 
125
158
  Split EnumerableTools into ArrayTools and HashTools.
126
159
 
127
160
  Implement ArrayTools#deep_dup, HashTools#deep_dup and ObjectTools#deep_dup.
128
161
 
129
- ### 0.1.3
162
+ ## 0.1.3
130
163
 
131
164
  Properly support both keywords and optional arguments in ObjectTools#apply.
132
165
 
133
- ### 0.1.2
166
+ ## 0.1.2
134
167
 
135
168
  Fix loading order issues when loading SemanticVersion in isolation.
136
169
 
137
- ### 0.1.1
170
+ ## 0.1.1
138
171
 
139
172
  Add configuration options to EnumerableTools#humanize_list.
140
173
 
141
- ### 0.1.0
174
+ ## 0.1.0
142
175
 
143
176
  Initial release.
data/README.md CHANGED
@@ -4,7 +4,7 @@ A library of utility services and concerns to expand the functionality of core c
4
4
 
5
5
  ## About
6
6
 
7
- SleepingKingStudios::Tools is tested against MRI Ruby 2.5 through 3.0.
7
+ SleepingKingStudios::Tools is tested against MRI Ruby 2.6 through 3.1.
8
8
 
9
9
  ### Documentation
10
10
 
@@ -30,18 +30,20 @@ Please note that the `SleepingKingStudios::Tools` project is released with a [Co
30
30
 
31
31
  The tools can be accessed in a convenient form using the Toolbelt class.
32
32
 
33
- require 'sleeping_king_studios/tools'
33
+ ```ruby
34
+ require 'sleeping_king_studios/tools'
34
35
 
35
- tools = ::SleepingKingStudios::Tools::Toolbelt.instance
36
+ tools = ::SleepingKingStudios::Tools::Toolbelt.instance
36
37
 
37
- tools.array.humanize_list 'one', 'two', 'three'
38
- #=> calls ArrayTools#humanize_list
38
+ tools.ary.humanize_list 'one', 'two', 'three'
39
+ #=> calls ArrayTools#humanize_list
39
40
 
40
- tools.core.deprecate 'my_method'
41
- #=> calls CoreTools#deprecate
41
+ tools.core.deprecate 'my_method'
42
+ #=> calls CoreTools#deprecate
42
43
 
43
- tools.string.underscore 'MyModuleName'
44
- #=> calls StringTools#underscore
44
+ tools.str.underscore 'MyModuleName'
45
+ #=> calls StringTools#underscore
46
+ ```
45
47
 
46
48
  ### Array Tools
47
49
 
@@ -181,6 +183,256 @@ Accepts an array, a start value, a number of items to delete, and zero or more i
181
183
  values
182
184
  #=> ['shortbow', 'longbow', 'arbalest', 'chu-ko-nu']
183
185
 
186
+ ### Assertions
187
+
188
+ Tools for validating the current application state.
189
+
190
+ #### `#assert`
191
+
192
+ Raises an exception unless the given block returns a truthy value.
193
+
194
+ ```ruby
195
+ Assertions.assert { true == false }
196
+ #=> raises an AssertionError with message 'block returned a falsy value'
197
+
198
+ Assertions.assert { true == true }
199
+ #=> does not raise an exception
200
+ ```
201
+
202
+ It accepts the following options:
203
+
204
+ - `error_class:` The class of exception to raise. Defaults to `SleepingKingStudios::Tools::Assertions::AssertionError`.
205
+ - `message`: The error message to display.
206
+
207
+ #### `#assert_boolean`
208
+
209
+ Raises an exception unless the given value is either `true` or `false`.
210
+
211
+ ```ruby
212
+ Assertions.assert_boolean(nil)
213
+ #=> raises an AssertionError with message 'value must be true or false'
214
+
215
+ Assertions.assert_boolean(Object.new)
216
+ #=> raises an AssertionError with message 'value must be true or false'
217
+
218
+ Assertions.assert_boolean(false)
219
+ #=> does not raise an exception
220
+
221
+ Assertions.assert_boolean(true)
222
+ #=> does not raise an exception
223
+ ```
224
+
225
+ It accepts the following options:
226
+
227
+ - `as:` A short descriptor of the given value. Defaults to `"value"`.
228
+ - `error_class:` The class of exception to raise. Defaults to `SleepingKingStudios::Tools::Assertions::AssertionError`.
229
+ - `message`: The error message to display.
230
+
231
+ #### `#assert_class`
232
+
233
+ Raises an exception unless the given value is a Class.
234
+
235
+ ```ruby
236
+ Assertions.assert_class(Object.new)
237
+ #=> raises an AssertionError with message 'value is not a class'
238
+
239
+ Assertions.assert_class(String)
240
+ #=> does not raise an exception
241
+ ```
242
+
243
+ It accepts the following options:
244
+
245
+ - `as:` A short descriptor of the given value. Defaults to `"value"`.
246
+ - `error_class:` The class of exception to raise. Defaults to `SleepingKingStudios::Tools::Assertions::AssertionError`.
247
+ - `message`: The error message to display.
248
+
249
+ #### `#assert_instance_of`
250
+
251
+ Raises an exception unless the given value is an instance of the expected Class or Module.
252
+
253
+ ```ruby
254
+ Assertions.assert_instance_of(:foo, expected: String)
255
+ #=> raises an AssertionError with message 'value is not an instance of String'
256
+
257
+ Assertions.assert_instance_of('foo', expected: String)
258
+ #=> does not raise an exception
259
+ ```
260
+
261
+ It accepts the following options:
262
+
263
+ - `as:` A short descriptor of the given value. Defaults to `"value"`.
264
+ - `error_class:` The class of exception to raise. Defaults to `SleepingKingStudios::Tools::Assertions::AssertionError`.
265
+ - `message`: The error message to display.
266
+ - `optional`: If true, accepts `nil` values as well as instances of the Class or Module.
267
+
268
+ #### `#assert_matches`
269
+
270
+ Raises an exception unless the given value matches the expected value using case equality (`#===`).
271
+
272
+
273
+ ```ruby
274
+ Assertions.assert_matches('bar', expected: /foo/)
275
+ #=> raises an AssertionError with message 'value does not match the pattern /foo/'
276
+
277
+ Assertions.assert_matches('foo', expected: /foo/)
278
+ #=> does not raise an exception
279
+ ```
280
+
281
+ It accepts the following options:
282
+
283
+ - `as:` A short descriptor of the given value. Defaults to `"value"`.
284
+ - `error_class:` The class of exception to raise. Defaults to `SleepingKingStudios::Tools::Assertions::AssertionError`.
285
+ - `message`: The error message to display.
286
+ - `optional`: If true, accepts `nil` values as well as matching values.
287
+
288
+ #### `#assert_name`
289
+
290
+ Raises an exception unless the given value is non-empty a String or Symbol.
291
+
292
+ ```ruby
293
+ Assertions.assert_name(nil)
294
+ #=> raises an AssertionError with message "value can't be blank"
295
+
296
+ Assertions.assert_name(Object.new)
297
+ #=> raises an AssertionError with message 'value is not a String or a Symbol'
298
+
299
+ Assertions.assert_name('')
300
+ #=> raises an AssertionError with message "value can't be blank"
301
+
302
+ Assertions.assert_name('foo')
303
+ #=> does not raise an exception
304
+
305
+ Assertions.assert_name(:bar)
306
+ #=> does not raise an exception
307
+ ```
308
+
309
+ It accepts the following options:
310
+
311
+ - `as:` A short descriptor of the given value. Defaults to `"value"`.
312
+ - `error_class:` The class of exception to raise. Defaults to `SleepingKingStudios::Tools::Assertions::AssertionError`.
313
+ - `message`: The error message to display.
314
+ - `optional`: If true, accepts `nil` values as well as valid Symbols and Strings.
315
+
316
+ #### `#validate`
317
+
318
+ Raises an `ArgumentError` unless the given block returns a truthy value.
319
+
320
+ ```ruby
321
+ Assertions.validate { true == false }
322
+ #=> raises an ArgumentError with message 'block returned a falsy value'
323
+
324
+ Assertions.validate { true == true }
325
+ #=> does not raise an exception
326
+ ```
327
+
328
+ It accepts the following options:
329
+
330
+ - `message`: The error message to display.
331
+
332
+ #### `#validate_boolean`
333
+
334
+ Raises an exception unless the given value is either `true` or `false`.
335
+
336
+ ```ruby
337
+ Assertions.validate_boolean(nil)
338
+ #=> raises an ArgumentError with message 'value must be true or false'
339
+
340
+ Assertions.validate_boolean(Object.new)
341
+ #=> raises an ArgumentError with message 'value must be true or false'
342
+
343
+ Assertions.validate_boolean(false)
344
+ #=> does not raise an exception
345
+
346
+ Assertions.validate_boolean(true)
347
+ #=> does not raise an exception
348
+ ```
349
+
350
+ It accepts the following options:
351
+
352
+ - `as:` A short descriptor of the given value. Defaults to `"value"`.
353
+ - `message`: The error message to display.
354
+
355
+ #### `#validate_class`
356
+
357
+ Raises an `ArgumentError` unless the given value is a Class.
358
+
359
+ ```ruby
360
+ Assertions.validate_class(Object.new)
361
+ #=> raises an ArgumentError with message 'value is not a class'
362
+
363
+ Assertions.validate_class(String)
364
+ #=> does not raise an exception
365
+ ```
366
+
367
+ It accepts the following options:
368
+
369
+ - `as:` A short descriptor of the given value. Defaults to `"value"`.
370
+ - `message`: The error message to display.
371
+
372
+ #### `#validate_instance_of`
373
+
374
+ Raises an `ArgumentError` unless the given value is an instance of the expected Class or Module.
375
+
376
+ ```ruby
377
+ Assertions.validate_instance_of(:foo, expected: String)
378
+ #=> raises an AssertionError with message 'value is not an instance of String'
379
+
380
+ Assertions.validate_instance_of('foo', expected: String)
381
+ #=> does not raise an exception
382
+ ```
383
+
384
+ It accepts the following options:
385
+
386
+ - `as:` A short descriptor of the given value. Defaults to `"value"`.
387
+ - `message`: The error message to display.
388
+ - `optional`: If true, accepts `nil` values as well as instances of the Class or Module.
389
+
390
+ #### `#validate_matches`
391
+
392
+ Raises an `ArgumentError` unless the given value matches the expected value using case equality (`#===`).
393
+
394
+
395
+ ```ruby
396
+ Assertions.validate_matches('bar', expected: /foo/)
397
+ #=> raises an ArgumentError with message 'value does not match the pattern /foo/'
398
+
399
+ Assertions.validate_matches('foo', expected: /foo/)
400
+ #=> does not raise an exception
401
+ ```
402
+
403
+ It accepts the following options:
404
+
405
+ - `as:` A short descriptor of the given value. Defaults to `"value"`.
406
+ - `message`: The error message to display.
407
+ - `optional`: If true, accepts `nil` values as well as matching values.
408
+
409
+ #### `#validate_name`
410
+
411
+ Raises an `ArgumentError` unless the given value is non-empty a String or Symbol.
412
+
413
+ ```ruby
414
+ Assertions.validate_name(nil)
415
+ #=> raises an ArgumentError with message "value can't be blank"
416
+
417
+ Assertions.validate_name(Object.new)
418
+ #=> raises an AssertionError with message 'value is not a String or a Symbol'
419
+
420
+ Assertions.validate_name('')
421
+ #=> raises an ArgumentError with message "value can't be blank"
422
+
423
+ Assertions.validate_name('foo')
424
+ #=> does not raise an exception
425
+
426
+ Assertions.validate_name(:bar)
427
+ #=> does not raise an exception
428
+ ```
429
+
430
+ It accepts the following options:
431
+
432
+ - `as:` A short descriptor of the given value. Defaults to `"value"`.
433
+ - `message`: The error message to display.
434
+ - `optional`: If true, accepts `nil` values as well as valid Symbols and Strings.
435
+
184
436
  ### Core Tools
185
437
 
186
438
  Tools for working with an application or working environment.
@@ -189,17 +441,40 @@ Tools for working with an application or working environment.
189
441
 
190
442
  Prints a deprecation warning.
191
443
 
192
- CoreTools.deprecate 'ObjectTools#old_method'
193
- #=> prints to stderr:
194
-
195
- [WARNING] ObjectTools#old_method is deprecated.
196
- called from /path/to/file.rb:4: in something_or_other
197
-
198
- CoreTools.deprecate 'ObjectTools#old_method', '0.1.0', :format => '%s was deprecated in version %s.'
199
- #=> prints to stderr:
200
-
201
- ObjectTools#old_method was deprecated in version 0.1.0.
202
- called from /path/to/file.rb:4: in something_or_other
444
+ ```ruby
445
+ CoreTools.deprecate 'ObjectTools#old_method'
446
+ #=> prints to stderr:
447
+ #
448
+ # [WARNING] ObjectTools#old_method is deprecated.
449
+ # called from /path/to/file.rb:4: in something_or_other
450
+ ```
451
+
452
+ You can also specify an additional message to display:
453
+
454
+ ```ruby
455
+ CoreTools.deprecate 'ObjectTools#old_method',
456
+ 'Use #new_method instead.'
457
+ #=> prints to stderr:
458
+ #
459
+ # [WARNING] ObjectTools#old_method is deprecated. Use #new_method instead.
460
+ # called from /path/to/file.rb:4: in something_or_other
461
+ ```
462
+
463
+ You can specify a custom format for the deprecation message:
464
+
465
+ ```ruby
466
+ CoreTools.deprecate 'ObjectTools#old_method',
467
+ '0.1.0',
468
+ format: '%s was deprecated in version %s.'
469
+ #=> prints to stderr:
470
+ #
471
+ # ObjectTools#old_method was deprecated in version 0.1.0.
472
+ # called from /path/to/file.rb:4: in something_or_other
473
+ ```
474
+
475
+ By default, `#deprecate` will print the last 3 lines of the caller, excluding
476
+ any lines from `Forwardable` and from `SleepingKingStudios::Tools` itself. To
477
+ print a different number of lines, pass a custom `deprecation_caller_depth` parameter to `CoreTools.new` or set the `DEPRECATION_CALLER_DEPTH` environment variable.
203
478
 
204
479
  #### `#empty_binding`
205
480
 
@@ -825,3 +1100,102 @@ Concatenates the MAJOR, MINOR, and PATCH constant values with PRERELEASE and BUI
825
1100
  #### `#to_version`
826
1101
 
827
1102
  Concatenates the MAJOR, MINOR, and PATCH constant values with PRERELEASE and BUILD (if available) to generate a semantic version string. The major, minor, and patch values are separated by dots `.`, then the prerelease (if available) preceded by a hyphen `-`, and the build (if available) preceded by a plus sign `+`.
1103
+
1104
+ ### Subclass
1105
+
1106
+ ```ruby
1107
+ require 'sleeping_king_studios/tools/toolbox/subclass'
1108
+ ```
1109
+
1110
+ The `Subclass` module provides a mechanism for performing partial application (or "currying") of constructor parameters. This is useful for defining subclasses that inject pre-defined values into the constructor.
1111
+
1112
+ Let's consider an example. We'll start by defining a base class.
1113
+
1114
+ ```ruby
1115
+ class Query
1116
+ extend SleepingKingStudios::Tools::Toolbox::Subclass
1117
+
1118
+ def initialize(entity_class, **options)
1119
+ @entity_class = entity_class
1120
+ @options = options
1121
+ end
1122
+
1123
+ attr_reader :entity_class
1124
+
1125
+ attr_reader :options
1126
+
1127
+ def call
1128
+ # Querying logic here.
1129
+ end
1130
+ end
1131
+
1132
+ query = Query.new(Book, limit: 10)
1133
+ query.entity_class
1134
+ #=> Book
1135
+ query.options
1136
+ #=> { limit: 10 }
1137
+ ```
1138
+
1139
+ Our `Query` class is used to perform queries on some data source - a relational table, an API, or some in-memory data structure. To perform a query, we need to know what data to request. This is represented by the `:entity_class` argument. Additionally, we can pass arbitrary `:options` as keywords.
1140
+
1141
+ ```ruby
1142
+ BooksQuery = Query.subclass(Book)
1143
+
1144
+ query = BooksQuery.new(order: :title)
1145
+ query.entity_class
1146
+ #=> Book
1147
+ query.options
1148
+ #=> { order: :title }
1149
+ ```
1150
+
1151
+ By calling `.subclass` on our `Query` class, we are defining a new subclass of `Query` that injects the given parameters and partially applies them to the constructor. In this case, we are injecting the `Book` class into our query.
1152
+
1153
+ We can also use `.subclass` to partially apply keywords or a block.
1154
+
1155
+ ```ruby
1156
+ RecentItemsQuery = Query.subclass(order: { created_at: :desc })
1157
+
1158
+ query = RecentItemsQuery.new(Book)
1159
+ query.entity_class
1160
+ #=> Book
1161
+ query.options
1162
+ #=> { order: { created_at: :desc } }
1163
+ ```
1164
+
1165
+ When you call the subclass's constructor with additional parameters, they are applied in addition to the configured values (if any).
1166
+
1167
+ - Any arguments passed to `.new` are added *after* the configured arguments.
1168
+ - Any keywords passed to `.new` are merged into the configured keywords, with the values passed to `.new` taking precedence.
1169
+ - A block passed to `.new` will take precedence over a configured block.
1170
+
1171
+ ```ruby
1172
+ class Character
1173
+ extend SleepingKingStudios::Tools::Toolbox::Subclass
1174
+
1175
+ def initialize(*traits, **stats, &special)
1176
+ @traits = traits
1177
+ @stats = stats
1178
+ @special = special
1179
+ end
1180
+
1181
+ attr_reader :special
1182
+
1183
+ attr_reader :stats
1184
+
1185
+ attr_reader :traits
1186
+ end
1187
+
1188
+ Bard = Character.subclass(:musical, performance: 5, persuasion: 10) do
1189
+ 'The bard sings a cheerful tune.'
1190
+ end
1191
+
1192
+ aoife = Bard.new(:sorcerous, magic: 5, performance: 10) do
1193
+ 'Aoife drops her lute!'
1194
+ end
1195
+ aoife.traits
1196
+ #=> [:musical, :sorcerous]
1197
+ aoife.stats
1198
+ #=> { magic: 5, performance: 10, persuasion: 10 }
1199
+ aoife.special.call
1200
+ #=> 'Aoife drops her lute!'
1201
+ ```
@@ -302,7 +302,7 @@ module SleepingKingStudios::Tools
302
302
  def require_array!(value)
303
303
  return if array?(value)
304
304
 
305
- raise ArgumentError, 'argument must be an array', caller[1..-1]
305
+ raise ArgumentError, 'argument must be an array', caller[1..]
306
306
  end
307
307
  end
308
308
  end
@@ -0,0 +1,322 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sleeping_king_studios/tools'
4
+
5
+ module SleepingKingStudios::Tools
6
+ # Methods for asserting on the state of a function or application.
7
+ class Assertions < Base # rubocop:disable Metrics/ClassLength
8
+ # Error class for handling a failed assertion.
9
+ class AssertionError < StandardError; end
10
+
11
+ # Asserts that the block returns a truthy value.
12
+ #
13
+ # @param error_class [Class] The exception class to raise on a failure.
14
+ # @param message [String] The exception message to raise on a failure.
15
+ #
16
+ # @yield The block to evaluate.
17
+ # @yieldreturn [Object] The returned value of the block.
18
+ #
19
+ # @raise AssertionError if the block does not return a truthy value.
20
+ def assert(error_class: AssertionError, message: nil, &block)
21
+ return if block.call
22
+
23
+ raise error_class,
24
+ message || 'block returned a falsy value',
25
+ caller(1..-1)
26
+ end
27
+
28
+ # Asserts that the value is either true or false.
29
+ #
30
+ # @param value [Object] The value to assert on.
31
+ # @param as [String] The name of the asserted value.
32
+ # @param error_class [Class] The exception class to raise on a failure.
33
+ # @param message [String] The exception message to raise on a failure.
34
+ #
35
+ # @raise AssertionError if the value is not a Class.
36
+ def assert_boolean(
37
+ value,
38
+ as: 'value',
39
+ error_class: AssertionError,
40
+ message: nil
41
+ )
42
+ return if value.equal?(true) || value.equal?(false)
43
+
44
+ raise error_class,
45
+ message || "#{as} must be true or false",
46
+ caller(1..-1)
47
+ end
48
+
49
+ # Asserts that the value is a Class.
50
+ #
51
+ # @param value [Object] The value to assert on.
52
+ # @param as [String] The name of the asserted value.
53
+ # @param error_class [Class] The exception class to raise on a failure.
54
+ # @param message [String] The exception message to raise on a failure.
55
+ #
56
+ # @raise AssertionError if the value is not a Class.
57
+ def assert_class(
58
+ value,
59
+ as: 'value',
60
+ error_class: AssertionError,
61
+ message: nil
62
+ )
63
+ return if value.is_a?(Class)
64
+
65
+ raise error_class,
66
+ message || "#{as} is not a Class",
67
+ caller(1..-1)
68
+ end
69
+
70
+ # Asserts that the value is an example of the given Class.
71
+ #
72
+ # @param value [Object] The value to assert on.
73
+ # @param as [String] The name of the asserted value.
74
+ # @param error_class [Class] The exception class to raise on a failure.
75
+ # @param expected [Class] The expected class.
76
+ # @param message [String] The exception message to raise on a failure.
77
+ # @param optional [true, false] If true, allows nil values.
78
+ #
79
+ # @raise ArgumentError if the expected class is not a Class.
80
+ # @raise AssertionError if the value is not an instance of the expected
81
+ # class.
82
+ def assert_instance_of( # rubocop:disable Metrics/ParameterLists
83
+ value,
84
+ expected:,
85
+ as: 'value',
86
+ error_class: AssertionError,
87
+ message: nil,
88
+ optional: false
89
+ )
90
+ unless expected.is_a?(Class)
91
+ raise ArgumentError, 'expected must be a Class'
92
+ end
93
+
94
+ return if optional && value.nil?
95
+ return if value.is_a?(expected)
96
+
97
+ raise error_class,
98
+ message || "#{as} is not an instance of #{class_name(expected)}",
99
+ caller(1..-1)
100
+ end
101
+
102
+ # Asserts that the value matches the expected object using #===.
103
+ #
104
+ # @param value [Object] The value to assert on.
105
+ # @param as [String] The name of the asserted value.
106
+ # @param error_class [Class] The exception class to raise on a failure.
107
+ # @param expected [#===] The expected object.
108
+ # @param message [String] The exception message to raise on a failure.
109
+ # @param optional [true, false] If true, allows nil values.
110
+ #
111
+ # @raise AssertionError if the value does not match the expected object.
112
+ def assert_matches( # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/ParameterLists
113
+ value,
114
+ expected:,
115
+ as: 'value',
116
+ error_class: AssertionError,
117
+ message: nil,
118
+ optional: false
119
+ )
120
+ return if optional && value.nil?
121
+ return if expected === value # rubocop:disable Style/CaseEquality
122
+
123
+ message ||=
124
+ case expected
125
+ when Module
126
+ "#{as} is not an instance of #{class_name(expected)}"
127
+ when Proc
128
+ "#{as} does not match the Proc"
129
+ when Regexp
130
+ "#{as} does not match the pattern #{expected.inspect}"
131
+ else
132
+ "#{as} does not match the expected value"
133
+ end
134
+
135
+ raise error_class, message, caller(1..-1)
136
+ end
137
+
138
+ # Asserts that the value is a non-empty String or Symbol.
139
+ #
140
+ # @param value [Object] The value to assert on.
141
+ # @param as [String] The name of the asserted value.
142
+ # @param error_class [Class] The exception class to raise on a failure.
143
+ # @param message [String] The exception message to raise on a failure.
144
+ # @param optional [true, false] If true, allows nil values.
145
+ #
146
+ # @raise AssertionError if the value is not a String or a Symbol, or if the
147
+ # value is empty.
148
+ def assert_name( # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
149
+ value,
150
+ as: 'value',
151
+ error_class: AssertionError,
152
+ message: nil,
153
+ optional: false
154
+ )
155
+ if value.nil?
156
+ return if optional
157
+
158
+ raise error_class, message || "#{as} can't be blank", caller(1..-1)
159
+ end
160
+
161
+ unless value.is_a?(String) || value.is_a?(Symbol)
162
+ raise error_class,
163
+ message || "#{as} is not a String or a Symbol",
164
+ caller(1..-1)
165
+ end
166
+
167
+ return unless value.empty?
168
+
169
+ raise error_class, message || "#{as} can't be blank", caller(1..-1)
170
+ end
171
+
172
+ # Asserts that the block returns a truthy value.
173
+ #
174
+ # @param message [String] The exception message to raise on a failure.
175
+ #
176
+ # @yield The block to evaluate.
177
+ # @yieldreturn [Object] The returned value of the block.
178
+ #
179
+ # @raise ArgumentError if the block does not return a truthy value.
180
+ def validate(message: nil, &block)
181
+ return if block.call
182
+
183
+ raise ArgumentError,
184
+ message || 'block returned a falsy value',
185
+ caller(1..-1)
186
+ end
187
+
188
+ # Asserts that the value is either true or false.
189
+ #
190
+ # @param value [Object] The value to assert on.
191
+ # @param as [String] The name of the asserted value.
192
+ # @param message [String] The exception message to raise on a failure.
193
+ #
194
+ # @raise AssertionError if the value is not a Class.
195
+ def validate_boolean(value, as: 'value', message: nil)
196
+ return if value.equal?(true) || value.equal?(false)
197
+
198
+ raise ArgumentError,
199
+ message || "#{as} must be true or false",
200
+ caller(1..-1)
201
+ end
202
+
203
+ # Asserts that the value is a Class.
204
+ #
205
+ # @param value [Object] The value to assert on.
206
+ # @param as [String] The name of the asserted value.
207
+ # @param message [String] The exception message to raise on a failure.
208
+ #
209
+ # @raise ArgumentError if the value is not a Class.
210
+ def validate_class(value, as: 'value', message: nil)
211
+ return if value.is_a?(Class)
212
+
213
+ raise ArgumentError,
214
+ message || "#{as} is not a Class",
215
+ caller(1..-1)
216
+ end
217
+
218
+ # Asserts that the value is an example of the given Class.
219
+ #
220
+ # @param value [Object] The value to assert on.
221
+ # @param as [String] The name of the asserted value.
222
+ # @param expected [Class] The expected class.
223
+ # @param message [String] The exception message to raise on a failure.
224
+ # @param optional [true, false] If true, allows nil values.
225
+ #
226
+ # @raise ArgumentError if the expected class is not a Class.
227
+ # @raise AssertionError if the value is not an instance of the expected
228
+ # class.
229
+ def validate_instance_of(
230
+ value,
231
+ expected:,
232
+ as: 'value',
233
+ message: nil,
234
+ optional: false
235
+ )
236
+ unless expected.is_a?(Class)
237
+ raise ArgumentError, 'expected must be a Class'
238
+ end
239
+
240
+ return if optional && value.nil?
241
+ return if value.is_a?(expected)
242
+
243
+ raise ArgumentError,
244
+ message || "#{as} is not an instance of #{class_name(expected)}",
245
+ caller(1..-1)
246
+ end
247
+
248
+ # Asserts that the value matches the expected object using #===.
249
+ #
250
+ # @param value [Object] The value to assert on.
251
+ # @param as [String] The name of the asserted value.
252
+ # @param expected [#===] The expected object.
253
+ # @param message [String] The exception message to raise on a failure.
254
+ # @param optional [true, false] If true, allows nil values.
255
+ #
256
+ # @raise ArgumentError if the value does not match the expected object.
257
+ def validate_matches( # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength
258
+ value,
259
+ expected:,
260
+ as: 'value',
261
+ message: nil,
262
+ optional: false
263
+ )
264
+ return if optional && value.nil?
265
+ return if expected === value # rubocop:disable Style/CaseEquality
266
+
267
+ message ||=
268
+ case expected
269
+ when Module
270
+ "#{as} is not an instance of #{class_name(expected)}"
271
+ when Proc
272
+ "#{as} does not match the Proc"
273
+ when Regexp
274
+ "#{as} does not match the pattern #{expected.inspect}"
275
+ else
276
+ "#{as} does not match the expected value"
277
+ end
278
+
279
+ raise ArgumentError, message, caller(1..-1)
280
+ end
281
+
282
+ # Asserts that the value is a non-empty String or Symbol.
283
+ #
284
+ # @param value [Object] The value to assert on.
285
+ # @param as [String] The name of the asserted value.
286
+ # @param message [String] The exception message to raise on a failure.
287
+ # @param optional [true, false] If true, allows nil values.
288
+ #
289
+ # @raise ArgumentError if the value is not a String or a Symbol, or if the
290
+ # value is empty.
291
+ def validate_name( # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
292
+ value,
293
+ as: 'value',
294
+ message: nil,
295
+ optional: false
296
+ )
297
+ if value.nil?
298
+ return if optional
299
+
300
+ raise ArgumentError, message || "#{as} can't be blank", caller(1..-1)
301
+ end
302
+
303
+ unless value.is_a?(String) || value.is_a?(Symbol)
304
+ raise ArgumentError,
305
+ message || "#{as} is not a String or a Symbol",
306
+ caller(1..-1)
307
+ end
308
+
309
+ return unless value.empty?
310
+
311
+ raise ArgumentError, message || "#{as} can't be blank", caller(1..-1)
312
+ end
313
+
314
+ private
315
+
316
+ def class_name(expected)
317
+ return expected.name if expected.name
318
+
319
+ "#{expected.inspect} (#{expected.ancestors.find(&:name).name})"
320
+ end
321
+ end
322
+ end
@@ -16,16 +16,28 @@ module SleepingKingStudios::Tools
16
16
  :require_each
17
17
  end
18
18
 
19
+ # @param deprecation_caller_depth [Integer] The number of backtrace lines to
20
+ # display when outputting a deprecation warning.
19
21
  # @param deprecation_strategy [String] The name of the strategy used when
20
22
  # deprecated code is called. Must be 'ignore', 'raise', or 'warn'.
21
- def initialize(deprecation_strategy: nil)
23
+ def initialize(
24
+ deprecation_caller_depth: nil,
25
+ deprecation_strategy: nil
26
+ )
22
27
  super()
23
28
 
29
+ @deprecation_caller_depth =
30
+ deprecation_caller_depth ||
31
+ ENV.fetch('DEPRECATION_CALLER_DEPTH', '3').to_i
24
32
  @deprecation_strategy =
25
33
  deprecation_strategy || ENV.fetch('DEPRECATION_STRATEGY', 'warn')
26
34
  end
27
35
 
28
- # @return [String] The current deprecation strategy.
36
+ # @return [Integer] the number of backtrace lines to display when outputting
37
+ # a deprecation warning.
38
+ attr_reader :deprecation_caller_depth
39
+
40
+ # @return [String] the current deprecation strategy.
29
41
  attr_reader :deprecation_strategy
30
42
 
31
43
  # @overload deprecate(name, message: nil)
@@ -92,19 +104,21 @@ module SleepingKingStudios::Tools
92
104
 
93
105
  str = format % args
94
106
  str << ' ' << message if message
95
-
96
- str << "\n called from #{external_caller}"
107
+ str << format_caller
97
108
 
98
109
  Kernel.warn str
99
110
  end
100
111
 
101
- def external_caller
102
- caller.find do |line|
103
- !(
104
- line.include?('forwardable.rb') ||
105
- line.include?('sleeping_king_studios-tools')
106
- )
112
+ def format_caller
113
+ lines = caller
114
+ start = lines.find_index do |line|
115
+ !line.include?('forwardable.rb') &&
116
+ !line.include?('sleeping_king_studios-tools')
107
117
  end
118
+
119
+ lines[start...(start + deprecation_caller_depth)]
120
+ .map { |line| "\n called from #{line}" }
121
+ .join
108
122
  end
109
123
  end
110
124
  end
@@ -168,7 +168,7 @@ module SleepingKingStudios::Tools
168
168
  def require_hash!(value)
169
169
  return if hash?(value)
170
170
 
171
- raise ArgumentError, 'argument must be a hash', caller[1..-1]
171
+ raise ArgumentError, 'argument must be a hash', caller[1..]
172
172
  end
173
173
  end
174
174
  end
@@ -108,7 +108,7 @@ module SleepingKingStudios::Tools
108
108
  # @return [Array<String>] The digits of the decomposed integer,
109
109
  # represented as a bigendian array of strings.
110
110
  def digits(integer, base: 10)
111
- integer.to_s(base).split('')
111
+ integer.to_s(base).chars
112
112
  end
113
113
 
114
114
  # Returns true if the object is an Integer.
@@ -177,8 +177,8 @@ module SleepingKingStudios::Tools
177
177
  return if (ROMANIZE_MIN..ROMANIZE_MAX).include?(integer)
178
178
 
179
179
  error_message =
180
- "integer to romanize must be within range #{ROMANIZE_MIN} to" \
181
- " #{ROMANIZE_MAX}"
180
+ "integer to romanize must be within range #{ROMANIZE_MIN} to " \
181
+ "#{ROMANIZE_MAX}"
182
182
 
183
183
  raise RangeError, error_message, caller(1..-1)
184
184
  end
@@ -167,7 +167,7 @@ module SleepingKingStudios::Tools
167
167
 
168
168
  return value.to_s if value.is_a?(Symbol)
169
169
 
170
- raise ArgumentError, 'argument must be a string', caller[1..-1]
170
+ raise ArgumentError, 'argument must be a string', caller[1..]
171
171
  end
172
172
  end
173
173
  end
@@ -18,6 +18,7 @@ module SleepingKingStudios::Tools
18
18
  # ActiveSupport::Inflector .
19
19
  def initialize(deprecation_strategy: nil, inflector: nil)
20
20
  @array_tools = ::SleepingKingStudios::Tools::ArrayTools.new
21
+ @assertions = ::SleepingKingStudios::Tools::Assertions.new
21
22
  @core_tools = ::SleepingKingStudios::Tools::CoreTools.new(
22
23
  deprecation_strategy: deprecation_strategy
23
24
  )
@@ -30,6 +31,8 @@ module SleepingKingStudios::Tools
30
31
 
31
32
  attr_reader :array_tools
32
33
 
34
+ attr_reader :assertions
35
+
33
36
  attr_reader :core_tools
34
37
 
35
38
  attr_reader :hash_tools
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'set'
4
+
3
5
  require 'sleeping_king_studios/tools/toolbox'
4
6
 
5
7
  class SleepingKingStudios::Tools::Toolbox::Inflector
@@ -47,7 +47,7 @@ module SleepingKingStudios::Tools::Toolbox
47
47
 
48
48
  word = word.to_s.gsub(/(\b|[_-])([a-z])/) { Regexp.last_match(2).upcase }
49
49
 
50
- (uppercase_first_letter ? word[0].upcase : word[0].downcase) + word[1..-1]
50
+ (uppercase_first_letter ? word[0].upcase : word[0].downcase) + word[1..]
51
51
  end
52
52
 
53
53
  # rubocop:disable Metrics/AbcSize
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sleeping_king_studios/tools/toolbox'
4
+
5
+ module SleepingKingStudios::Tools::Toolbox
6
+ # Mixin for partially applying constructor parameters.
7
+ #
8
+ # @example
9
+ # class Character
10
+ # extend SleepingKingStudios::Tools::Toolbox::Subclass
11
+ #
12
+ # def initialize(*traits)
13
+ # @traits = traits
14
+ # end
15
+ #
16
+ # attr_reader :traits
17
+ # end
18
+ #
19
+ # Bard = Character.subclass(:charismatic, :musical)
20
+ #
21
+ # aoife = Bard.new(:sorcerous)
22
+ # aoife.traits
23
+ # #=> [:charismatic, :musical, :sorcerous]
24
+ module Subclass
25
+ # Creates a subclass with partially applied constructor parameters.
26
+ #
27
+ # @param class_arguments [Array] The arguments, if any, to apply to the
28
+ # constructor. These arguments will be added before any args passed
29
+ # directly to the constructor.
30
+ # @param class_keywords [Hash] The keywords, if any, to apply to the
31
+ # constructor. These keywords will be added before any kwargs passed
32
+ # directly to the constructor.
33
+ #
34
+ # @yield The block, if any, to pass to the constructor. This will be
35
+ # overriden by a block passed directly to the constructor.
36
+ #
37
+ # @return [Class] the generated subclass.
38
+ def subclass(*class_arguments, **class_keywords, &class_block) # rubocop:disable Metrics/MethodLength
39
+ subclass = Class.new(self)
40
+
41
+ subclass.define_method :initialize do |*args, **kwargs, &block|
42
+ super(
43
+ *class_arguments,
44
+ *args,
45
+ **class_keywords,
46
+ **kwargs,
47
+ &(block || class_block)
48
+ )
49
+ end
50
+
51
+ subclass
52
+ end
53
+ end
54
+ end
@@ -6,5 +6,16 @@ module SleepingKingStudios::Tools
6
6
  # Namespace for common objects or patterns that are useful across projects but
7
7
  # are larger than or do not fit the functional paradigm of the tools.*
8
8
  # pattern.
9
- module Toolbox; end
9
+ module Toolbox
10
+ autoload :ConstantMap,
11
+ 'sleeping_king_studios/tools/toolbox/constant_map'
12
+ autoload :Inflector,
13
+ 'sleeping_king_studios/tools/toolbox/inflector'
14
+ autoload :Mixin,
15
+ 'sleeping_king_studios/tools/toolbox/mixin'
16
+ autoload :SemanticVersion,
17
+ 'sleeping_king_studios/tools/toolbox/semantic_version'
18
+ autoload :Subclass,
19
+ 'sleeping_king_studios/tools/toolbox/subclass'
20
+ end
10
21
  end
@@ -13,7 +13,7 @@ module SleepingKingStudios
13
13
  # Major version.
14
14
  MAJOR = 1
15
15
  # Minor version.
16
- MINOR = 0
16
+ MINOR = 1
17
17
  # Patch version.
18
18
  PATCH = 0
19
19
  # Prerelease version.
@@ -7,12 +7,14 @@ module SleepingKingStudios
7
7
  module Tools
8
8
  autoload :Base, 'sleeping_king_studios/tools/base'
9
9
  autoload :ArrayTools, 'sleeping_king_studios/tools/array_tools'
10
+ autoload :Assertions, 'sleeping_king_studios/tools/assertions'
10
11
  autoload :CoreTools, 'sleeping_king_studios/tools/core_tools'
11
12
  autoload :HashTools, 'sleeping_king_studios/tools/hash_tools'
12
13
  autoload :IntegerTools, 'sleeping_king_studios/tools/integer_tools'
13
14
  autoload :ObjectTools, 'sleeping_king_studios/tools/object_tools'
14
15
  autoload :StringTools, 'sleeping_king_studios/tools/string_tools'
15
16
  autoload :Toolbelt, 'sleeping_king_studios/tools/toolbelt'
17
+ autoload :Toolbox, 'sleeping_king_studios/tools/toolbox'
16
18
  autoload :Version, 'sleeping_king_studios/tools/version'
17
19
  end
18
20
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sleeping_king_studios-tools
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rob "Merlin" Smith
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-19 00:00:00.000000000 Z
11
+ date: 2022-09-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: byebug
@@ -58,42 +58,42 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '1.6'
61
+ version: '1.35'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '1.6'
68
+ version: '1.35'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rubocop-rake
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '0.5'
75
+ version: '0.6'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '0.5'
82
+ version: '0.6'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rubocop-rspec
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '2.1'
89
+ version: '2.12'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '2.1'
96
+ version: '2.12'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: simplecov
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -128,28 +128,14 @@ dependencies:
128
128
  requirements:
129
129
  - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: '2.5'
131
+ version: '2.7'
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: '2.5'
139
- - !ruby/object:Gem::Dependency
140
- name: sleeping_king_studios-tasks
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - "~>"
144
- - !ruby/object:Gem::Version
145
- version: '0.4'
146
- type: :development
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - "~>"
151
- - !ruby/object:Gem::Version
152
- version: '0.4'
138
+ version: '2.7'
153
139
  description: |
154
140
  A library of utility services and concerns to expand the functionality of
155
141
  core classes without polluting the global namespace.
@@ -166,6 +152,7 @@ files:
166
152
  - README.md
167
153
  - lib/sleeping_king_studios/tools.rb
168
154
  - lib/sleeping_king_studios/tools/array_tools.rb
155
+ - lib/sleeping_king_studios/tools/assertions.rb
169
156
  - lib/sleeping_king_studios/tools/base.rb
170
157
  - lib/sleeping_king_studios/tools/core_tools.rb
171
158
  - lib/sleeping_king_studios/tools/hash_tools.rb
@@ -179,11 +166,15 @@ files:
179
166
  - lib/sleeping_king_studios/tools/toolbox/inflector/rules.rb
180
167
  - lib/sleeping_king_studios/tools/toolbox/mixin.rb
181
168
  - lib/sleeping_king_studios/tools/toolbox/semantic_version.rb
169
+ - lib/sleeping_king_studios/tools/toolbox/subclass.rb
182
170
  - lib/sleeping_king_studios/tools/version.rb
183
171
  homepage: http://sleepingkingstudios.com
184
172
  licenses:
185
173
  - MIT
186
- metadata: {}
174
+ metadata:
175
+ bug_tracker_uri: https://github.com/sleepingkingstudios/sleeping_king_studios-tools/issues
176
+ source_code_uri: https://github.com/sleepingkingstudios/sleeping_king_studios-tools
177
+ rubygems_mfa_required: 'true'
187
178
  post_install_message:
188
179
  rdoc_options: []
189
180
  require_paths:
@@ -192,7 +183,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
192
183
  requirements:
193
184
  - - ">="
194
185
  - !ruby/object:Gem::Version
195
- version: 2.5.0
186
+ version: 2.7.0
196
187
  required_rubygems_version: !ruby/object:Gem::Requirement
197
188
  requirements:
198
189
  - - ">="