literal 0.2.0 → 1.0.0.rc1

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.
data/lib/literal/types.rb CHANGED
@@ -33,68 +33,144 @@ module Literal::Types
33
33
  autoload :UnionType, "literal/types/union_type"
34
34
  autoload :VoidType, "literal/types/void_type"
35
35
 
36
- # Matches any value except `nil`. Use `_Nilable(_Any)` or `_Void` to match any value including `nil`.
36
+ NilableBooleanType = NilableType.new(BooleanType)
37
+ NilableCallableType = NilableType.new(CallableType)
38
+ NilableJSONDataType = NilableType.new(JSONDataType)
39
+ NilableLambdaType = NilableType.new(LambdaType)
40
+ NilableProcableType = NilableType.new(ProcableType)
41
+
42
+ # Matches any value except `nil`. Use `_Any?` or `_Unit` to match any value including `nil`.
37
43
  def _Any
38
- Literal::Types::AnyType
44
+ AnyType
45
+ end
46
+
47
+ def _Any?
48
+ VoidType
39
49
  end
40
50
 
41
51
  # Matches if the value is an `Array` and all the elements match the given type.
42
52
  def _Array(...)
43
- Literal::Types::ArrayType.new(...)
53
+ ArrayType.new(...)
54
+ end
55
+
56
+ # Nilable version of `_Array`
57
+ def _Array?(...)
58
+ NilableType.new(
59
+ ArrayType.new(...),
60
+ )
44
61
  end
45
62
 
46
63
  # Matches if the value is `true` or `false`.
47
64
  def _Boolean
48
- Literal::Types::BooleanType
65
+ BooleanType
66
+ end
67
+
68
+ # Nilable version of `_Boolean`
69
+ def _Boolean?
70
+ NilableBooleanType
49
71
  end
50
72
 
51
73
  # Matches if the value responds to `#call`.
52
74
  def _Callable
53
- Literal::Types::CallableType
75
+ CallableType
76
+ end
77
+
78
+ # Nilabl version of `_Callable`
79
+ def _Callable?
80
+ NilableCallableType
54
81
  end
55
82
 
56
83
  # Matches if the value either the given class or a subclass of it.
57
84
  def _Class(...)
58
- Literal::Types::ClassType.new(...)
85
+ ClassType.new(...)
86
+ end
87
+
88
+ # Nilable version of `_Class`
89
+ def _Class?(...)
90
+ NilableType.new(
91
+ ClassType.new(...),
92
+ )
59
93
  end
60
94
 
61
95
  # Similar to `_Intersection`, but allows you to specify attribute constraints as keyword arguments.
62
96
  # @example
63
97
  # _Constraint(Array, size: 1..3)
64
98
  def _Constraint(...)
65
- Literal::Types::ConstraintType.new(...)
99
+ ConstraintType.new(...)
100
+ end
101
+
102
+ # Nilable version of `_Constraint`
103
+ def _Constraint?(...)
104
+ NilableType.new(
105
+ ConstraintType.new(...),
106
+ )
66
107
  end
67
108
 
68
109
  # Matches if the value is a descendant of the given class.
69
110
  def _Descendant(...)
70
- Literal::Types::DescendantType.new(...)
111
+ DescendantType.new(...)
112
+ end
113
+
114
+ # Nilable version of `_Descendant`
115
+ def _Descendant?(...)
116
+ NilableType.new(
117
+ DescendantType.new(...),
118
+ )
71
119
  end
72
120
 
73
121
  #  Matches if the value is an `Enumerable` and all its elements match the given type.
74
122
  def _Enumerable(...)
75
- Literal::Types::EnumerableType.new(...)
123
+ EnumerableType.new(...)
124
+ end
125
+
126
+ # Nilable version of `_Enumerable`
127
+ def _Enumerable?(...)
128
+ NilableType.new(
129
+ EnumerableType.new(...),
130
+ )
76
131
  end
77
132
 
78
133
  # Matches *"falsy"* values (`nil` and `false`).
79
134
  def _Falsy
80
- Literal::Types::FalsyType
135
+ FalsyType
81
136
  end
82
137
 
83
138
  # Matches if the value is a `Float` and matches the given constraint.
84
139
  # You could use a `Range`, for example, as a constraint.
85
140
  # If you don't need a constraint, use `Float` instead of `_Float`.
86
141
  def _Float(...)
87
- Literal::Types::FloatType.new(...)
142
+ FloatType.new(...)
143
+ end
144
+
145
+ # Nilable version of `_Float`
146
+ def _Float?(...)
147
+ NilableType.new(
148
+ FloatType.new(...),
149
+ )
88
150
  end
89
151
 
90
152
  # Matches if the value is *frozen*.
91
153
  def _Frozen(...)
92
- Literal::Types::FrozenType.new(...)
154
+ FrozenType.new(...)
155
+ end
156
+
157
+ # Nilable version of `_Frozen`
158
+ def _Frozen?(...)
159
+ NilableType.new(
160
+ FrozenType.new(...),
161
+ )
93
162
  end
