literal 0.2.1 → 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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.1"
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.1
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
@@ -91,8 +95,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
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