stannum 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +21 -0
  3. data/CODE_OF_CONDUCT.md +132 -0
  4. data/DEVELOPMENT.md +105 -0
  5. data/LICENSE +22 -0
  6. data/README.md +1327 -0
  7. data/config/locales/en.rb +47 -0
  8. data/lib/stannum/attribute.rb +115 -0
  9. data/lib/stannum/constraint.rb +65 -0
  10. data/lib/stannum/constraints/absence.rb +42 -0
  11. data/lib/stannum/constraints/anything.rb +28 -0
  12. data/lib/stannum/constraints/base.rb +285 -0
  13. data/lib/stannum/constraints/boolean.rb +33 -0
  14. data/lib/stannum/constraints/delegator.rb +71 -0
  15. data/lib/stannum/constraints/enum.rb +64 -0
  16. data/lib/stannum/constraints/equality.rb +47 -0
  17. data/lib/stannum/constraints/hashes/extra_keys.rb +126 -0
  18. data/lib/stannum/constraints/hashes/indifferent_key.rb +74 -0
  19. data/lib/stannum/constraints/hashes.rb +11 -0
  20. data/lib/stannum/constraints/identity.rb +46 -0
  21. data/lib/stannum/constraints/nothing.rb +28 -0
  22. data/lib/stannum/constraints/presence.rb +42 -0
  23. data/lib/stannum/constraints/signature.rb +92 -0
  24. data/lib/stannum/constraints/signatures/map.rb +17 -0
  25. data/lib/stannum/constraints/signatures/tuple.rb +17 -0
  26. data/lib/stannum/constraints/signatures.rb +11 -0
  27. data/lib/stannum/constraints/tuples/extra_items.rb +84 -0
  28. data/lib/stannum/constraints/tuples.rb +10 -0
  29. data/lib/stannum/constraints/type.rb +113 -0
  30. data/lib/stannum/constraints/types/array_type.rb +148 -0
  31. data/lib/stannum/constraints/types/big_decimal_type.rb +16 -0
  32. data/lib/stannum/constraints/types/date_time_type.rb +16 -0
  33. data/lib/stannum/constraints/types/date_type.rb +16 -0
  34. data/lib/stannum/constraints/types/float_type.rb +14 -0
  35. data/lib/stannum/constraints/types/hash_type.rb +205 -0
  36. data/lib/stannum/constraints/types/hash_with_indifferent_keys.rb +21 -0
  37. data/lib/stannum/constraints/types/hash_with_string_keys.rb +21 -0
  38. data/lib/stannum/constraints/types/hash_with_symbol_keys.rb +21 -0
  39. data/lib/stannum/constraints/types/integer_type.rb +14 -0
  40. data/lib/stannum/constraints/types/nil_type.rb +20 -0
  41. data/lib/stannum/constraints/types/proc_type.rb +14 -0
  42. data/lib/stannum/constraints/types/string_type.rb +14 -0
  43. data/lib/stannum/constraints/types/symbol_type.rb +14 -0
  44. data/lib/stannum/constraints/types/time_type.rb +14 -0
  45. data/lib/stannum/constraints/types.rb +25 -0
  46. data/lib/stannum/constraints/union.rb +85 -0
  47. data/lib/stannum/constraints.rb +26 -0
  48. data/lib/stannum/contract.rb +243 -0
  49. data/lib/stannum/contracts/array_contract.rb +108 -0
  50. data/lib/stannum/contracts/base.rb +597 -0
  51. data/lib/stannum/contracts/builder.rb +72 -0
  52. data/lib/stannum/contracts/definition.rb +74 -0
  53. data/lib/stannum/contracts/hash_contract.rb +136 -0
  54. data/lib/stannum/contracts/indifferent_hash_contract.rb +78 -0
  55. data/lib/stannum/contracts/map_contract.rb +199 -0
  56. data/lib/stannum/contracts/parameters/arguments_contract.rb +185 -0
  57. data/lib/stannum/contracts/parameters/keywords_contract.rb +174 -0
  58. data/lib/stannum/contracts/parameters/signature_contract.rb +29 -0
  59. data/lib/stannum/contracts/parameters.rb +15 -0
  60. data/lib/stannum/contracts/parameters_contract.rb +530 -0
  61. data/lib/stannum/contracts/tuple_contract.rb +213 -0
  62. data/lib/stannum/contracts.rb +19 -0
  63. data/lib/stannum/errors.rb +730 -0
  64. data/lib/stannum/messages/default_strategy.rb +124 -0
  65. data/lib/stannum/messages.rb +25 -0
  66. data/lib/stannum/parameter_validation.rb +216 -0
  67. data/lib/stannum/rspec/match_errors.rb +17 -0
  68. data/lib/stannum/rspec/match_errors_matcher.rb +93 -0
  69. data/lib/stannum/rspec/validate_parameter.rb +23 -0
  70. data/lib/stannum/rspec/validate_parameter_matcher.rb +506 -0
  71. data/lib/stannum/rspec.rb +8 -0
  72. data/lib/stannum/schema.rb +131 -0
  73. data/lib/stannum/struct.rb +444 -0
  74. data/lib/stannum/support/coercion.rb +114 -0
  75. data/lib/stannum/support/optional.rb +69 -0
  76. data/lib/stannum/support.rb +8 -0
  77. data/lib/stannum/version.rb +57 -0
  78. data/lib/stannum.rb +27 -0
  79. metadata +216 -0