94
163
 
95
164
  # Matches if the value is a `Hash` and all the keys and values match the given types.
96
165
  def _Hash(...)
97
- Literal::Types::HashType.new(...)
166
+ HashType.new(...)
167
+ end
168
+
169
+ # Nilable version of `_Hash`
170
+ def _Hash?
171
+ NilableType.new(
172
+ HashType.new,
173
+ )
98
174
  end
99
175
 
100
176
  # Matches if the value is an `Integer` and matches the given constraint.
@@ -103,95 +179,189 @@ module Literal::Types
103
179
  # @example
104
180
  # attribute :age, _Integer(18..127)
105
181
  def _Integer(...)
106
- Literal::Types::IntegerType.new(...)
182
+ IntegerType.new(...)
183
+ end
184
+
185
+ # Nilable version of `_Integer`
186
+ def _Integer?(...)
187
+ NilableType.new(
188
+ IntegerType(...),
189
+ )
107
190
  end
108
191
 
109
192
  # Matches if the value responds to all the given methods.
110
193
  def _Interface(...)
111
- Literal::Types::InterfaceType.new(...)
194
+ InterfaceType.new(...)
195
+ end
196
+
197
+ # Nilable version of `_Interface`
198
+ def _Interface?(...)
199
+ NilableType.new(
200
+ InterfaceType.new(...),
201
+ )
112
202
  end
113
203
 
114
204
  # Matches if *all* given types are matched.
115
205
  def _Intersection(...)
116
- Literal::Types::IntersectionType.new(...)
206
+ IntersectionType.new(...)
207
+ end
208
+
209
+ # Nilable version of `_Intersection`
210
+ def _Intersection?(...)
211
+ NilableType.new(
212
+ IntersectionType.new(...),
213
+ )
117
214
  end
118
215
 
119
216
  # Ensures the value is valid JSON data (i.e. it came from JSON.parse).
120
217
  def _JSONData
121
- Literal::Types::JSONDataType
218
+ JSONDataType
219
+ end
220
+
221
+ # Nilable version of `_JSONData`
222
+ def _JSONData?
223
+ NilableJSONDataType
122
224
  end
123
225
 
124
226
  # Matches if the value is a `Proc` and `#lambda?` returns truthy.
125
227
  def _Lambda
126
- Literal::Types::LambdaType
228
+ LambdaType
229
+ end
230
+
231
+ # Nilable version of `_Lambda`
232
+ def _Lambda?
233
+ NilableLambdaType
127
234
  end
128
235
 
129
236
  def _Map(...)
130
- Literal::Types::MapType.new(...)
237
+ MapType.new(...)
238
+ end
239
+
240
+ # Nilable version of `_Map`
241
+ def _Map?(...)
242
+ NilableType.new(
243
+ MapType.new(...),
244
+ )
131
245
  end
132
246
 
133
247
  # Never matches any value.
134
248
  def _Never
135
- Literal::Types::NeverType
249
+ NeverType
136
250
  end
137
251
 
138
252
  # Matches if the value is either `nil` or the given type.
139
253
  def _Nilable(...)
140
- Literal::Types::NilableType.new(...)
254
+ NilableType.new(...)
141
255
  end
142
256
 
143
257
  # Matches if the given type is *not* matched.
144
258
  def _Not(...)
145
- Literal::Types::NotType.new(...)
259
+ NotType.new(...)
146
260
  end
147
261
 
148
262
  # Matches if the value is a `Proc` or responds to `#to_proc`.
149
263
  def _Procable
150
- Literal::Types::ProcableType
264
+ ProcableType
265
+ end
266
+
267
+ # Nilable version ofo `_Procable`
268
+ def _Procable?
269
+ NilableProcableType
151
270
  end
152
271
 
153
272
  # Matches if the value is a `Range` of the given type.
154
273
  def _Range(...)
155
- Literal::Types::RangeType.new(...)
274
+ RangeType.new(...)
275
+ end
276
+
277
+ # Nilable version of `_Range`
278
+ def _Range?(...)
279
+ NilableType.new(
280
+ RangeType.new(...),
281
+ )
156
282
  end
157
283
 
158
284
  # Matches if the value is a `Set` and all the elements match the given type.
159
285
  def _Set(...)
160
- Literal::Types::SetType.new(...)
286
+ SetType.new(...)
287
+ end
288
+
289
+ # Nilable version of `_Set`
290
+ def _Set?(...)
291
+ NilableType.new(
292
+ SetType.new(...),
293
+ )
161
294
  end
162
295
 
163
296
  # Ensures a value matches the given shape of a Hash
164
297
  def _Shape(...)
165
- Literal::Types::ShapeType.new(...)
298
+ ShapeType.new(...)
299
+ end
300
+
301
+ # Nilable version of `_Shape`
302
+ def _Shape?(...)
303
+ NilableType.new(
304
+ ShapeType.new(...),
305
+ )
166
306
  end
167
307
 
