sleeping_king_studios-tools 1.1.1 → 1.2.0.rc.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/CHANGELOG.md +32 -0
- data/README.md +9 -1178
- data/lib/sleeping_king_studios/tools/array_tools.rb +166 -87
- data/lib/sleeping_king_studios/tools/assertions.rb +886 -156
- data/lib/sleeping_king_studios/tools/core_tools.rb +47 -13
- data/lib/sleeping_king_studios/tools/hash_tools.rb +137 -35
- data/lib/sleeping_king_studios/tools/integer_tools.rb +56 -40
- data/lib/sleeping_king_studios/tools/object_tools.rb +208 -68
- data/lib/sleeping_king_studios/tools/string_tools.rb +161 -54
- data/lib/sleeping_king_studios/tools/toolbelt.rb +47 -14
- data/lib/sleeping_king_studios/tools/toolbox/constant_map.rb +29 -10
- data/lib/sleeping_king_studios/tools/toolbox/inflector/rules.rb +23 -24
- data/lib/sleeping_king_studios/tools/toolbox/inflector.rb +35 -25
- data/lib/sleeping_king_studios/tools/toolbox/mixin.rb +83 -11
- data/lib/sleeping_king_studios/tools/toolbox/semantic_version.rb +25 -15
- data/lib/sleeping_king_studios/tools/toolbox/subclass.rb +4 -4
- data/lib/sleeping_king_studios/tools/toolbox.rb +1 -3
- data/lib/sleeping_king_studios/tools/version.rb +4 -4
- metadata +6 -136
- data/DEVELOPMENT.md +0 -17
@@ -1,84 +1,387 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'forwardable'
|
4
|
+
|
3
5
|
require 'sleeping_king_studios/tools'
|
4
6
|
|
5
7
|
module SleepingKingStudios::Tools
|
6
8
|
# Methods for asserting on the state of a function or application.
|
7
9
|
class Assertions < Base # rubocop:disable Metrics/ClassLength
|
10
|
+
# rubocop:disable Layout/HashAlignment
|
11
|
+
ERROR_MESSAGES =
|
12
|
+
{
|
13
|
+
'blank' =>
|
14
|
+
'must be nil or empty',
|
15
|
+
'block' =>
|
16
|
+
'block returned a falsy value',
|
17
|
+
'boolean' =>
|
18
|
+
'must be true or false',
|
19
|
+
'class' =>
|
20
|
+
'is not a Class',
|
21
|
+
'instance_of' =>
|
22
|
+
'is not an instance of %<expected>s',
|
23
|
+
'instance_of_anonymous' =>
|
24
|
+
'is not an instance of %<expected>s (%<parent>s)',
|
25
|
+
'matches' =>
|
26
|
+
'does not match the expected value',
|
27
|
+
'matches_proc' =>
|
28
|
+
'does not match the Proc',
|
29
|
+
'matches_regexp' =>
|
30
|
+
'does not match the pattern %<pattern>s',
|
31
|
+
'name' =>
|
32
|
+
'is not a String or a Symbol',
|
33
|
+
'nil' =>
|
34
|
+
'must be nil',
|
35
|
+
'not_nil' =>
|
36
|
+
'must not be nil',
|
37
|
+
# @note: This value will be changed in a future version.
|
38
|
+
'presence' =>
|
39
|
+
"can't be blank"
|
40
|
+
}
|
41
|
+
.transform_keys { |key| "sleeping_king_studios.tools.assertions.#{key}" }
|
42
|
+
.freeze
|
43
|
+
private_constant :ERROR_MESSAGES
|
44
|
+
# rubocop:enable Layout/HashAlignment
|
45
|
+
|
46
|
+
# Utility for grouping multiple assertion statements.
|
47
|
+
#
|
48
|
+
# @example
|
49
|
+
# rocket = Struct.new(:fuel, :launched).new(0.0, true)
|
50
|
+
# aggregator = SleepingKingStudios::Tools::Assertions::Aggregator.new
|
51
|
+
# aggregator.empty?
|
52
|
+
# #=> true
|
53
|
+
#
|
54
|
+
# aggregator.assert(message: 'is out of fuel') { rocket.fuel > 0 }
|
55
|
+
# aggregator.assert(message: 'has already launched') { !rocket.launched }
|
56
|
+
# aggregator.empty?
|
57
|
+
# #=> false
|
58
|
+
# aggregator.failure_message
|
59
|
+
# #=> 'is out of fuel, has already launched'
|
60
|
+
class Aggregator < Assertions
|
61
|
+
extend Forwardable
|
62
|
+
|
63
|
+
def initialize
|
64
|
+
super
|
65
|
+
|
66
|
+
@failures = []
|
67
|
+
end
|
68
|
+
|
69
|
+
# @!method <<(message)
|
70
|
+
# Appends the message to the failure messages.
|
71
|
+
#
|
72
|
+
# @param message [String] the message to append.
|
73
|
+
#
|
74
|
+
# @return [Array] the updated failure messages.
|
75
|
+
#
|
76
|
+
# @see Array#<<.
|
77
|
+
|
78
|
+
# @!method clear
|
79
|
+
# Removes all items from the failure messages.
|
80
|
+
#
|
81
|
+
# @return [Array] the empty failure messages.
|
82
|
+
#
|
83
|
+
# @see Array#clear.
|
84
|
+
|
85
|
+
# @!method count
|
86
|
+
# Returns a count of the failure message.
|
87
|
+
#
|
88
|
+
# @return [Integer] the number of failure messages.
|
89
|
+
#
|
90
|
+
# @see Array#count.
|
91
|
+
|
92
|
+
# @!method each
|
93
|
+
# Iterates over the failure messages.
|
94
|
+
#
|
95
|
+
# @overload each
|
96
|
+
# Returns an enumerator that iterates over the failure messages.
|
97
|
+
#
|
98
|
+
# @return [Enumerator] an enumerator over the messages.
|
99
|
+
#
|
100
|
+
# @see Enumerable#each.
|
101
|
+
#
|
102
|
+
# @overload each(&block)
|
103
|
+
# Yields each failure message to the block.
|
104
|
+
#
|
105
|
+
# @yieldparam message [String] the current failure message.
|
106
|
+
#
|
107
|
+
# @see Enumerable#each.
|
108
|
+
|
109
|
+
# @!method empty?
|
110
|
+
# Checks if there are any failure messages.
|
111
|
+
#
|
112
|
+
# @return [true, false] true if there are no failure messages; otherwise
|
113
|
+
# false.
|
114
|
+
#
|
115
|
+
# @see Enumerable#empty?
|
116
|
+
|
117
|
+
# @!method size
|
118
|
+
# Returns a count of the failure message.
|
119
|
+
#
|
120
|
+
# @return [Integer] the number of failure messages.
|
121
|
+
#
|
122
|
+
# @see Array#size.
|
123
|
+
def_delegators :@failures,
|
124
|
+
:<<,
|
125
|
+
:clear,
|
126
|
+
:count,
|
127
|
+
:each,
|
128
|
+
:empty?,
|
129
|
+
:size
|
130
|
+
|
131
|
+
# (see SleepingKingStudios::Tools::Assertions#assert_group)
|
132
|
+
def assert_group(error_class: AssertionError, message: nil, &assertions)
|
133
|
+
return super if message
|
134
|
+
|
135
|
+
raise ArgumentError, 'no block given' unless block_given?
|
136
|
+
|
137
|
+
assertions.call(self)
|
138
|
+
end
|
139
|
+
alias aggregate assert_group
|
140
|
+
|
141
|
+
# Generates a combined failure message from the configured messages.
|
142
|
+
#
|
143
|
+
# @return [String] the combined messages for each failed assertion.
|
144
|
+
#
|
145
|
+
# @example With an empty aggregator.
|
146
|
+
# aggregator = SleepingKingStudios::Tools::Assertions::Aggregator.new
|
147
|
+
#
|
148
|
+
# aggregator.failure_message
|
149
|
+
# #=> ''
|
150
|
+
#
|
151
|
+
# @example With an aggregator with failure messages.
|
152
|
+
# aggregator = SleepingKingStudios::Tools::Assertions::Aggregator.new
|
153
|
+
# aggrgator << 'rocket is out of fuel'
|
154
|
+
# aggrgator << 'rocket is not pointed toward space'
|
155
|
+
#
|
156
|
+
# aggregator.failure_message
|
157
|
+
# #=> 'rocket is out of fuel, rocket is not pointed toward space'
|
158
|
+
def failure_message
|
159
|
+
failures.join(', ')
|
160
|
+
end
|
161
|
+
|
162
|
+
private
|
163
|
+
|
164
|
+
attr_reader :failures
|
165
|
+
|
166
|
+
def handle_error(message:, **_)
|
167
|
+
failures << message
|
168
|
+
|
169
|
+
message
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
8
173
|
# Error class for handling a failed assertion.
|
9
174
|
class AssertionError < StandardError; end
|
10
175
|
|
176
|
+
# @return [Class] the class used to aggregate grouped assertion failures.
|
177
|
+
def aggregator_class
|
178
|
+
Aggregator
|
179
|
+
end
|
180
|
+
|
11
181
|
# Asserts that the block returns a truthy value.
|
12
182
|
#
|
13
|
-
# @param error_class [Class]
|
14
|
-
# @param message [String]
|
183
|
+
# @param error_class [Class] the exception class to raise on a failure.
|
184
|
+
# @param message [String] the exception message to raise on a failure.
|
15
185
|
#
|
16
|
-
# @yield
|
17
|
-
# @yieldreturn [Object]
|
186
|
+
# @yield the block to evaluate.
|
187
|
+
# @yieldreturn [Object] the returned value of the block.
|
188
|
+
#
|
189
|
+
# @return [void]
|
190
|
+
#
|
191
|
+
# @raise [AssertionError] if the block does not return a truthy value.
|
18
192
|
#
|
19
|
-
# @
|
193
|
+
# @example
|
194
|
+
# Assertions.assert { true == false }
|
195
|
+
# #=> raises an AssertionError with message 'block returned a falsy value'
|
196
|
+
#
|
197
|
+
# Assertions.assert { true == true }
|
198
|
+
# #=> does not raise an exception
|
20
199
|
def assert(error_class: AssertionError, message: nil, &block)
|
21
200
|
return if block.call
|
22
201
|
|
23
|
-
|
24
|
-
|
25
|
-
|
202
|
+
message ||= error_message_for(
|
203
|
+
'sleeping_king_studios.tools.assertions.block',
|
204
|
+
as: false
|
205
|
+
)
|
206
|
+
|
207
|
+
handle_error(error_class:, message:)
|
208
|
+
end
|
209
|
+
|
210
|
+
# Asserts that the value is either nil or empty.
|
211
|
+
#
|
212
|
+
# @param value [Object] the value to assert on.
|
213
|
+
# @param as [String] the name of the asserted value.
|
214
|
+
# @param error_class [Class] the exception class to raise on a failure.
|
215
|
+
# @param message [String] the exception message to raise on a failure.
|
216
|
+
#
|
217
|
+
# @return [void]
|
218
|
+
#
|
219
|
+
# @raise [AssertionError] if the value is not nil and either does not respond
|
220
|
+
# to #empty? or value.empty returns false.
|
221
|
+
#
|
222
|
+
# @example
|
223
|
+
# Assertions.assert_blank(nil)
|
224
|
+
# #=> does not raise an exception
|
225
|
+
#
|
226
|
+
# Assertions.assert_blank(Object.new)
|
227
|
+
# #=> raises an AssertionError with message 'value must be nil or empty'
|
228
|
+
#
|
229
|
+
# Assertions.assert_blank([])
|
230
|
+
# #=> does not raise an exception
|
231
|
+
#
|
232
|
+
# Assertions.assert_blank([1, 2, 3])
|
233
|
+
# #=> raises an AssertionError with message 'value must be nil or empty'
|
234
|
+
def assert_blank(
|
235
|
+
value,
|
236
|
+
as: 'value',
|
237
|
+
error_class: AssertionError,
|
238
|
+
message: nil
|
239
|
+
)
|
240
|
+
return if value.nil?
|
241
|
+
return if value.respond_to?(:empty?) && value.empty?
|
242
|
+
|
243
|
+
message ||= error_message_for(
|
244
|
+
'sleeping_king_studios.tools.assertions.blank',
|
245
|
+
as:
|
246
|
+
)
|
247
|
+
|
248
|
+
handle_error(error_class:, message:)
|
26
249
|
end
|
27
250
|
|
28
251
|
# Asserts that the value is either true or false.
|
29
252
|
#
|
30
|
-
# @param value [Object]
|
31
|
-
# @param as [String]
|
32
|
-
# @param error_class [Class]
|
33
|
-
# @param message [String]
|
253
|
+
# @param value [Object] the value to assert on.
|
254
|
+
# @param as [String] the name of the asserted value.
|
255
|
+
# @param error_class [Class] the exception class to raise on a failure.
|
256
|
+
# @param message [String] the exception message to raise on a failure.
|
257
|
+
# @param optional [true, false] if true, allows nil values.
|
258
|
+
#
|
259
|
+
# @return [void]
|
260
|
+
#
|
261
|
+
# @raise [AssertionError] if the value is not true or false.
|
34
262
|
#
|
35
|
-
# @
|
263
|
+
# @example
|
264
|
+
# Assertions.assert_boolean(nil)
|
265
|
+
# #=> raises an AssertionError with message 'value must be true or false'
|
266
|
+
#
|
267
|
+
# Assertions.assert_boolean(Object.new)
|
268
|
+
# #=> raises an AssertionError with message 'value must be true or false'
|
269
|
+
#
|
270
|
+
# Assertions.assert_boolean(false)
|
271
|
+
# #=> does not raise an exception
|
272
|
+
#
|
273
|
+
# Assertions.assert_boolean(true)
|
274
|
+
# #=> does not raise an exception
|
36
275
|
def assert_boolean(
|
37
276
|
value,
|
38
277
|
as: 'value',
|
39
278
|
error_class: AssertionError,
|
40
|
-
message: nil
|
279
|
+
message: nil,
|
280
|
+
optional: false
|
41
281
|
)
|
282
|
+
return if optional && value.nil?
|
283
|
+
|
42
284
|
return if value.equal?(true) || value.equal?(false)
|
43
285
|
|
44
|
-
|
45
|
-
|
46
|
-
|
286
|
+
message ||= error_message_for(
|
287
|
+
'sleeping_king_studios.tools.assertions.boolean',
|
288
|
+
as:
|
289
|
+
)
|
290
|
+
|
291
|
+
handle_error(error_class:, message:)
|
47
292
|
end
|
48
293
|
|
49
294
|
# Asserts that the value is a Class.
|
50
295
|
#
|
51
|
-
# @param value [Object]
|
52
|
-
# @param as [String]
|
53
|
-
# @param error_class [Class]
|
54
|
-
# @param message [String]
|
296
|
+
# @param value [Object] the value to assert on.
|
297
|
+
# @param as [String] the name of the asserted value.
|
298
|
+
# @param error_class [Class] the exception class to raise on a failure.
|
299
|
+
# @param message [String] the exception message to raise on a failure.
|
300
|
+
# @param optional [true, false] if true, allows nil values.
|
301
|
+
#
|
302
|
+
# @return [void]
|
303
|
+
#
|
304
|
+
# @raise [AssertionError] if the value is not a Class.
|
55
305
|
#
|
56
|
-
# @
|
306
|
+
# @example
|
307
|
+
# Assertions.assert_class(Object.new)
|
308
|
+
# #=> raises an AssertionError with message 'value is not a class'
|
309
|
+
#
|
310
|
+
# Assertions.assert_class(String)
|
311
|
+
# #=> does not raise an exception
|
57
312
|
def assert_class(
|
58
313
|
value,
|
59
314
|
as: 'value',
|
60
315
|
error_class: AssertionError,
|
61
|
-
message: nil
|
316
|
+
message: nil,
|
317
|
+
optional: false
|
62
318
|
)
|
319
|
+
return if optional && value.nil?
|
320
|
+
|
63
321
|
return if value.is_a?(Class)
|
64
322
|
|
65
|
-
|
66
|
-
|
67
|
-
|
323
|
+
message ||= error_message_for(
|
324
|
+
'sleeping_king_studios.tools.assertions.class',
|
325
|
+
as:
|
326
|
+
)
|
327
|
+
|
328
|
+
handle_error(error_class:, message:)
|
68
329
|
end
|
69
330
|
|
331
|
+
# Evaluates a series of assertions and combines all failures.
|
332
|
+
#
|
333
|
+
# @param error_class [Class] the exception class to raise on a failure.
|
334
|
+
# @param message [String] the exception message to raise on a failure.
|
335
|
+
#
|
336
|
+
# @yield the assertions to evaluate.
|
337
|
+
# @yieldparam aggregator [Aggregator] the aggregator object.
|
338
|
+
#
|
339
|
+
# @return [void]
|
340
|
+
#
|
341
|
+
# @raise [AssertionError] if any of the assertions fail.
|
342
|
+
#
|
343
|
+
# @example
|
344
|
+
# Assertions.assert_group do |group|
|
345
|
+
# group.assert_name(nil, as: 'label')
|
346
|
+
# group.assert_instance_of(0.0, expected: Integer, as: 'quantity')
|
347
|
+
# end
|
348
|
+
# # raises an AssertionError with message: "label can't be blank, quantity is not an instance of Integer"
|
349
|
+
def assert_group(error_class: AssertionError, message: nil, &assertions)
|
350
|
+
raise ArgumentError, 'no block given' unless block_given?
|
351
|
+
|
352
|
+
aggregator = aggregator_class.new
|
353
|
+
|
354
|
+
assertions.call(aggregator)
|
355
|
+
|
356
|
+
return if aggregator.empty?
|
357
|
+
|
358
|
+
message ||= aggregator.failure_message
|
359
|
+
|
360
|
+
handle_error(error_class:, message:)
|
361
|
+
end
|
362
|
+
alias aggregate assert_group
|
363
|
+
|
70
364
|
# Asserts that the value is an example of the given Class.
|
71
365
|
#
|
72
|
-
# @param value [Object]
|
73
|
-
# @param as [String]
|
74
|
-
# @param error_class [Class]
|
75
|
-
# @param expected [Class]
|
76
|
-
# @param message [String]
|
77
|
-
# @param optional [true, false]
|
366
|
+
# @param value [Object] the value to assert on.
|
367
|
+
# @param as [String] the name of the asserted value.
|
368
|
+
# @param error_class [Class] the exception class to raise on a failure.
|
369
|
+
# @param expected [Class] the expected class.
|
370
|
+
# @param message [String] the exception message to raise on a failure.
|
371
|
+
# @param optional [true, false] if true, allows nil values.
|
372
|
+
#
|
373
|
+
# @return [void]
|
78
374
|
#
|
79
|
-
# @raise ArgumentError if the expected class is not a Class.
|
80
|
-
# @raise AssertionError if the value is not an instance of the expected
|
375
|
+
# @raise [ArgumentError] if the expected class is not a Class.
|
376
|
+
# @raise [AssertionError] if the value is not an instance of the expected
|
81
377
|
# class.
|
378
|
+
#
|
379
|
+
# @example
|
380
|
+
# Assertions.assert_instance_of(:foo, expected: String)
|
381
|
+
# #=> raises an AssertionError with message 'value is not an instance of String'
|
382
|
+
#
|
383
|
+
# Assertions.assert_instance_of('foo', expected: String)
|
384
|
+
# #=> does not raise an exception
|
82
385
|
def assert_instance_of( # rubocop:disable Metrics/ParameterLists
|
83
386
|
value,
|
84
387
|
expected:,
|
@@ -94,22 +397,31 @@ module SleepingKingStudios::Tools
|
|
94
397
|
return if optional && value.nil?
|
95
398
|
return if value.is_a?(expected)
|
96
399
|
|
97
|
-
|
98
|
-
|
99
|
-
|
400
|
+
message ||= error_message_for_instance_of(as:, expected:)
|
401
|
+
|
402
|
+
handle_error(error_class:, message:)
|
100
403
|
end
|
101
404
|
|
102
405
|
# Asserts that the value matches the expected object using #===.
|
103
406
|
#
|
104
|
-
# @param value [Object]
|
105
|
-
# @param as [String]
|
106
|
-
# @param error_class [Class]
|
107
|
-
# @param expected [#===]
|
108
|
-
# @param message [String]
|
109
|
-
# @param optional [true, false]
|
407
|
+
# @param value [Object] the value to assert on.
|
408
|
+
# @param as [String] the name of the asserted value.
|
409
|
+
# @param error_class [Class] the exception class to raise on a failure.
|
410
|
+
# @param expected [#===] the expected object.
|
411
|
+
# @param message [String] the exception message to raise on a failure.
|
412
|
+
# @param optional [true, false] if true, allows nil values.
|
413
|
+
#
|
414
|
+
# @return [void]
|
110
415
|
#
|
111
|
-
# @raise AssertionError if the value does not match the expected object.
|
112
|
-
|
416
|
+
# @raise [AssertionError] if the value does not match the expected object.
|
417
|
+
#
|
418
|
+
# @example
|
419
|
+
# Assertions.assert_matches('bar', expected: /foo/)
|
420
|
+
# #=> raises an AssertionError with message 'value does not match the pattern /foo/'
|
421
|
+
#
|
422
|
+
# Assertions.assert_matches('foo', expected: /foo/)
|
423
|
+
# #=> does not raise an exception
|
424
|
+
def assert_matches( # rubocop:disable Metrics/ParameterLists
|
113
425
|
value,
|
114
426
|
expected:,
|
115
427
|
as: 'value',
|
@@ -120,31 +432,39 @@ module SleepingKingStudios::Tools
|
|
120
432
|
return if optional && value.nil?
|
121
433
|
return if expected === value # rubocop:disable Style/CaseEquality
|
122
434
|
|
123
|
-
message ||=
|
124
|
-
|
125
|
-
|
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)
|
435
|
+
message ||= error_message_for_matches(as:, expected:)
|
436
|
+
|
437
|
+
handle_error(error_class:, message:)
|
136
438
|
end
|
137
439
|
|
138
440
|
# Asserts that the value is a non-empty String or Symbol.
|
139
441
|
#
|
140
|
-
# @param value [Object]
|
141
|
-
# @param as [String]
|
142
|
-
# @param error_class [Class]
|
143
|
-
# @param message [String]
|
144
|
-
# @param optional [true, false]
|
442
|
+
# @param value [Object] the value to assert on.
|
443
|
+
# @param as [String] the name of the asserted value.
|
444
|
+
# @param error_class [Class] the exception class to raise on a failure.
|
445
|
+
# @param message [String] the exception message to raise on a failure.
|
446
|
+
# @param optional [true, false] if true, allows nil values.
|
145
447
|
#
|
146
|
-
# @
|
147
|
-
#
|
448
|
+
# @return [void]
|
449
|
+
#
|
450
|
+
# @raise [AssertionError] if the value is not a String or a Symbol, or if
|
451
|
+
# the value is empty.
|
452
|
+
#
|
453
|
+
# @example
|
454
|
+
# Assertions.assert_name(nil)
|
455
|
+
# #=> raises an AssertionError with message "value can't be blank"
|
456
|
+
#
|
457
|
+
# Assertions.assert_name(Object.new)
|
458
|
+
# #=> raises an AssertionError with message 'value is not a String or a Symbol'
|
459
|
+
#
|
460
|
+
# Assertions.assert_name('')
|
461
|
+
# #=> raises an AssertionError with message "value can't be blank"
|
462
|
+
#
|
463
|
+
# Assertions.assert_name('foo')
|
464
|
+
# #=> does not raise an exception
|
465
|
+
#
|
466
|
+
# Assertions.assert_name(:bar)
|
467
|
+
# #=> does not raise an exception
|
148
468
|
def assert_name( # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
149
469
|
value,
|
150
470
|
as: 'value',
|
@@ -155,77 +475,342 @@ module SleepingKingStudios::Tools
|
|
155
475
|
if value.nil?
|
156
476
|
return if optional
|
157
477
|
|
158
|
-
|
478
|
+
message ||= error_message_for(
|
479
|
+
'sleeping_king_studios.tools.assertions.presence',
|
480
|
+
as:
|
481
|
+
)
|
482
|
+
|
483
|
+
return handle_error(error_class:, message:)
|
159
484
|
end
|
160
485
|
|
161
486
|
unless value.is_a?(String) || value.is_a?(Symbol)
|
162
|
-
|
163
|
-
|
164
|
-
|
487
|
+
message ||= error_message_for(
|
488
|
+
'sleeping_king_studios.tools.assertions.name',
|
489
|
+
as:
|
490
|
+
)
|
491
|
+
|
492
|
+
return handle_error(error_class:, message:)
|
165
493
|
end
|
166
494
|
|
167
495
|
return unless value.empty?
|
168
496
|
|
169
|
-
|
497
|
+
message ||= error_message_for(
|
498
|
+
'sleeping_king_studios.tools.assertions.presence',
|
499
|
+
as:
|
500
|
+
)
|
501
|
+
|
502
|
+
handle_error(error_class:, message:)
|
503
|
+
end
|
504
|
+
|
505
|
+
# Asserts that the value is nil.
|
506
|
+
#
|
507
|
+
# @param value [Object] the value to assert on.
|
508
|
+
# @param as [String] the name of the asserted value.
|
509
|
+
# @param error_class [Class] the exception class to raise on a failure.
|
510
|
+
# @param message [String] the exception message to raise on a failure.
|
511
|
+
#
|
512
|
+
# @return [void]
|
513
|
+
#
|
514
|
+
# @raise [AssertionError] if the value is not nil.
|
515
|
+
#
|
516
|
+
# @example
|
517
|
+
# Assertions.assert_nil(nil)
|
518
|
+
# #=> does not raise an exception
|
519
|
+
#
|
520
|
+
# Assertions.assert_nil(Object.new)
|
521
|
+
# #=> raises an AssertionError with message 'value must be nil'
|
522
|
+
def assert_nil(
|
523
|
+
value,
|
524
|
+
as: 'value',
|
525
|
+
error_class: AssertionError,
|
526
|
+
message: nil
|
527
|
+
)
|
528
|
+
return if value.nil?
|
529
|
+
|
530
|
+
message ||= error_message_for(
|
531
|
+
'sleeping_king_studios.tools.assertions.nil',
|
532
|
+
as:
|
533
|
+
)
|
534
|
+
|
535
|
+
handle_error(error_class:, message:)
|
536
|
+
end
|
537
|
+
|
538
|
+
# Asserts that the value is not nil.
|
539
|
+
#
|
540
|
+
# @param value [Object] the value to assert on.
|
541
|
+
# @param as [String] the name of the asserted value.
|
542
|
+
# @param error_class [Class] the exception class to raise on a failure.
|
543
|
+
# @param message [String] the exception message to raise on a failure.
|
544
|
+
#
|
545
|
+
# @return [void]
|
546
|
+
#
|
547
|
+
# @raise [AssertionError] if the value is nil.
|
548
|
+
#
|
549
|
+
# @example
|
550
|
+
# Assertions.assert_not_nil(nil)
|
551
|
+
# #=> raises an AssertionError with message 'value must not be nil'
|
552
|
+
#
|
553
|
+
# Assertions.assert_not_nil(Object.new)
|
554
|
+
# #=> does not raise an exception
|
555
|
+
def assert_not_nil(
|
556
|
+
value,
|
557
|
+
as: 'value',
|
558
|
+
error_class: AssertionError,
|
559
|
+
message: nil
|
560
|
+
)
|
561
|
+
return unless value.nil?
|
562
|
+
|
563
|
+
message ||= error_message_for(
|
564
|
+
'sleeping_king_studios.tools.assertions.not_nil',
|
565
|
+
as:
|
566
|
+
)
|
567
|
+
|
568
|
+
handle_error(error_class:, message:)
|
569
|
+
end
|
570
|
+
|
571
|
+
# Asserts that the value is not nil and not empty.
|
572
|
+
#
|
573
|
+
# @param value [Object] the value to assert on.
|
574
|
+
# @param as [String] the name of the asserted value.
|
575
|
+
# @param error_class [Class] the exception class to raise on a failure.
|
576
|
+
# @param message [String] the exception message to raise on a failure.
|
577
|
+
# @param optional [true, false] if true, allows nil values.
|
578
|
+
#
|
579
|
+
# @return [void]
|
580
|
+
#
|
581
|
+
# @raise [AssertionError] if the value is nil, or if the value responds to
|
582
|
+
# #empty? and value.empty is true.
|
583
|
+
#
|
584
|
+
# @example
|
585
|
+
# Assertions.assert_presence(nil)
|
586
|
+
# #=> raises an AssertionError with message "can't be blank"
|
587
|
+
#
|
588
|
+
# Assertions.assert_presence(Object.new)
|
589
|
+
# #=> does not raise an exception
|
590
|
+
#
|
591
|
+
# Assertions.assert_presence([])
|
592
|
+
# #=> raises an AssertionError with message "can't be blank"
|
593
|
+
#
|
594
|
+
# Assertions.assert_presence([1, 2, 3])
|
595
|
+
# #=> does not raise an exception
|
596
|
+
def assert_presence( # rubocop:disable Metrics/MethodLength
|
597
|
+
value,
|
598
|
+
as: 'value',
|
599
|
+
error_class: AssertionError,
|
600
|
+
message: nil,
|
601
|
+
optional: false
|
602
|
+
)
|
603
|
+
if value.nil?
|
604
|
+
return if optional
|
605
|
+
|
606
|
+
message ||= error_message_for(
|
607
|
+
'sleeping_king_studios.tools.assertions.presence',
|
608
|
+
as:
|
609
|
+
)
|
610
|
+
|
611
|
+
handle_error(error_class:, message:)
|
612
|
+
end
|
613
|
+
|
614
|
+
return unless value.respond_to?(:empty?) && value.empty?
|
615
|
+
|
616
|
+
message ||= error_message_for(
|
617
|
+
'sleeping_king_studios.tools.assertions.presence',
|
618
|
+
as:
|
619
|
+
)
|
620
|
+
|
621
|
+
handle_error(error_class:, message:)
|
622
|
+
end
|
623
|
+
|
624
|
+
# Generates an error message for a failed validation.
|
625
|
+
#
|
626
|
+
# @param scope [String] the message scope.
|
627
|
+
# @param options [Hash] additional options for generating the message.
|
628
|
+
#
|
629
|
+
# @option options as [String] the name of the validated property. Defaults
|
630
|
+
# to 'value'.
|
631
|
+
# @option options expected [Object] the expected object, if any.
|
632
|
+
#
|
633
|
+
# @return [String] the generated error message.
|
634
|
+
#
|
635
|
+
# @example
|
636
|
+
# scope = 'sleeping_king_studios.tools.assertions.blank'
|
637
|
+
#
|
638
|
+
# assertions.error_message_for(scope)
|
639
|
+
# #=> 'value must be nil or empty'
|
640
|
+
# assertions.error_message_for(scope, as: false)
|
641
|
+
# #=> 'must be nil or empty'
|
642
|
+
# assertions.error_message_for(scope, as: 'item')
|
643
|
+
# #=> 'item must be nil or empty'
|
644
|
+
def error_message_for(scope, as: 'value', **options)
|
645
|
+
message =
|
646
|
+
ERROR_MESSAGES
|
647
|
+
.fetch(scope.to_s) { return "Error message missing: #{scope}" }
|
648
|
+
.then { |raw| format(raw, **options) }
|
649
|
+
|
650
|
+
join_error_message(as:, message:)
|
170
651
|
end
|
171
652
|
|
172
653
|
# Asserts that the block returns a truthy value.
|
173
654
|
#
|
174
|
-
# @param message [String]
|
655
|
+
# @param message [String] the exception message to raise on a failure.
|
175
656
|
#
|
176
657
|
# @yield The block to evaluate.
|
177
|
-
# @yieldreturn [Object]
|
658
|
+
# @yieldreturn [Object] the returned value of the block.
|
659
|
+
#
|
660
|
+
# @return [void]
|
178
661
|
#
|
179
|
-
# @raise ArgumentError if the block does not return a truthy value.
|
662
|
+
# @raise [ArgumentError] if the block does not return a truthy value.
|
663
|
+
#
|
664
|
+
# @example
|
665
|
+
# Assertions.validate { true == false }
|
666
|
+
# #=> raises an ArgumentError with message 'block returned a falsy value'
|
667
|
+
#
|
668
|
+
# Assertions.validate { true == true }
|
669
|
+
# #=> does not raise an exception
|
180
670
|
def validate(message: nil, &block)
|
181
|
-
|
671
|
+
assert(
|
672
|
+
error_class: ArgumentError,
|
673
|
+
message:,
|
674
|
+
&block
|
675
|
+
)
|
676
|
+
end
|
182
677
|
|
183
|
-
|
184
|
-
|
185
|
-
|
678
|
+
# Asserts that the value is either nil or empty.
|
679
|
+
#
|
680
|
+
# @param value [Object] the value to assert on.
|
681
|
+
# @param as [String] the name of the asserted value.
|
682
|
+
# @param message [String] the exception message to raise on a failure.
|
683
|
+
#
|
684
|
+
# @return [void]
|
685
|
+
#
|
686
|
+
# @raise [ArgumentError] if the value is not nil and either does not respond
|
687
|
+
# to #empty? or value.empty returns false.
|
688
|
+
#
|
689
|
+
# @example
|
690
|
+
# Assertions.validate_blank(nil)
|
691
|
+
# #=> does not raise an exception
|
692
|
+
#
|
693
|
+
# Assertions.validate_blank(Object.new)
|
694
|
+
# #=> raises an ArgumentError with message 'value must be nil or empty'
|
695
|
+
#
|
696
|
+
# Assertions.validate_blank([])
|
697
|
+
# #=> does not raise an exception
|
698
|
+
#
|
699
|
+
# Assertions.validate_blank([1, 2, 3])
|
700
|
+
# #=> raises an ArgumentError with message 'value must be nil or empty'
|
701
|
+
def validate_blank(value, as: 'value', message: nil)
|
702
|
+
assert_blank(
|
703
|
+
value,
|
704
|
+
as:,
|
705
|
+
error_class: ArgumentError,
|
706
|
+
message:
|
707
|
+
)
|
186
708
|
end
|
187
709
|
|
188
710
|
# Asserts that the value is either true or false.
|
189
711
|
#
|
190
|
-
# @param value [Object]
|
191
|
-
# @param as [String]
|
192
|
-
# @param message [String]
|
712
|
+
# @param value [Object] the value to assert on.
|
713
|
+
# @param as [String] the name of the asserted value.
|
714
|
+
# @param message [String] the exception message to raise on a failure.
|
715
|
+
# @param optional [true, false] if true, allows nil values.
|
193
716
|
#
|
194
|
-
# @
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
717
|
+
# @return [void]
|
718
|
+
#
|
719
|
+
# @raise [ArgumentError] if the value is not true or false.
|
720
|
+
#
|
721
|
+
# @example
|
722
|
+
# Assertions.validate_boolean(nil)
|
723
|
+
# #=> raises an ArgumentError with message 'value must be true or false'
|
724
|
+
#
|
725
|
+
# Assertions.validate_boolean(Object.new)
|
726
|
+
# #=> raises an ArgumentError with message 'value must be true or false'
|
727
|
+
#
|
728
|
+
# Assertions.validate_boolean(false)
|
729
|
+
# #=> does not raise an exception
|
730
|
+
#
|
731
|
+
# Assertions.validate_boolean(true)
|
732
|
+
# #=> does not raise an exception
|
733
|
+
def validate_boolean(value, as: 'value', message: nil, optional: false)
|
734
|
+
assert_boolean(
|
735
|
+
value,
|
736
|
+
as:,
|
737
|
+
error_class: ArgumentError,
|
738
|
+
message:,
|
739
|
+
optional:
|
740
|
+
)
|
201
741
|
end
|
202
742
|
|
203
743
|
# Asserts that the value is a Class.
|
204
744
|
#
|
205
|
-
# @param value [Object]
|
206
|
-
# @param as [String]
|
207
|
-
# @param message [String]
|
745
|
+
# @param value [Object] the value to assert on.
|
746
|
+
# @param as [String] the name of the asserted value.
|
747
|
+
# @param message [String] the exception message to raise on a failure.
|
748
|
+
# @param optional [true, false] if true, allows nil values.
|
208
749
|
#
|
209
|
-
# @
|
210
|
-
|
211
|
-
|
750
|
+
# @return [void]
|
751
|
+
#
|
752
|
+
# @raise [ArgumentError] if the value is not a Class.
|
753
|
+
#
|
754
|
+
# @example
|
755
|
+
# Assertions.validate_class(Object.new)
|
756
|
+
# #=> raises an ArgumentError with message 'value is not a class'
|
757
|
+
#
|
758
|
+
# Assertions.validate_class(String)
|
759
|
+
# #=> does not raise an exception
|
760
|
+
def validate_class(value, as: 'value', message: nil, optional: false)
|
761
|
+
assert_class(
|
762
|
+
value,
|
763
|
+
as:,
|
764
|
+
error_class: ArgumentError,
|
765
|
+
message:,
|
766
|
+
optional:
|
767
|
+
)
|
768
|
+
end
|
212
769
|
|
213
|
-
|
214
|
-
|
215
|
-
|
770
|
+
# Evaluates a series of validations and combines all failures.
|
771
|
+
#
|
772
|
+
# @param message [String] the exception message to raise on a failure.
|
773
|
+
#
|
774
|
+
# @yield the validations to evaluate.
|
775
|
+
# @yieldparam aggregator [Aggregator] the aggregator object.
|
776
|
+
#
|
777
|
+
# @return [void]
|
778
|
+
#
|
779
|
+
# @raise [ArgumentError] if any of the validations fail.
|
780
|
+
#
|
781
|
+
# @example
|
782
|
+
# Assertions.validate_group do |group|
|
783
|
+
# group.validate_name(nil, as: 'label')
|
784
|
+
# group.validate_instance_of(0.0, expected: Integer, as: 'quantity')
|
785
|
+
# end
|
786
|
+
# # raises an ArgumentError with message: "label can't be blank, quantity is not an instance of Integer"
|
787
|
+
def validate_group(message: nil, &validations)
|
788
|
+
assert_group(
|
789
|
+
error_class: ArgumentError,
|
790
|
+
message:,
|
791
|
+
&validations
|
792
|
+
)
|
216
793
|
end
|
217
794
|
|
218
795
|
# Asserts that the value is an example of the given Class.
|
219
796
|
#
|
220
|
-
# @param value [Object]
|
221
|
-
# @param as [String]
|
222
|
-
# @param expected [Class]
|
223
|
-
# @param message [String]
|
224
|
-
# @param optional [true, false]
|
797
|
+
# @param value [Object] the value to assert on.
|
798
|
+
# @param as [String] the name of the asserted value.
|
799
|
+
# @param expected [Class] the expected class.
|
800
|
+
# @param message [String] the exception message to raise on a failure.
|
801
|
+
# @param optional [true, false] if true, allows nil values.
|
802
|
+
#
|
803
|
+
# @return [void]
|
225
804
|
#
|
226
|
-
# @raise ArgumentError if the
|
227
|
-
# @raise AssertionError if the value is not an instance of the expected
|
805
|
+
# @raise [ArgumentError] if the value is not an instance of the expected
|
228
806
|
# class.
|
807
|
+
#
|
808
|
+
# @example
|
809
|
+
# Assertions.validate_instance_of(:foo, expected: String)
|
810
|
+
# #=> raises an AssertionError with message 'value is not an instance of String'
|
811
|
+
#
|
812
|
+
# Assertions.validate_instance_of('foo', expected: String)
|
813
|
+
# #=> does not raise an exception
|
229
814
|
def validate_instance_of(
|
230
815
|
value,
|
231
816
|
expected:,
|
@@ -233,90 +818,235 @@ module SleepingKingStudios::Tools
|
|
233
818
|
message: nil,
|
234
819
|
optional: false
|
235
820
|
)
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
message || "#{as} is not an instance of #{class_name(expected)}",
|
245
|
-
caller(1..-1)
|
821
|
+
assert_instance_of(
|
822
|
+
value,
|
823
|
+
as:,
|
824
|
+
error_class: ArgumentError,
|
825
|
+
expected:,
|
826
|
+
message:,
|
827
|
+
optional:
|
828
|
+
)
|
246
829
|
end
|
247
830
|
|
248
831
|
# Asserts that the value matches the expected object using #===.
|
249
832
|
#
|
250
|
-
# @param value [Object]
|
251
|
-
# @param as [String]
|
252
|
-
# @param expected [#===]
|
253
|
-
# @param message [String]
|
254
|
-
# @param optional [true, false]
|
833
|
+
# @param value [Object] the value to assert on.
|
834
|
+
# @param as [String] the name of the asserted value.
|
835
|
+
# @param expected [#===] the expected object.
|
836
|
+
# @param message [String] the exception message to raise on a failure.
|
837
|
+
# @param optional [true, false] if true, allows nil values.
|
838
|
+
#
|
839
|
+
# @return [void]
|
255
840
|
#
|
256
|
-
# @raise ArgumentError if the value does not match the expected object.
|
257
|
-
|
841
|
+
# @raise [ArgumentError] if the value does not match the expected object.
|
842
|
+
#
|
843
|
+
# @example
|
844
|
+
# Assertions.validate_matches('bar', expected: /foo/)
|
845
|
+
# #=> raises an ArgumentError with message 'value does not match the pattern /foo/'
|
846
|
+
#
|
847
|
+
# Assertions.validate_matches('foo', expected: /foo/)
|
848
|
+
# #=> does not raise an exception
|
849
|
+
def validate_matches(
|
258
850
|
value,
|
259
851
|
expected:,
|
260
852
|
as: 'value',
|
261
853
|
message: nil,
|
262
854
|
optional: false
|
263
855
|
)
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
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)
|
856
|
+
assert_matches(
|
857
|
+
value,
|
858
|
+
as:,
|
859
|
+
error_class: ArgumentError,
|
860
|
+
expected:,
|
861
|
+
message:,
|
862
|
+
optional:
|
863
|
+
)
|
280
864
|
end
|
281
865
|
|
282
866
|
# Asserts that the value is a non-empty String or Symbol.
|
283
867
|
#
|
284
|
-
# @param value [Object]
|
285
|
-
# @param as [String]
|
286
|
-
# @param message [String]
|
287
|
-
# @param optional [true, false]
|
868
|
+
# @param value [Object] the value to assert on.
|
869
|
+
# @param as [String] the name of the asserted value.
|
870
|
+
# @param message [String] the exception message to raise on a failure.
|
871
|
+
# @param optional [true, false] if true, allows nil values.
|
872
|
+
#
|
873
|
+
# @return [void]
|
288
874
|
#
|
289
|
-
# @raise ArgumentError if the value is not a String or a Symbol, or if the
|
875
|
+
# @raise [ArgumentError] if the value is not a String or a Symbol, or if the
|
290
876
|
# value is empty.
|
291
|
-
|
877
|
+
#
|
878
|
+
# @example
|
879
|
+
# Assertions.validate_name(nil)
|
880
|
+
# #=> raises an ArgumentError with message "value can't be blank"
|
881
|
+
#
|
882
|
+
# Assertions.validate_name(Object.new)
|
883
|
+
# #=> raises an AssertionError with message 'value is not a String or a Symbol'
|
884
|
+
#
|
885
|
+
# Assertions.validate_name('')
|
886
|
+
# #=> raises an ArgumentError with message "value can't be blank"
|
887
|
+
#
|
888
|
+
# Assertions.validate_name('foo')
|
889
|
+
# #=> does not raise an exception
|
890
|
+
#
|
891
|
+
# Assertions.validate_name(:bar)
|
892
|
+
# #=> does not raise an exception
|
893
|
+
def validate_name(
|
292
894
|
value,
|
293
895
|
as: 'value',
|
294
896
|
message: nil,
|
295
897
|
optional: false
|
296
898
|
)
|
297
|
-
|
298
|
-
|
899
|
+
assert_name(
|
900
|
+
value,
|
901
|
+
as:,
|
902
|
+
error_class: ArgumentError,
|
903
|
+
message:,
|
904
|
+
optional:
|
905
|
+
)
|
906
|
+
end
|
299
907
|
|
300
|
-
|
301
|
-
|
908
|
+
# Asserts that the value is nil.
|
909
|
+
#
|
910
|
+
# @param value [Object] the value to assert on.
|
911
|
+
# @param as [String] the name of the asserted value.
|
912
|
+
# @param message [String] the exception message to raise on a failure.
|
913
|
+
#
|
914
|
+
# @return [void]
|
915
|
+
#
|
916
|
+
# @raise [ArgumentError] if the value is not nil.
|
917
|
+
#
|
918
|
+
# @example
|
919
|
+
# Assertions.validate_nil(nil)
|
920
|
+
# #=> does not raise an exception
|
921
|
+
#
|
922
|
+
# Assertions.validate_nil(Object.new)
|
923
|
+
# #=> raises an ArgumentError with message 'value must be nil'
|
924
|
+
def validate_nil(
|
925
|
+
value,
|
926
|
+
as: 'value',
|
927
|
+
message: nil
|
928
|
+
)
|
929
|
+
assert_nil(
|
930
|
+
value,
|
931
|
+
as:,
|
932
|
+
error_class: ArgumentError,
|
933
|
+
message:
|
934
|
+
)
|
935
|
+
end
|
302
936
|
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
937
|
+
# Asserts that the value is not nil.
|
938
|
+
#
|
939
|
+
# @param value [Object] the value to assert on.
|
940
|
+
# @param as [String] the name of the asserted value.
|
941
|
+
# @param message [String] the exception message to raise on a failure.
|
942
|
+
#
|
943
|
+
# @return [void]
|
944
|
+
#
|
945
|
+
# @raise [ArgumentError] if the value is nil.
|
946
|
+
#
|
947
|
+
# @example
|
948
|
+
# Assertions.validate_not_nil(nil)
|
949
|
+
# #=> raises an ArgumentError with message 'value must not be nil'
|
950
|
+
#
|
951
|
+
# Assertions.validate_not_nil(Object.new)
|
952
|
+
# #=> does not raise an exception
|
953
|
+
def validate_not_nil(
|
954
|
+
value,
|
955
|
+
as: 'value',
|
956
|
+
message: nil
|
957
|
+
)
|
958
|
+
assert_not_nil(
|
959
|
+
value,
|
960
|
+
as:,
|
961
|
+
error_class: ArgumentError,
|
962
|
+
message:
|
963
|
+
)
|
964
|
+
end
|
965
|
+
|
966
|
+
# Asserts that the value is not nil and not empty.
|
967
|
+
#
|
968
|
+
# @param value [Object] the value to assert on.
|
969
|
+
# @param as [String] the name of the asserted value.
|
970
|
+
# @param message [String] the exception message to raise on a failure.
|
971
|
+
# @param optional [true, false] if true, allows nil values.
|
972
|
+
#
|
973
|
+
# @return [void]
|
974
|
+
#
|
975
|
+
# @raise [ArgumentError] if the value is nil, or if the value responds to
|
976
|
+
# #empty? and value.empty is true.
|
977
|
+
#
|
978
|
+
# @example
|
979
|
+
# Assertions.validate_presence(nil)
|
980
|
+
# #=> raises an ArgumentError with message "can't be blank"
|
981
|
+
#
|
982
|
+
# Assertions.validate_presence(Object.new)
|
983
|
+
# #=> does not raise an exception
|
984
|
+
#
|
985
|
+
# Assertions.validate_presence([])
|
986
|
+
# #=> raises an ArgumentError with message "can't be blank"
|
987
|
+
#
|
988
|
+
# Assertions.validate_presence([1, 2, 3])
|
989
|
+
# #=> does not raise an exception
|
990
|
+
def validate_presence(value, as: 'value', message: nil, optional: false)
|
991
|
+
assert_presence(
|
992
|
+
value,
|
993
|
+
as:,
|
994
|
+
error_class: ArgumentError,
|
995
|
+
message:,
|
996
|
+
optional:
|
997
|
+
)
|
998
|
+
end
|
999
|
+
|
1000
|
+
private
|
1001
|
+
|
1002
|
+
def error_message_for_instance_of(expected:, **options) # rubocop:disable Metrics/MethodLength
|
1003
|
+
if expected.name
|
1004
|
+
return error_message_for(
|
1005
|
+
'sleeping_king_studios.tools.assertions.instance_of',
|
1006
|
+
expected:,
|
1007
|
+
**options
|
1008
|
+
)
|
307
1009
|
end
|
308
1010
|
|
309
|
-
|
1011
|
+
error_message_for(
|
1012
|
+
'sleeping_king_studios.tools.assertions.instance_of_anonymous',
|
1013
|
+
expected:,
|
1014
|
+
parent: expected.ancestors.find(&:name),
|
1015
|
+
**options
|
1016
|
+
)
|
1017
|
+
end
|
310
1018
|
|
311
|
-
|
1019
|
+
def error_message_for_matches(expected:, **options) # rubocop:disable Metrics/MethodLength
|
1020
|
+
case expected
|
1021
|
+
when Module
|
1022
|
+
error_message_for_instance_of(expected:, **options)
|
1023
|
+
when Proc
|
1024
|
+
error_message_for(
|
1025
|
+
'sleeping_king_studios.tools.assertions.matches_proc',
|
1026
|
+
**options
|
1027
|
+
)
|
1028
|
+
when Regexp
|
1029
|
+
error_message_for(
|
1030
|
+
'sleeping_king_studios.tools.assertions.matches_regexp',
|
1031
|
+
pattern: expected.inspect,
|
1032
|
+
**options
|
1033
|
+
)
|
1034
|
+
else
|
1035
|
+
error_message_for(
|
1036
|
+
'sleeping_king_studios.tools.assertions.matches',
|
1037
|
+
**options
|
1038
|
+
)
|
1039
|
+
end
|
312
1040
|
end
|
313
1041
|
|
314
|
-
|
1042
|
+
def handle_error(error_class:, message:)
|
1043
|
+
raise error_class, message, caller(2..)
|
1044
|
+
end
|
315
1045
|
|
316
|
-
def
|
317
|
-
return
|
1046
|
+
def join_error_message(as:, message:)
|
1047
|
+
return message unless as
|
318
1048
|
|
319
|
-
"#{
|
1049
|
+
"#{as} #{message}"
|
320
1050
|
end
|
321
1051
|
end
|
322
1052
|
end
|