stannum 0.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 +7 -0
- data/CHANGELOG.md +21 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/DEVELOPMENT.md +105 -0
- data/LICENSE +22 -0
- data/README.md +1327 -0
- data/config/locales/en.rb +47 -0
- data/lib/stannum/attribute.rb +115 -0
- data/lib/stannum/constraint.rb +65 -0
- data/lib/stannum/constraints/absence.rb +42 -0
- data/lib/stannum/constraints/anything.rb +28 -0
- data/lib/stannum/constraints/base.rb +285 -0
- data/lib/stannum/constraints/boolean.rb +33 -0
- data/lib/stannum/constraints/delegator.rb +71 -0
- data/lib/stannum/constraints/enum.rb +64 -0
- data/lib/stannum/constraints/equality.rb +47 -0
- data/lib/stannum/constraints/hashes/extra_keys.rb +126 -0
- data/lib/stannum/constraints/hashes/indifferent_key.rb +74 -0
- data/lib/stannum/constraints/hashes.rb +11 -0
- data/lib/stannum/constraints/identity.rb +46 -0
- data/lib/stannum/constraints/nothing.rb +28 -0
- data/lib/stannum/constraints/presence.rb +42 -0
- data/lib/stannum/constraints/signature.rb +92 -0
- data/lib/stannum/constraints/signatures/map.rb +17 -0
- data/lib/stannum/constraints/signatures/tuple.rb +17 -0
- data/lib/stannum/constraints/signatures.rb +11 -0
- data/lib/stannum/constraints/tuples/extra_items.rb +84 -0
- data/lib/stannum/constraints/tuples.rb +10 -0
- data/lib/stannum/constraints/type.rb +113 -0
- data/lib/stannum/constraints/types/array_type.rb +148 -0
- data/lib/stannum/constraints/types/big_decimal_type.rb +16 -0
- data/lib/stannum/constraints/types/date_time_type.rb +16 -0
- data/lib/stannum/constraints/types/date_type.rb +16 -0
- data/lib/stannum/constraints/types/float_type.rb +14 -0
- data/lib/stannum/constraints/types/hash_type.rb +205 -0
- data/lib/stannum/constraints/types/hash_with_indifferent_keys.rb +21 -0
- data/lib/stannum/constraints/types/hash_with_string_keys.rb +21 -0
- data/lib/stannum/constraints/types/hash_with_symbol_keys.rb +21 -0
- data/lib/stannum/constraints/types/integer_type.rb +14 -0
- data/lib/stannum/constraints/types/nil_type.rb +20 -0
- data/lib/stannum/constraints/types/proc_type.rb +14 -0
- data/lib/stannum/constraints/types/string_type.rb +14 -0
- data/lib/stannum/constraints/types/symbol_type.rb +14 -0
- data/lib/stannum/constraints/types/time_type.rb +14 -0
- data/lib/stannum/constraints/types.rb +25 -0
- data/lib/stannum/constraints/union.rb +85 -0
- data/lib/stannum/constraints.rb +26 -0
- data/lib/stannum/contract.rb +243 -0
- data/lib/stannum/contracts/array_contract.rb +108 -0
- data/lib/stannum/contracts/base.rb +597 -0
- data/lib/stannum/contracts/builder.rb +72 -0
- data/lib/stannum/contracts/definition.rb +74 -0
- data/lib/stannum/contracts/hash_contract.rb +136 -0
- data/lib/stannum/contracts/indifferent_hash_contract.rb +78 -0
- data/lib/stannum/contracts/map_contract.rb +199 -0
- data/lib/stannum/contracts/parameters/arguments_contract.rb +185 -0
- data/lib/stannum/contracts/parameters/keywords_contract.rb +174 -0
- data/lib/stannum/contracts/parameters/signature_contract.rb +29 -0
- data/lib/stannum/contracts/parameters.rb +15 -0
- data/lib/stannum/contracts/parameters_contract.rb +530 -0
- data/lib/stannum/contracts/tuple_contract.rb +213 -0
- data/lib/stannum/contracts.rb +19 -0
- data/lib/stannum/errors.rb +730 -0
- data/lib/stannum/messages/default_strategy.rb +124 -0
- data/lib/stannum/messages.rb +25 -0
- data/lib/stannum/parameter_validation.rb +216 -0
- data/lib/stannum/rspec/match_errors.rb +17 -0
- data/lib/stannum/rspec/match_errors_matcher.rb +93 -0
- data/lib/stannum/rspec/validate_parameter.rb +23 -0
- data/lib/stannum/rspec/validate_parameter_matcher.rb +506 -0
- data/lib/stannum/rspec.rb +8 -0
- data/lib/stannum/schema.rb +131 -0
- data/lib/stannum/struct.rb +444 -0
- data/lib/stannum/support/coercion.rb +114 -0
- data/lib/stannum/support/optional.rb +69 -0
- data/lib/stannum/support.rb +8 -0
- data/lib/stannum/version.rb +57 -0
- data/lib/stannum.rb +27 -0
- metadata +216 -0
@@ -0,0 +1,530 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'stannum/contracts'
|
4
|
+
|
5
|
+
require 'stannum/support/coercion'
|
6
|
+
|
7
|
+
module Stannum::Contracts
|
8
|
+
# A Parameters defines constraints on the parameters for a block or method.
|
9
|
+
#
|
10
|
+
# The ParametersContract requires that the actual object matched be a Hash
|
11
|
+
# with the following keys: :arguments, with an Array value; :keywords, with a
|
12
|
+
# Hash value; and :block, with a value of either a Proc or nil.
|
13
|
+
#
|
14
|
+
# For the arguments constraints, the contract verifies that the correct number
|
15
|
+
# of arguments are given and that each argument matches the type or constraint
|
16
|
+
# specified. If the contract has a variadic arguments constraint, then each
|
17
|
+
# variadic (or "splatted") argument is checked against the type or constraint.
|
18
|
+
#
|
19
|
+
# For the keywords constraints, the contract verifies that the expected
|
20
|
+
# keywords are given and that each keyword value matches the type or
|
21
|
+
# constraint specified. If the contract has a variadic keywords constraint,
|
22
|
+
# then each variadic keyword value is checked against the type or constraint.
|
23
|
+
#
|
24
|
+
# For the block constraint, the contract specifies that the block is present,
|
25
|
+
# the block is absent, or the block matches the given constraint.
|
26
|
+
#
|
27
|
+
# @example Defining A Parameters Contract With Arguments
|
28
|
+
# contract = Stannum::Contracts::ParametersContract.new do
|
29
|
+
# argument :name, String
|
30
|
+
# argument :size, String, default: true
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# contract.matches?(
|
34
|
+
# { arguments: [], keywords: {}, block: nil }
|
35
|
+
# )
|
36
|
+
# #=> false
|
37
|
+
#
|
38
|
+
# contract.matches?(
|
39
|
+
# { arguments: [:a_symbol], keywords: {}, block: nil }
|
40
|
+
# )
|
41
|
+
# #=> false
|
42
|
+
#
|
43
|
+
# contract.matches?(
|
44
|
+
# { arguments: ['Widget', 'Small', :extra], keywords: {}, block: nil }
|
45
|
+
# )
|
46
|
+
# #=> false
|
47
|
+
#
|
48
|
+
# contract.matches?(
|
49
|
+
# { arguments: ['Widget', 'Small', :extra], keywords: {}, block: nil }
|
50
|
+
# )
|
51
|
+
# #=> false
|
52
|
+
#
|
53
|
+
# contract.matches?(
|
54
|
+
# { arguments: ['Widget'], keywords: {}, block: nil }
|
55
|
+
# )
|
56
|
+
# #=> true
|
57
|
+
#
|
58
|
+
# contract.matches?(
|
59
|
+
# { arguments: ['Widget', nil], keywords: {}, block: nil }
|
60
|
+
# )
|
61
|
+
# #=> false
|
62
|
+
#
|
63
|
+
# contract.matches?(
|
64
|
+
# { arguments: ['Widget', 'Small'], keywords: {}, block: nil }
|
65
|
+
# )
|
66
|
+
# #=> true
|
67
|
+
#
|
68
|
+
# @example Defining A Parameters Contract With Keywords
|
69
|
+
# contract = Stannum::Contracts::ParametersContract.new do
|
70
|
+
# keyword :price, String
|
71
|
+
# keyword :quantity, Integer, optional: true
|
72
|
+
# end
|
73
|
+
#
|
74
|
+
# contract.matches?(
|
75
|
+
# { arguments: [], keywords: {}, block: nil }
|
76
|
+
# )
|
77
|
+
# #=> false
|
78
|
+
#
|
79
|
+
# contract.matches?(
|
80
|
+
# arguments: [],
|
81
|
+
# keywords: {
|
82
|
+
# price: 1_000_000,
|
83
|
+
# },
|
84
|
+
# block: nil
|
85
|
+
# )
|
86
|
+
# #=> false
|
87
|
+
#
|
88
|
+
# contract.matches?(
|
89
|
+
# arguments: [],
|
90
|
+
# keywords: {
|
91
|
+
# currency: 'USD',
|
92
|
+
# price: '$1_000_000',
|
93
|
+
# },
|
94
|
+
# block: nil
|
95
|
+
# )
|
96
|
+
# #=> false
|
97
|
+
#
|
98
|
+
# contract.matches?(
|
99
|
+
# arguments: [],
|
100
|
+
# keywords: {
|
101
|
+
# price: '$1_000_000',
|
102
|
+
# },
|
103
|
+
# block: nil
|
104
|
+
# )
|
105
|
+
#
|
106
|
+
# #=> true
|
107
|
+
# contract.matches?(
|
108
|
+
# arguments: [],
|
109
|
+
# keywords: {
|
110
|
+
# price: '$1_000_000',
|
111
|
+
# quantity: 50,
|
112
|
+
# },
|
113
|
+
# block: nil
|
114
|
+
# )
|
115
|
+
# #=> true
|
116
|
+
#
|
117
|
+
# @example Defining A Parameters Contract With Variadic Arguments
|
118
|
+
# contract = Stannum::Contracts::ParametersContract.new do
|
119
|
+
# arguments :words, String
|
120
|
+
# end
|
121
|
+
#
|
122
|
+
# contract.matches?(
|
123
|
+
# { arguments: [1, 2, 3], keywords: {}, block: nil }
|
124
|
+
# )
|
125
|
+
# #=> false
|
126
|
+
#
|
127
|
+
# contract.matches?(
|
128
|
+
# { arguments: [], keywords: {}, block: nil }
|
129
|
+
# )
|
130
|
+
# #=> true
|
131
|
+
#
|
132
|
+
# contract.matches?(
|
133
|
+
# { arguments: ['foo', 'bar', 'baz'], keywords: {}, block: nil }
|
134
|
+
# )
|
135
|
+
# #=> true
|
136
|
+
#
|
137
|
+
# @example Defining A Parameters Contract With Variadic Keywords
|
138
|
+
# contract = Stannum::Contracts::ParametersContract.new do
|
139
|
+
# keywords :options, Symbol
|
140
|
+
# end
|
141
|
+
#
|
142
|
+
# contract.matches?(
|
143
|
+
# arguments: [],
|
144
|
+
# keywords: {
|
145
|
+
# price: 1_000_000,
|
146
|
+
# },
|
147
|
+
# block: nil
|
148
|
+
# )
|
149
|
+
# #=> false
|
150
|
+
#
|
151
|
+
# contract.matches?(
|
152
|
+
# arguments: [],
|
153
|
+
# keywords: {},
|
154
|
+
# block: nil
|
155
|
+
# )
|
156
|
+
# #=> true
|
157
|
+
#
|
158
|
+
# contract.matches?(
|
159
|
+
# arguments: [],
|
160
|
+
# keywords: {
|
161
|
+
# color: :red,
|
162
|
+
# shape: :triangle
|
163
|
+
# },
|
164
|
+
# block: nil
|
165
|
+
# )
|
166
|
+
# #=> true
|
167
|
+
#
|
168
|
+
# @example Defining A Parameters Contract With A Block Constraint
|
169
|
+
# contract = Stannum::Contracts::ParametersContract.new do
|
170
|
+
# block true
|
171
|
+
# end
|
172
|
+
#
|
173
|
+
# contract.matches?(
|
174
|
+
# { arguments: [], keywords: {}, block: nil }
|
175
|
+
# )
|
176
|
+
# #=> false
|
177
|
+
#
|
178
|
+
# contract.matches?(
|
179
|
+
# { arguments: [], keywords: {}, block: Proc.new }
|
180
|
+
# )
|
181
|
+
# #=> true
|
182
|
+
class ParametersContract < Stannum::Contracts::HashContract
|
183
|
+
# Builder class for defining item constraints for a ParametersContract.
|
184
|
+
#
|
185
|
+
# This class should not be invoked directly. Instead, pass a block to the
|
186
|
+
# constructor for ParametersContract.
|
187
|
+
#
|
188
|
+
# @api private
|
189
|
+
class Builder < Stannum::Contract::Builder
|
190
|
+
# Adds an argument constraint to the contract.
|
191
|
+
#
|
192
|
+
# If the index is specified, then the constraint will be added for the
|
193
|
+
# argument at the specified index. If the index is not given, then the
|
194
|
+
# constraint will be applied to the next unconstrained argument. For
|
195
|
+
# example, the first argument constraint will be added for the argument at
|
196
|
+
# index 0, the second constraint for the argument at index 1, and so on.
|
197
|
+
#
|
198
|
+
# @overload argument(name, type, index: nil, **options)
|
199
|
+
# Generates an argument constraint based on the given type. If the type
|
200
|
+
# is a constraint, then the given constraint will be copied with the
|
201
|
+
# given options and added for the argument at the index. If the type is
|
202
|
+
# a Class or a Module, then a Stannum::Constraints::Type constraint will
|
203
|
+
# be created with the given type and options and added for the argument.
|
204
|
+
#
|
205
|
+
# @param name [String, Symbol] The name of the argument.
|
206
|
+
# @param type [Class, Module, Stannum::Constraints:Base] The expected
|
207
|
+
# type of the argument.
|
208
|
+
# @param index [Integer, nil] The index of the argument. If not given,
|
209
|
+
# then the next argument will be constrained with the type.
|
210
|
+
# @param options [Hash<Symbol, Object>] Configuration options for the
|
211
|
+
# constraint. Defaults to an empty Hash.
|
212
|
+
#
|
213
|
+
# @return [Stannum::Contracts::ParametersContract::Builder] the builder.
|
214
|
+
#
|
215
|
+
# @overload argument(name, index: nil, **options, &block
|
216
|
+
# Generates a new Stannum::Constraint using the block.
|
217
|
+
#
|
218
|
+
# @param name [String, Symbol] The name of the argument.
|
219
|
+
# @param index [Integer, nil] The index of the argument. If not given,
|
220
|
+
# then the next argument will be constrained with the type.
|
221
|
+
# @param options [Hash<Symbol, Object>] Configuration options for the
|
222
|
+
# constraint. Defaults to an empty Hash.
|
223
|
+
#
|
224
|
+
# @yield The definition for the constraint. Each time #matches? is
|
225
|
+
# called for this constraint, the given object will be passed to this
|
226
|
+
# block and the result of the block will be returned.
|
227
|
+
# @yieldparam actual [Object] The object to check against the
|
228
|
+
# constraint.
|
229
|
+
# @yieldreturn [true, false] true if the given object matches the
|
230
|
+
# constraint, otherwise false.
|
231
|
+
#
|
232
|
+
# @return [Stannum::Contracts::ParametersContract::Builder] the builder.
|
233
|
+
def argument(name, type = nil, index: nil, **options, &block)
|
234
|
+
type = resolve_constraint_or_type(type, **options, &block)
|
235
|
+
|
236
|
+
contract.add_argument_constraint(
|
237
|
+
index,
|
238
|
+
type,
|
239
|
+
property_name: name,
|
240
|
+
**options
|
241
|
+
)
|
242
|
+
|
243
|
+
self
|
244
|
+
end
|
245
|
+
|
246
|
+
# Sets the variadic arguments constraint for the contract.
|
247
|
+
#
|
248
|
+
# If the parameters includes variadic (or "splatted") arguments, then each
|
249
|
+
# item in the variadic arguments array must match the given type or
|
250
|
+
# constraint. If the type is a constraint, then the given constraint will
|
251
|
+
# be copied with the given options. If the type is a Class or a Module,
|
252
|
+
# then a Stannum::Constraints::Type constraint will be created with the
|
253
|
+
# given type.
|
254
|
+
#
|
255
|
+
# @param name [String, Symbol] a human-readable name for the variadic
|
256
|
+
# arguments; used in generating error messages.
|
257
|
+
# @param type [Class, Module, Stannum::Constraints:Base] The expected type
|
258
|
+
# of the variadic arguments items.
|
259
|
+
#
|
260
|
+
# @return [Stannum::Contracts::ParametersContract::Builder] the builder.
|
261
|
+
#
|
262
|
+
# @raise [RuntimeError] if there is already a variadic arguments
|
263
|
+
# constraint defined for the contract.
|
264
|
+
def arguments(name, type)
|
265
|
+
contract.set_arguments_item_constraint(name, type)
|
266
|
+
|
267
|
+
self
|
268
|
+
end
|
269
|
+
|
270
|
+
# Sets the block parameter constraint for the contract.
|
271
|
+
#
|
272
|
+
# If the expected presence is true, a block must be given as part of the
|
273
|
+
# parameters. If the expected presence is false, a block must not be
|
274
|
+
# given. If the presence is a constraint, then the block must match the
|
275
|
+
# constraint.
|
276
|
+
#
|
277
|
+
# @param present [true, false, Stannum::Constraint] The expected presence
|
278
|
+
# of the block.
|
279
|
+
#
|
280
|
+
# @return [Stannum::Contracts::ParametersContract] the contract.
|
281
|
+
#
|
282
|
+
# @raise [RuntimeError] if there is already a block constraint defined for
|
283
|
+
# the contract.
|
284
|
+
def block(present)
|
285
|
+
contract.set_block_constraint(present)
|
286
|
+
|
287
|
+
self
|
288
|
+
end
|
289
|
+
|
290
|
+
# Adds a keyword constraint to the contract.
|
291
|
+
#
|
292
|
+
# @overload keyword(name, type, **options)
|
293
|
+
# Generates a keyword constraint based on the given type. If the type is
|
294
|
+
# a constraint, then the given constraint will be copied with the given
|
295
|
+
# options and added for the given keyword. If the type is a Class or a
|
296
|
+
# Module, then a Stannum::Constraints::Type constraint will be created
|
297
|
+
# with the given type and options and added for the keyword.
|
298
|
+
#
|
299
|
+
# @param keyword [Symbol] The keyword to constrain.
|
300
|
+
# @param type [Class, Module, Stannum::Constraints:Base] The expected
|
301
|
+
# type of the keyword.
|
302
|
+
# @param options [Hash<Symbol, Object>] Configuration options for the
|
303
|
+
# constraint. Defaults to an empty Hash.
|
304
|
+
#
|
305
|
+
# @return [Stannum::Contracts::ParametersContract::Builder] the builder.
|
306
|
+
#
|
307
|
+
# @overload keyword(name, **options, &block)
|
308
|
+
# Generates a new Stannum::Constraint using the block.
|
309
|
+
#
|
310
|
+
# @param keyword [Symbol] The keyword to constrain.
|
311
|
+
# @param options [Hash<Symbol, Object>] Configuration options for the
|
312
|
+
# constraint. Defaults to an empty Hash.
|
313
|
+
#
|
314
|
+
# @yield The definition for the constraint. Each time #matches? is
|
315
|
+
# called for this constraint, the given object will be passed to this
|
316
|
+
# block and the result of the block will be returned.
|
317
|
+
# @yieldparam actual [Object] The object to check against the
|
318
|
+
# constraint.
|
319
|
+
# @yieldreturn [true, false] true if the given object matches the
|
320
|
+
# constraint, otherwise false.
|
321
|
+
#
|
322
|
+
# @return [Stannum::Contracts::ParametersContract::Builder] the builder.
|
323
|
+
def keyword(name, type = nil, **options, &block)
|
324
|
+
type = resolve_constraint_or_type(type, **options, &block)
|
325
|
+
|
326
|
+
contract.add_keyword_constraint(
|
327
|
+
name,
|
328
|
+
type,
|
329
|
+
**options
|
330
|
+
)
|
331
|
+
|
332
|
+
self
|
333
|
+
end
|
334
|
+
|
335
|
+
# Sets the variadic keywords constraint for the contract.
|
336
|
+
#
|
337
|
+
# If the parameters includes variadic (or "splatted") keywords, then each
|
338
|
+
# value in the variadic keywords hash must match the given type or
|
339
|
+
# constraint. If the type is a constraint, then the given constraint will
|
340
|
+
# be copied with the given options. If the type is a Class or a Module,
|
341
|
+
# then a Stannum::Constraints::Type constraint will be created with the
|
342
|
+
# given type.
|
343
|
+
#
|
344
|
+
# @param name [String, Symbol] a human-readable name for the variadic
|
345
|
+
# keywords; used in generating error messages.
|
346
|
+
# @param type [Class, Module, Stannum::Constraints:Base] The expected type
|
347
|
+
# of the variadic keywords values.
|
348
|
+
#
|
349
|
+
# @return [Stannum::Contracts::ParametersContract::Builder] the builder.
|
350
|
+
#
|
351
|
+
# @raise [RuntimeError] if there is already a variadic keywords constraint
|
352
|
+
# defined for the contract.
|
353
|
+
def keywords(name, type)
|
354
|
+
contract.set_keywords_value_constraint(name, type)
|
355
|
+
|
356
|
+
self
|
357
|
+
end
|
358
|
+
|
359
|
+
private
|
360
|
+
|
361
|
+
def resolve_constraint_or_type(type = nil, **options, &block)
|
362
|
+
if block_given? && type
|
363
|
+
raise ArgumentError, ambiguous_values_error(type), caller(1..-1)
|
364
|
+
end
|
365
|
+
|
366
|
+
return type if type.is_a?(Module) || valid_constraint?(type)
|
367
|
+
|
368
|
+
return Stannum::Constraint.new(**options, &block) if block
|
369
|
+
|
370
|
+
raise ArgumentError,
|
371
|
+
"invalid constraint #{type.inspect}",
|
372
|
+
caller(1..-1)
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
# Adds an argument constraint to the contract.
|
377
|
+
#
|
378
|
+
# Generates an argument constraint based on the given type. If the type is
|
379
|
+
# a constraint, then the given constraint will be copied with the given
|
380
|
+
# options and added for the argument at the index. If the type is a Class or
|
381
|
+
# a Module, then a Stannum::Constraints::Type constraint will be created
|
382
|
+
# with the given type and options and added for the argument.
|
383
|
+
#
|
384
|
+
# If the index is specified, then the constraint will be added for the
|
385
|
+
# argument at the specified index. If the index is not given, then the
|
386
|
+
# constraint will be applied to the next unconstrained argument. For
|
387
|
+
# example, the first argument constraint will be added for the argument at
|
388
|
+
# index 0, the second constraint for the argument at index 1, and so on.
|
389
|
+
#
|
390
|
+
# @param index [Integer, nil] The index of the argument. If not given, then
|
391
|
+
# the next argument will be constrained with the type.
|
392
|
+
# @param type [Class, Module, Stannum::Constraints:Base] The expected type
|
393
|
+
# of the argument.
|
394
|
+
# @param options [Hash<Symbol, Object>] Configuration options for the
|
395
|
+
# constraint. Defaults to an empty Hash.
|
396
|
+
#
|
397
|
+
# @return [Stannum::Contracts::ParametersContract] the contract.
|
398
|
+
def add_argument_constraint(index, type, **options)
|
399
|
+
arguments_contract.add_argument_constraint(index, type, **options)
|
400
|
+
|
401
|
+
self
|
402
|
+
end
|
403
|
+
|
404
|
+
# Adds a keyword constraint to the contract.
|
405
|
+
#
|
406
|
+
# Generates a keyword constraint based on the given type. If the type is
|
407
|
+
# a constraint, then the given constraint will be copied with the given
|
408
|
+
# options and added for the given keyword. If the type is a Class or a
|
409
|
+
# Module, then a Stannum::Constraints::Type constraint will be created with
|
410
|
+
# the given type and options and added for the keyword.
|
411
|
+
#
|
412
|
+
# @param keyword [Symbol] The keyword to constrain.
|
413
|
+
# @param type [Class, Module, Stannum::Constraints:Base] The expected type
|
414
|
+
# of the argument.
|
415
|
+
# @param options [Hash<Symbol, Object>] Configuration options for the
|
416
|
+
# constraint. Defaults to an empty Hash.
|
417
|
+
#
|
418
|
+
# @return [Stannum::Contracts::ParametersContract] the contract.
|
419
|
+
def add_keyword_constraint(keyword, type, **options)
|
420
|
+
keywords_contract.add_keyword_constraint(keyword, type, **options)
|
421
|
+
|
422
|
+
self
|
423
|
+
end
|
424
|
+
|
425
|
+
# Sets the variadic arguments constraint for the contract.
|
426
|
+
#
|
427
|
+
# If the parameters includes variadic (or "splatted") arguments, then each
|
428
|
+
# item in the variadic arguments array must match the given type or
|
429
|
+
# constraint. If the type is a constraint, then the given constraint will be
|
430
|
+
# copied with the given options. If the type is a Class or a Module, then a
|
431
|
+
# Stannum::Constraints::Type constraint will be created with the given type.
|
432
|
+
#
|
433
|
+
# @param name [String, Symbol] a human-readable name for the variadic
|
434
|
+
# arguments; used in generating error messages.
|
435
|
+
# @param type [Class, Module, Stannum::Constraints:Base] The expected type
|
436
|
+
# of the variadic arguments items.
|
437
|
+
#
|
438
|
+
# @return [Stannum::Contracts::ParametersContract] the contract.
|
439
|
+
#
|
440
|
+
# @raise [RuntimeError] if there is already a variadic arguments constraint
|
441
|
+
# defined for the contract.
|
442
|
+
def set_arguments_item_constraint(name, type)
|
443
|
+
arguments_contract.set_variadic_item_constraint(type, as: name)
|
444
|
+
|
445
|
+
self
|
446
|
+
end
|
447
|
+
|
448
|
+
# Sets the block parameter constraint for the contract.
|
449
|
+
#
|
450
|
+
# If the expected presence is true, a block must be given as part of the
|
451
|
+
# parameters. If the expected presence is false, a block must not be given.
|
452
|
+
# If the presence is a constraint, then the block must match the constraint.
|
453
|
+
#
|
454
|
+
# @param present [true, false, Stannum::Constraint] The expected presence of
|
455
|
+
# the block.
|
456
|
+
#
|
457
|
+
# @return [Stannum::Contracts::ParametersContract] the contract.
|
458
|
+
#
|
459
|
+
# @raise [RuntimeError] if there is already a block constraint defined for
|
460
|
+
# the contract.
|
461
|
+
def set_block_constraint(present) # rubocop:disable Naming/AccessorMethodName
|
462
|
+
raise 'block constraint is already set' if @block_constraint
|
463
|
+
|
464
|
+
@block_constraint = build_block_constraint(present)
|
465
|
+
|
466
|
+
add_key_constraint(:block, @block_constraint)
|
467
|
+
end
|
468
|
+
|
469
|
+
# Sets the variadic keywords constraint for the contract.
|
470
|
+
#
|
471
|
+
# If the parameters includes variadic (or "splatted") keywords, then each
|
472
|
+
# value in the variadic keywords hash must match the given type or
|
473
|
+
# constraint. If the type is a constraint, then the given constraint will be
|
474
|
+
# copied with the given options. If the type is a Class or a Module, then a
|
475
|
+
# Stannum::Constraints::Type constraint will be created with the given type.
|
476
|
+
#
|
477
|
+
# @param name [String, Symbol] a human-readable name for the variadic
|
478
|
+
# keywords; used in generating error messages.
|
479
|
+
# @param type [Class, Module, Stannum::Constraints:Base] The expected type
|
480
|
+
# of the variadic keywords values.
|
481
|
+
#
|
482
|
+
# @return [Stannum::Contracts::ParametersContract] the contract.
|
483
|
+
#
|
484
|
+
# @raise [RuntimeError] if there is already a variadic keywords constraint
|
485
|
+
# defined for the contract.
|
486
|
+
def set_keywords_value_constraint(name, type)
|
487
|
+
keywords_contract.set_variadic_value_constraint(type, as: name)
|
488
|
+
|
489
|
+
self
|
490
|
+
end
|
491
|
+
|
492
|
+
private
|
493
|
+
|
494
|
+
attr_reader :block_constraint
|
495
|
+
|
496
|
+
def add_extra_keys_constraint; end
|
497
|
+
|
498
|
+
def add_type_constraint
|
499
|
+
add_constraint \
|
500
|
+
Stannum::Contracts::Parameters::SignatureContract.new,
|
501
|
+
sanity: true
|
502
|
+
end
|
503
|
+
|
504
|
+
def arguments_contract
|
505
|
+
@arguments_contract ||=
|
506
|
+
Stannum::Contracts::Parameters::ArgumentsContract.new
|
507
|
+
end
|
508
|
+
|
509
|
+
def build_block_constraint(value)
|
510
|
+
Stannum::Support::Coercion.presence_constraint(value) \
|
511
|
+
do |present, **options|
|
512
|
+
next Stannum::Constraints::Types::ProcType.new(**options) if present
|
513
|
+
|
514
|
+
Stannum::Constraints::Types::NilType.new(**options)
|
515
|
+
end
|
516
|
+
end
|
517
|
+
|
518
|
+
def define_constraints(&block)
|
519
|
+
super(&block)
|
520
|
+
|
521
|
+
add_key_constraint :arguments, arguments_contract
|
522
|
+
add_key_constraint :keywords, keywords_contract
|
523
|
+
end
|
524
|
+
|
525
|
+
def keywords_contract
|
526
|
+
@keywords_contract ||=
|
527
|
+
Stannum::Contracts::Parameters::KeywordsContract.new
|
528
|
+
end
|
529
|
+
end
|
530
|
+
end
|