308
+ # Nilable version of `_Shape`
309
+
168
310
  # Matches if the value is a `String` and matches the given constraints.
169
311
  # If you don't need any constraints, use `String` instead of `_String`.
170
312
  def _String(...)
171
- Literal::Types::StringType.new(...)
313
+ StringType.new(...)
314
+ end
315
+
316
+ # Nilable version of `_String`
317
+ def _String?(...)
318
+ NilableType.new(
319
+ StringType.new(...),
320
+ )
172
321
  end
173
322
 
174
323
  # Matches if the value is a `Symbol` and matches the given constraint.
175
324
  def _Symbol(...)
176
- Literal::Types::SymbolType.new(...)
325
+ SymbolType.new(...)
326
+ end
327
+
328
+ # Nilable version of `_Symbol`
329
+ def _Symbol?(...)
330
+ NilableType.new(
331
+ SymbolType.new(...),
332
+ )
177
333
  end
178
334
 
179
335
  # Matches *"truthy"* values (anything except `nil` and `false`).
180
336
  def _Truthy
181
- Literal::Types::TruthyType
337
+ TruthyType
182
338
  end
183
339
 
184
340
  # Matches if the value is an `Array` and each element matches the given types in order.
185
341
  def _Tuple(...)
186
- Literal::Types::TupleType.new(...)
342
+ TupleType.new(...)
343
+ end
344
+
345
+ # Nilable version of `_Typle`
346
+ def _Tuple?(...)
347
+ NilableType.new(
348
+ TupleType.new(...),
349
+ )
187
350
  end
188
351
 
189
352
  # Matches if *any* given type is matched.
190
353
  def _Union(...)
191
- Literal::Types::UnionType.new(...)
354
+ UnionType.new(...)
355
+ end
356
+
357
+ # Nilable version of `_Union`
358
+ def _Union?(...)
359
+ NilableType.new(
360
+ UnionType.new(...),
361
+ )
192
362
  end
193
363
 
194
364
  def _Void
195
- Literal::Types::VoidType
365
+ VoidType
196
366
  end
197
367
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Literal
4
- VERSION = "0.2.0"
4
+ VERSION = "1.0.0.rc1"
5
5
  end
data/lib/literal.rb CHANGED
@@ -25,11 +25,16 @@ module Literal
25
25
  end
26
26
  end
27
27
 
28
- def self.check(value, type)
29
- if TYPE_CHECKS_DISABLED || type === value
28
+ def self.check(actual:, expected:)
29
+ if expected === actual
30
30
  true
31
31
  else
32
- raise Literal::TypeError.expected(value, to_be_a: type)
32
+ context = Literal::TypeError::Context.new(expected:, actual:)
33
+ expected.record_literal_type_errors(context) if expected.respond_to?(:record_literal_type_errors)
34
+ yield context if block_given?
35
+ raise Literal::TypeError.new(context:)
33
36
  end
34
37
  end
35
38
  end
39
+
40
+ require_relative "literal/rails" if defined?(Rails)
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: literal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 1.0.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joel Drapper
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-06-30 00:00:00.000000000 Z
11
+ date: 2024-10-26 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: ''
13
+ description: Enums, properties, generics, structured objects.
14
14
  email:
15
15
  - joel@drapper.me
16
16
  executables: []
@@ -20,7 +20,6 @@ files:
20
20
  - LICENSE.txt
21
21
  - README.md
22
22
  - lib/literal.rb
23
- - lib/literal.test.rb
24
23
  - lib/literal/data.rb
25
24
  - lib/literal/data_property.rb
26
25
  - lib/literal/data_structure.rb
@@ -34,6 +33,11 @@ files:
34
33
  - lib/literal/properties/data_schema.rb
35
34
  - lib/literal/properties/schema.rb
36
35
  - lib/literal/property.rb
36
+ - lib/literal/rails.rb
37
+ - lib/literal/rails/enum_serializer.rb
38
+ - lib/literal/rails/enum_type.rb
39
+ - lib/literal/rails/patches/active_record.rb
40
+ - lib/literal/railtie.rb
37
41
  - lib/literal/struct.rb
38
42
  - lib/literal/types.rb
39
43
  - lib/literal/types/any_type.rb
@@ -84,15 +88,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
84
88
  requirements:
85
89
  - - ">="
86
90
  - !ruby/object:Gem::Version
87
- version: '3.2'
91
+ version: '3.1'
88
92
  required_rubygems_version: !ruby/object:Gem::Requirement
89
93
  requirements:
90
94
  - - ">="
91
95
  - !ruby/object:Gem::Version
92
96
  version: '0'
93
97
  requirements: []
94
- rubygems_version: 3.5.13
98
+ rubygems_version: 3.5.18
95
99
  signing_key:
96
100
  specification_version: 4
97
- summary: A literal Ruby gem
101
+ summary: A literal Ruby gem.
98
102
  test_files: []
data/lib/literal.test.rb DELETED
@@ -1,5 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- test do
4
- expect(Literal::VERSION).to_be_a String
5
- end