@@ -0,0 +1,113 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'stannum/constraints/base'
4
+ require 'stannum/support/optional'
5
+
6
+ module Stannum::Constraints
7
+ # A type constraint asserts that the object is of the expected type.
8
+ #
9
+ # @example Using a Type constraint with a Class
10
+ # constraint = Stannum::Constraints::Type.new(StandardError)
11
+ #
12
+ # constraint.matches?(nil) # => false
13
+ # constraint.matches?(Object.new) # => false
14
+ # constraint.matches?(StandardError.new) # => true
15
+ # constraint.matches?(RuntimeError.new) # => true
16
+ #
17
+ # @example Using a Type constraint with a Module
18
+ # constraint = Stannum::Constraints::Type.new(Enumerable)
19
+ #
20
+ # constraint.matches?(nil) #=> false
21
+ # constraint.matches?(Object.new) #=> false
22
+ # constraint.matches?(Array) #=> true
23
+ # constraint.matches?(Object.new.extend(Enumerable)) #=> true
24
+ #
25
+ # @example Using a Type constraint with a Class name
26
+ # constraint = Stannum::Constraints::Type.new('StandardError')
27
+ #
28
+ # constraint.matches?(nil) # => false
29
+ # constraint.matches?(Object.new) # => false
30
+ # constraint.matches?(StandardError.new) # => true
31
+ # constraint.matches?(RuntimeError.new) # => true
32
+ class Type < Stannum::Constraints::Base
33
+ include Stannum::Support::Optional
34
+
35
+ # The :type of the error generated for a matching object.
36
+ NEGATED_TYPE = 'stannum.constraints.is_type'
37
+
38
+ # The :type of the error generated for a non-matching object.
39
+ TYPE = 'stannum.constraints.is_not_type'
40
+
41
+ # @param expected_type [Class, Module, String] The type the object is
42
+ # expected to belong to. Can be a Class or a Module, or the name of a
43
+ # class or module.
44
+ # @param options [Hash<Symbol, Object>] Configuration options for the
45
+ # constraint. Defaults to an empty Hash.
46
+ def initialize(expected_type, optional: nil, required: nil, **options)
47
+ expected_type = resolve_expected_type(expected_type)
48
+
49
+ super(
50
+ expected_type: expected_type,
51
+ **resolve_required_option(
52
+ optional: optional,
53
+ required: required,
54
+ **options
55
+ )
56
+ )
57
+ end
58
+
59
+ # (see Stannum::Constraints::Base#errors_for)
60
+ def errors_for(actual, errors: nil) # rubocop:disable Lint/UnusedMethodArgument
61
+ (errors || Stannum::Errors.new).add(type, **error_properties)
62
+ end
63
+
64
+ # @return [Class, Module, String] the type the object is expected to belong
65
+ # to.
66
+ def expected_type
67
+ options[:expected_type]
68
+ end
69
+
70
+ # Checks that the object is an instance of the expected type.
71
+ #
72
+ # @return [true, false] true if the object is an instance of the expected
73
+ # type, otherwise false.
74
+ #
75
+ # @see Stannum::Constraint#matches?
76
+ def matches?(actual)
77
+ matches_type?(actual)
78
+ end
79
+ alias match? matches?
80
+
81
+ # (see Stannum::Constraints::Base#negated_errors_for)
82
+ def negated_errors_for(actual, errors: nil) # rubocop:disable Lint/UnusedMethodArgument
83
+ (errors || Stannum::Errors.new).add(negated_type, **error_properties)
84
+ end
85
+
86
+ # (see Stannum::Constraints::Base#with_options)
87
+ def with_options(**options)
88
+ options = options.merge(required_by_default: required?)
89
+
90
+ super(**resolve_required_option(**options))
91
+ end
92
+
93
+ private
94
+
95
+ def error_properties
96
+ { required: required?, type: expected_type }
97
+ end
98
+
99
+ def matches_type?(actual)
100
+ actual.is_a?(expected_type) || (optional? && actual.nil?)
101
+ end
102
+
103
+ def resolve_expected_type(type_or_name)
104
+ return type_or_name if type_or_name.is_a?(Module)
105
+
106
+ return Object.const_get(type_or_name) if type_or_name.is_a?(String)
107
+
108
+ raise ArgumentError,
109
+ 'expected type must be a Class or Module',
110
+ caller[1..-1]
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,148 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'stannum/constraints/types'
4
+ require 'stannum/support/coercion'
5
+
6
+ module Stannum::Constraints::Types
7
+ # An Array type constraint asserts that the object is an Array.
8
+ #
9
+ # @example Using an Array type constraint
10
+ # constraint = Stannum::Constraints::Types::ArrayType.new
11
+ #
12
+ # constraint.matches?(nil) # => false
13
+ # constraint.matches?(Object.new) # => false
14
+ # constraint.matches?([]) # => true
15
+ # constraint.matches?([1, 2, 3]) # => true
16
+ #
17
+ # @example Using an Array type constraint with an item constraint
18
+ # constraint = Stannum::Constraints::Types::ArrayType.new(item_type: String)
19
+ #
20
+ # constraint.matches?(nil) # => false
21
+ # constraint.matches?(Object.new) # => false
22
+ # constraint.matches?([]) # => true
23
+ # constraint.matches?([1, 2, 3]) # => false
24
+ # constraint.matches?(%w[one two three]) # => true
25
+ #
26
+ # @example Using an Array type constraint with a presence constraint
27
+ # constraint = Stannum::Constraints::Types::ArrayType.new(allow_empty: false)
28
+ #
29
+ # constraint.matches?(nil) # => false
30
+ # constraint.matches?(Object.new) # => false
31
+ # constraint.matches?([]) # => false
32
+ # constraint.matches?([1, 2, 3]) # => true
33
+ # constraint.matches?(%w[one two three]) # => true
34
+ class ArrayType < Stannum::Constraints::Type
35
+ # @param allow_empty [true, false] If false, then the constraint will not
36
+ # match against an Array with no items.
37
+ # @param item_type [Stannum::Constraints::Base, Class, nil] If set, then
38
+ # the constraint will check the types of each item in the Array against
39
+ # the expected type and will fail if any items do not match.
40
+ # @param options [Hash<Symbol, Object>] Configuration options for the
41
+ # constraint. Defaults to an empty Hash.
42
+ def initialize(allow_empty: true, item_type: nil, **options)
43
+ super(
44
+ ::Array,
45
+ allow_empty: !!allow_empty,
46
+ item_type: coerce_item_type(item_type),
47
+ **options
48
+ )
49
+ end
50
+
51
+ # @return [true, false] if false, then the constraint will not
52
+ # match against an Array with no items.
53
+ def allow_empty?
54
+ options[:allow_empty]
55
+ end
56
+
57
+ # Checks that the object is not an Array instance.
58
+ #
59
+ # @return [true, false] true if the object is not an Array instance,
60
+ # otherwise false.
61
+ #
62
+ # @see Stannum::Constraints::Types::ArrayType#matches?
63
+ def does_not_match?(actual)
64
+ !matches_type?(actual)
65
+ end
66
+
67
+ # (see Stannum::Constraints::Base#errors_for)
68
+ def errors_for(actual, errors: nil)
69
+ return super unless actual.is_a?(expected_type)
70
+
71
+ errors ||= Stannum::Errors.new
72
+
73
+ return add_presence_error(errors) unless presence_matches?(actual)
74
+
75
+ unless item_type_matches?(actual)
76
+ non_matching_items(actual).each do |item, index|
77
+ item_type.errors_for(item, errors: errors[index])
78
+ end
79
+ end
80
+
81
+ errors
82
+ end
83
+
84
+ # @return [Stannum::Constraints::Base, nil] the expected type for the items
85
+ # in the array.
86
+ def item_type
87
+ options[:item_type]
88
+ end
89
+
90
+ # Checks that the object is an Array instance and that the items match.
91
+ #
92
+ # If the constraint was configured with an item_type, each item in the Array
93
+ # will be compared to the expected type. If any items do not match the
94
+ # expectation, then #matches? will return false.
95
+ #
96
+ # @return [true, false] true if the object is an Array instance with
97
+ # matching items, otherwise false.
98
+ #
99
+ # @see Stannum::Constraints::Types::ArrayType#does_not_match?
100
+ def matches?(actual)
101
+ return false unless super
102
+
103
+ return false unless presence_matches?(actual)
104
+
105
+ return false unless item_type_matches?(actual)
106
+
107
+ true
108
+ end
109
+ alias match? matches?
110
+
111
+ private
112
+
113
+ def add_presence_error(errors)
114
+ errors.add(
115
+ Stannum::Constraints::Presence::TYPE,
116
+ **error_properties
117
+ )
118
+ end
119
+
120
+ def coerce_item_type(item_type)
121
+ Stannum::Support::Coercion.type_constraint(
122
+ item_type,
123
+ allow_nil: true,
124
+ as: 'item type'
125
+ )
126
+ end
127
+
128
+ def error_properties
129
+ super().merge(allow_empty: allow_empty?)
130
+ end
131
+
132
+ def item_type_matches?(actual)
133
+ return true unless item_type
134
+
135
+ return true if actual.nil?
136
+
137
+ actual.all? { |item| item_type.matches?(item) }
138
+ end
139
+
140
+ def non_matching_items(actual)
141
+ actual.each.with_index.reject { |item, _| item_type.matches?(item) }
142
+ end
143
+
144
+ def presence_matches?(actual)
145
+ allow_empty? || !actual.empty?
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bigdecimal'
4
+
5
+ require 'stannum/constraints/types'
6
+
7
+ module Stannum::Constraints::Types
8
+ # A BigDecimal type constraint asserts that the object is a BigDecimal.
9
+ class BigDecimalType < Stannum::Constraints::Type
10
+ # @param options [Hash<Symbol, Object>] Configuration options for the
11
+ # constraint. Defaults to an empty Hash.
12
+ def initialize(**options)
13
+ super(::BigDecimal, **options)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'date'
4
+
5
+ require 'stannum/constraints/types'
6
+
7
+ module Stannum::Constraints::Types
8
+ # A DateTimeType constraint asserts that the object is a DateTime.
9
+ class DateTimeType < Stannum::Constraints::Type
10
+ # @param options [Hash<Symbol, Object>] Configuration options for the
11
+ # constraint. Defaults to an empty Hash.
12
+ def initialize(**options)
13
+ super(::DateTime, **options)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'date'
4
+
5
+ require 'stannum/constraints/types'
6
+
7
+ module Stannum::Constraints::Types
8
+ # A DateType constraint asserts that the object is a Date.
9
+ class DateType < Stannum::Constraints::Type
10
+ # @param options [Hash<Symbol, Object>] Configuration options for the
11
+ # constraint. Defaults to an empty Hash.
12
+ def initialize(**options)
13
+ super(::Date, **options)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'stannum/constraints/types'
4
+
5
+ module Stannum::Constraints::Types
6
+ # A FloatType constraint asserts that the object is a Float.
7
+ class FloatType < Stannum::Constraints::Type
8
+ # @param options [Hash<Symbol, Object>] Configuration options for the
9
+ # constraint. Defaults to an empty Hash.
10
+ def initialize(**options)
11
+ super(::Float, **options)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,205 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'stannum/constraints/types'
4
+ require 'stannum/support/coercion'
5
+
6
+ module Stannum::Constraints::Types
7
+ # A Hash type constraint asserts that the object is a Hash.
8
+ #
9
+ # @example Using a Hash type constraint
10
+ # constraint = Stannum::Constraints::Types::HashType.new
11
+ #
12
+ # constraint.matches?(nil) # => false
13
+ # constraint.matches?(Object.new) # => false
14
+ # constraint.matches?({}) # => true
15
+ # constraint.matches?({ key: 'value' }) # => true
16
+ #
17
+ # @example Using a Hash type constraint with a key constraint
18
+ # constraint = Stannum::Constraints::Types::HashType.new(key_type: String)
19
+ #
20
+ # constraint.matches?(nil) # => false
21
+ # constraint.matches?(Object.new) # => false
22
+ # constraint.matches?({}) # => true
23
+ # constraint.matches?({ key: 'value' }) # => false
24
+ # constraint.matches?({ 'key' => 'value' }) # => true
25
+ #
26
+ # @example Using a Hash type constraint with a value constraint
27
+ # constraint = Stannum::Constraints::Types::HashType.new(value_type: String)
28
+ #
29
+ # constraint.matches?(nil) # => false
30
+ # constraint.matches?(Object.new) # => false
31
+ # constraint.matches?({}) # => true
32
+ # constraint.matches?({ key: :value }) # => false
33
+ # constraint.matches?({ key: 'value' }) # => true
34
+ #
35
+ # @example Using a Hash type constraint with a presence constraint
36
+ # constraint = Stannum::Constraints::Types::HashType.new(allow_empty: false)
37
+ #
38
+ # constraint.matches?(nil) # => false
39
+ # constraint.matches?(Object.new) # => false
40
+ # constraint.matches?({}) # => false
41
+ # constraint.matches?({ key: :value }) # => true
42
+ # constraint.matches?({ key: 'value' }) # => true
43
+ class HashType < Stannum::Constraints::Type
44
+ # @param allow_empty [true, false] If false, then the constraint will not
45
+ # match against a Hash with no keys.
46
+ # @param key_type [Stannum::Constraints::Base, Class, nil] If set, then the
47
+ # constraint will check the types of each key in the Hash against the
48
+ # expected type and will fail if any keys do not match.
49
+ # @param value_type [Stannum::Constraints::Base, Class, nil] If set, then
50
+ # the constraint will check the types of each value in the Hash against
51
+ # the expected type and will fail if any values do not match.
52
+ # @param options [Hash<Symbol, Object>] Configuration options for the
53
+ # constraint. Defaults to an empty Hash.
54
+ def initialize(allow_empty: true, key_type: nil, value_type: nil, **options)
55
+ super(
56
+ ::Hash,
57
+ allow_empty: !!allow_empty,
58
+ key_type: coerce_key_type(key_type),
59
+ value_type: coerce_value_type(value_type),
60
+ **options
61
+ )
62
+ end
63
+
64
+ # @return [true, false] if false, then the constraint will not
65
+ # match against a Hash with no keys.
66
+ def allow_empty?
67
+ options[:allow_empty]
68
+ end
69
+
70
+ # Checks that the object is not a Hash instance.
71
+ #
72
+ # @return [true, false] true if the object is not a Hash instance, otherwise
73
+ # false.
74
+ #
75
+ # @see Stannum::Constraints::Types::HashType#matches?
76
+ def does_not_match?(actual)
77
+ !matches_type?(actual)
78
+ end
79
+
80
+ # (see Stannum::Constraints::Base#errors_for)
81
+ def errors_for(actual, errors: nil)
82
+ return super unless actual.is_a?(expected_type)
83
+
84
+ errors ||= Stannum::Errors.new
85
+
86
+ return add_presence_error(errors) unless presence_matches?(actual)
87
+
88
+ update_key_errors_for(actual: actual, errors: errors)
89
+
90
+ update_value_errors_for(actual: actual, errors: errors)
91
+
92
+ errors
93
+ end
94
+
95
+ # @return [Stannum::Constraints::Base, nil] the expected type for the keys
96
+ # in the hash.
97
+ def key_type
98
+ options[:key_type]
99
+ end
100
+
101
+ # Checks that the object is a Hash instance and that the keys/values match.
102
+ #
103
+ # If the constraint was configured with a key_type, each key in the hash
104
+ # will be compared to the expected type. Likewise, if the constraint was
105
+ # configured with a value_type, each value in the hash will be compared. If
106
+ # any keys and/or values do not match the expectation, then #matches? will
107
+ # return false.
108
+ #
109
+ # @return [true, false] true if the object is a Hash instance with matching
110
+ # keys and values, otherwise false.
111
+ #
112
+ # @see Stannum::Constraints::Types::HashType#does_not_match?
113
+ def matches?(actual)
114
+ return false unless super
115
+
116
+ return false unless presence_matches?(actual)
117
+
118
+ return false unless key_type_matches?(actual)
119
+
120
+ return false unless value_type_matches?(actual)
121
+
122
+ true
123
+ end
124
+ alias match? matches?
125
+
126
+ # @return [Stannum::Constraints::Base, nil] the expected type for the values
127
+ # in the hash.
128
+ def value_type
129
+ options[:value_type]
130
+ end
131
+
132
+ private
133
+
134
+ def add_presence_error(errors)
135
+ errors.add(
136
+ Stannum::Constraints::Presence::TYPE,
137
+ **error_properties
138
+ )
139
+ end
140
+
141
+ def coerce_key_type(key_type)
142
+ Stannum::Support::Coercion.type_constraint(
143
+ key_type,
144
+ allow_nil: true,
145
+ as: 'key type'
146
+ )
147
+ end
148
+
149
+ def coerce_value_type(value_type)
150
+ Stannum::Support::Coercion.type_constraint(
151
+ value_type,
152
+ allow_nil: true,
153
+ as: 'value type'
154
+ )
155
+ end
156
+
157
+ def error_properties
158
+ super().merge(allow_empty: allow_empty?)
159
+ end
160
+
161
+ def key_type_matches?(actual)
162
+ return true unless key_type
163
+
164
+ return true if actual.nil?
165
+
166
+ actual.each_key.all? { |key| key_type.matches?(key) }
167
+ end
168
+
169
+ def non_matching_keys(actual)
170
+ return [] unless key_type && actual.is_a?(Hash)
171
+
172
+ actual.each_key.reject { |key| key_type.matches?(key) }
173
+ end
174
+
175
+ def non_matching_values(actual)
176
+ return [] unless value_type && actual.is_a?(Hash)
177
+
178
+ actual.each.reject { |_, value| value_type.matches?(value) }
179
+ end
180
+
181
+ def presence_matches?(actual)
182
+ allow_empty? || !actual.empty?
183
+ end
184
+
185
+ def update_key_errors_for(actual:, errors:)
186
+ non_matching_keys(actual).each do |key|
187
+ key_type.errors_for(key, errors: errors[:keys][key])
188
+ end
189
+ end
190
+
191
+ def update_value_errors_for(actual:, errors:)
192
+ non_matching_values(actual).each do |key, value|
193
+ value_type.errors_for(value, errors: errors[key])
194
+ end
195
+ end
196
+
197
+ def value_type_matches?(actual)
198
+ return true unless value_type
199
+
200
+ return true if actual.nil?
201
+
202
+ actual.each_value.all? { |value| value_type.matches?(value) }
203
+ end
204
+ end
205
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'stannum/constraints/types'
4
+
5
+ module Stannum::Constraints::Types
6
+ # Asserts that the object is a Hash with String or Symbol keys.
7
+ class HashWithIndifferentKeys < Stannum::Constraints::Types::HashType
8
+ # @param value_type [Stannum::Constraints::Base, Class, nil] If set, then
9
+ # the constraint will check the types of each value in the Hash against
10
+ # the expected type and will fail if any values do not match.
11
+ # @param options [Hash<Symbol, Object>] Configuration options for the
12
+ # constraint. Defaults to an empty Hash.
13
+ def initialize(value_type: nil, **options)
14
+ super(
15
+ key_type: Stannum::Constraints::Hashes::IndifferentKey.new,
16
+ value_type: coerce_value_type(value_type),
17
+ **options
18
+ )
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'stannum/constraints/types'
4
+
5
+ module Stannum::Constraints::Types
6
+ # Asserts that the object is a Hash with String keys.
7
+ class HashWithStringKeys < Stannum::Constraints::Types::HashType
8
+ # @param value_type [Stannum::Constraints::Base, Class, nil] If set, then
9
+ # the constraint will check the types of each value in the Hash against
10
+ # the expected type and will fail if any values do not match.
11
+ # @param options [Hash<Symbol, Object>] Configuration options for the
12
+ # constraint. Defaults to an empty Hash.
13
+ def initialize(value_type: nil, **options)
14
+ super(
15
+ key_type: Stannum::Constraints::Types::StringType.new,
16
+ value_type: coerce_value_type(value_type),
17
+ **options
18
+ )
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'stannum/constraints/types'
4
+
5
+ module Stannum::Constraints::Types
6
+ # Asserts that the object is a Hash with Symbol keys.
7
+ class HashWithSymbolKeys < Stannum::Constraints::Types::HashType
8
+ # @param value_type [Stannum::Constraints::Base, Class, nil] If set, then
9
+ # the constraint will check the types of each value in the Hash against
10
+ # the expected type and will fail if any values do not match.
11
+ # @param options [Hash<Symbol, Object>] Configuration options for the
12
+ # constraint. Defaults to an empty Hash.
13
+ def initialize(value_type: nil, **options)
14
+ super(
15
+ key_type: Stannum::Constraints::Types::SymbolType.new,
16
+ value_type: coerce_value_type(value_type),
17
+ **options
18
+ )
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'stannum/constraints/types'
4
+
5
+ module Stannum::Constraints::Types
6
+ # An IntegerType constraint asserts that the object is an Integer.
7
+ class IntegerType < Stannum::Constraints::Type
8
+ # @param options [Hash<Symbol, Object>] Configuration options for the
9
+ # constraint. Defaults to an empty Hash.
10
+ def initialize(**options)
11
+ super(::Integer, **options)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'stannum/constraints/types'
4
+
5
+ module Stannum::Constraints::Types
6
+ # A Nil type constraint asserts that the object is nil.
7
+ class NilType < Stannum::Constraints::Type
8
+ # The :type of the error generated for a matching object.
9
+ NEGATED_TYPE = 'stannum.constraints.types.is_nil'
10
+
11
+ # The :type of the error generated for a non-matching object.
12
+ TYPE = 'stannum.constraints.types.is_not_nil'
13
+
14
+ # @param options [Hash<Symbol, Object>] Configuration options for the
15
+ # constraint. Defaults to an empty Hash.
16
+ def initialize(**options)
17
+ super(::NilClass, **options)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'stannum/constraints/types'
4
+
5
+ module Stannum::Constraints::Types
6
+ # A Proc type constraint asserts that the object is a Proc.
7
+ class ProcType < Stannum::Constraints::Type
8
+ # @param options [Hash<Symbol, Object>] Configuration options for the
9
+ # constraint. Defaults to an empty Hash.
10
+ def initialize(**options)
11
+ super(::Proc, **options)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'stannum/constraints/types'
4
+
5
+ module Stannum::Constraints::Types
6
+ # A String type constraint asserts that the object is a String.
7
+ class StringType < Stannum::Constraints::Type
8
+ # @param options [Hash<Symbol, Object>] Configuration options for the
9
+ # constraint. Defaults to an empty Hash.
10
+ def initialize(**options)
11
+ super(::String, **options)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'stannum/constraints/types'
4
+
5
+ module Stannum::Constraints::Types
6
+ # A Symbol type constraint asserts that the object is a Symbol.
7
+ class SymbolType < Stannum::Constraints::Type
8
+ # @param options [Hash<Symbol, Object>] Configuration options for the
9
+ # constraint. Defaults to an empty Hash.
10
+ def initialize(**options)
11
+ super(::Symbol, **options)
12
+ end
13
+ end
14
+ end