data_model 0.4.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +8 -2
  3. data/.solargraph.yml +22 -0
  4. data/Gemfile.lock +71 -29
  5. data/Rakefile +0 -6
  6. data/Steepfile +27 -0
  7. data/data_model.gemspec +1 -2
  8. data/lib/data_model/boolean.rb +0 -2
  9. data/lib/data_model/builtin/array.rb +32 -25
  10. data/lib/data_model/builtin/big_decimal.rb +15 -14
  11. data/lib/data_model/builtin/boolean.rb +10 -7
  12. data/lib/data_model/builtin/date.rb +15 -12
  13. data/lib/data_model/builtin/float.rb +14 -13
  14. data/lib/data_model/builtin/hash.rb +109 -36
  15. data/lib/data_model/builtin/integer.rb +14 -13
  16. data/lib/data_model/builtin/numeric.rb +35 -0
  17. data/lib/data_model/builtin/object.rb +28 -0
  18. data/lib/data_model/builtin/or.rb +73 -0
  19. data/lib/data_model/builtin/string.rb +15 -16
  20. data/lib/data_model/builtin/symbol.rb +14 -13
  21. data/lib/data_model/builtin/time.rb +17 -14
  22. data/lib/data_model/builtin.rb +9 -9
  23. data/lib/data_model/error.rb +30 -18
  24. data/lib/data_model/errors.rb +79 -55
  25. data/lib/data_model/fixtures/array.rb +22 -9
  26. data/lib/data_model/fixtures/big_decimal.rb +9 -7
  27. data/lib/data_model/fixtures/boolean.rb +5 -5
  28. data/lib/data_model/fixtures/date.rb +13 -11
  29. data/lib/data_model/fixtures/example.rb +7 -7
  30. data/lib/data_model/fixtures/float.rb +9 -7
  31. data/lib/data_model/fixtures/hash.rb +22 -10
  32. data/lib/data_model/fixtures/integer.rb +9 -7
  33. data/lib/data_model/fixtures/numeric.rb +31 -0
  34. data/lib/data_model/fixtures/object.rb +27 -0
  35. data/lib/data_model/fixtures/or.rb +29 -0
  36. data/lib/data_model/fixtures/string.rb +15 -32
  37. data/lib/data_model/fixtures/symbol.rb +9 -7
  38. data/lib/data_model/fixtures/time.rb +13 -11
  39. data/lib/data_model/logging.rb +5 -8
  40. data/lib/data_model/model.rb +11 -8
  41. data/lib/data_model/registry.rb +37 -22
  42. data/lib/data_model/scanner.rb +23 -28
  43. data/lib/data_model/struct.rb +116 -0
  44. data/lib/data_model/testing/minitest.rb +33 -9
  45. data/lib/data_model/testing.rb +0 -2
  46. data/lib/data_model/type.rb +38 -22
  47. data/lib/data_model/version.rb +1 -3
  48. data/lib/data_model.rb +8 -17
  49. metadata +13 -26
  50. data/sorbet/config +0 -4
  51. data/sorbet/rbi/annotations/rainbow.rbi +0 -269
  52. data/sorbet/rbi/gems/minitest@5.18.0.rbi +0 -1491
  53. data/sorbet/rbi/gems/zeitwerk.rbi +0 -196
  54. data/sorbet/rbi/gems/zeitwerk@2.6.7.rbi +0 -966
  55. data/sorbet/rbi/todo.rbi +0 -5
  56. data/sorbet/tapioca/config.yml +0 -13
  57. data/sorbet/tapioca/require.rb +0 -4
@@ -1,34 +1,37 @@
1
- # typed: strict
2
-
3
1
  module DataModel
4
- # Error is a class that holds errors.
2
+ # Error is a class that holds errors. Errors are a tuple of [name, ctx]
3
+ # - name is a symbol that identifies the error
4
+ # - ctx is contextual information about the error which can be used to build an error message
5
+ #
6
+ # The error object is a structured way to store, modify, and add errors in that intermediary format.
7
+ # To turn an error into a human readable message, use #to_messages, which delegates to a registry
8
+ #
9
+ # Base errors are errors that are related to the object as a whole, and not to any specific child
10
+ # Child errors are errors that are related to a specific child of the object, which may or may not apply depending on the type
5
11
  class Error
6
- extend T::Sig
7
12
  include Errors
8
13
 
9
- TErrorList = T.type_alias { T::Array[TError] }
10
- TErrorMap = T.type_alias { T::Hash[Symbol, TErrorList] }
11
-
12
- sig { void }
14
+ # Create a new error Object
15
+ # @return [Error] the new error object
13
16
  def initialize
14
- @base = T.let([], TErrorList)
15
- @children = T.let({}, TErrorMap)
17
+ @base = []
18
+ @children = {}
16
19
  end
17
20
 
18
21
  # errors related to the object as a whole
19
- sig { returns(TErrorList) }
22
+ # @return [Array<Array(Symbol, untyped)>] the base errors
20
23
  def base
21
24
  return @base
22
25
  end
23
26
 
24
27
  # errors related children
25
- sig { returns(TErrorMap) }
28
+ # @return [Hash{Symbol => Array<Array(Symbol, untyped)>}] the child errors
26
29
  def children
27
30
  return @children
28
31
  end
29
32
 
30
33
  # all errors
31
- sig { returns(TErrorMap) }
34
+ # @return [Hash{Symbol => Array<Array(Symbol, untyped)>}] all errors
32
35
  def all
33
36
  return children.merge(base:)
34
37
  end
@@ -36,7 +39,8 @@ module DataModel
36
39
  alias to_h all
37
40
 
38
41
  # Returns true if any errors are present.
39
- sig { params(blk: T.nilable(T.proc.params(error: TError).returns(T::Boolean))).returns(T::Boolean) }
42
+ # @param blk [Proc] an optional block to filter errors, takes an Array(Symbol, untyped) and returns boolean
43
+ # @return [Boolean] true if any errors are present
40
44
  def any?(&blk)
41
45
  if !blk
42
46
  return !@base.empty? || !@children.empty?
@@ -54,13 +58,16 @@ module DataModel
54
58
  return any
55
59
  end
56
60
 
57
- sig { returns(T::Boolean) }
61
+ # Returns true if no errors are present.
62
+ # @return [Boolean] true if no errors are present
58
63
  def empty?
59
64
  !any?
60
65
  end
61
66
 
62
67
  # Add an error to the error list.
63
- sig { params(err: TError, child: T.nilable(T.any(Symbol, T::Array[Symbol]))).void }
68
+ # @param err [Array(Symbol, untyped)] the error to add
69
+ # @param child [Symbol, Array(Symbol)] the child to add the error to. child can be an array of symbols to specify a path if nested
70
+ # @return [void]
64
71
  def add(err, child: nil)
65
72
  if child.is_a?(Array)
66
73
  child = child.join(".").to_sym
@@ -74,7 +81,10 @@ module DataModel
74
81
  errs.push(err)
75
82
  end
76
83
 
77
- sig { params(name: Symbol, child: Error).void }
84
+ # Merge another error object into this one for child Errors
85
+ # @param name [Symbol] the name of the child
86
+ # @param child [Error] the child error object
87
+ # @return [void]
78
88
  def merge_child(name, child)
79
89
  if !child.any?
80
90
  return
@@ -87,7 +97,9 @@ module DataModel
87
97
  end
88
98
  end
89
99
 
90
- sig { params(registry: Registry).returns(T::Hash[Symbol, T::Array[String]]) }
100
+ # Get human readable error messages from error tuples
101
+ # @param registry [Registry] the registry to use to get error messages
102
+ # @return [Hash{Symbol => Array[String]}] the error messages
91
103
  def to_messages(registry: Registry.instance)
92
104
  return registry.error_messages(self)
93
105
  end
@@ -1,84 +1,96 @@
1
- # typed: strict
2
-
3
1
  module DataModel
4
2
  # Provide Error building functionality as a mixin
5
3
  module Errors
6
- include Kernel
7
- extend T::Sig
8
4
  extend self
9
5
 
10
- TTemporal = T.type_alias { T.any(::Date, ::Time, ::DateTime) }
11
-
12
6
  ## Constructors
13
7
 
14
8
  # Type error applies when a value is not of the expected type
15
- sig { params(cls: T.class_of(Object), value: Object).returns(TError) }
9
+ # @param cls [String, Array(String)] the expected class
10
+ # @param value [Object] the value that failed
11
+ # @return [Array(Symbol, untyped)] the error
16
12
  def type_error(cls, value)
17
13
  [:type, [cls, value]]
18
14
  end
19
15
 
20
16
  # Coerce error applies when a value cannot be coerced to the expected type
21
- sig { params(cls: T.class_of(Object), value: Object).returns(TError) }
17
+ # @param cls [String] the expected class
18
+ # @param value [Object] the value that failed
19
+ # @return [Array(Symbol, untyped)] the error
22
20
  def coerce_error(cls, value)
23
21
  [:coerce, [cls, value]]
24
22
  end
25
23
 
26
24
  # Missing error applies when a value is missing
27
- sig { params(cls: T.class_of(Object)).returns(TError) }
25
+ # @param cls [String, Array<String>] the expected class
26
+ # @return [Array(Symbol, untyped)] the error
28
27
  def missing_error(cls)
29
28
  [:missing, cls]
30
29
  end
31
30
 
32
31
  # Inclusion error applies when a value is not in a set of allowed values
33
- sig { params(set: T::Array[T.any(Symbol, String)]).returns(TError) }
32
+ # @param set [Array<Symbol, String>] the set of allowed values
33
+ # @return [Array(Symbol, untyped)] the error
34
34
  def inclusion_error(set)
35
35
  [:inclusion, set]
36
36
  end
37
37
 
38
38
  # Exclusive error applies when a value is in a set of disallowed values
39
- sig { params(set: T::Array[T.any(Symbol, String)]).returns(TError) }
39
+ # @param set [Array<Symbol, String>] the set of disallowed values
40
+ # @return [Array(Symbol, untyped)] the error
40
41
  def exclusion_error(set)
41
42
  [:exclusion, set]
42
43
  end
43
44
 
44
45
  # Blank error applies when a value is blank
45
- sig { returns(TError) }
46
+ # @return [Array(Symbol, untyped)] the error
46
47
  def blank_error
47
48
  [:blank, nil]
48
49
  end
49
50
 
50
51
  # Extra keys error applies when a hash has extra keys
51
- sig { params(keys: T::Array[Symbol]).returns(TError) }
52
+ # @param keys [Array<Symbol>] the extra keys
53
+ # @return [Array(Symbol, untyped)] the error
52
54
  def extra_keys_error(keys)
53
55
  [:extra_keys, keys]
54
56
  end
55
57
 
56
58
  # Min applies when value is less then the minimum
57
- sig { params(min: Numeric, val: Numeric).returns(TError) }
59
+ # @param min [Numeric] the minimum value
60
+ # @param val [Numeric] the value that failed
61
+ # @return [Array(Symbol, untyped)] the error
58
62
  def min_error(min, val)
59
63
  [:min, [min, val]]
60
64
  end
61
65
 
62
66
  # Max applies when value is less then the minimum
63
- sig { params(min: Numeric, val: Numeric).returns(TError) }
67
+ # @param min [Numeric] the minimum value
68
+ # @param val [Numeric] the value that failed
69
+ # @return [Array(Symbol, untyped)] the error
64
70
  def max_error(min, val)
65
71
  [:max, [min, val]]
66
72
  end
67
73
 
68
74
  # Earliest applies when value is earlier then earliest
69
- sig { params(earliest: TTemporal, val: TTemporal).returns(TError) }
75
+ # @param earliest [Date, Time] the earliest value
76
+ # @param val [Date, Time] the value that failed
77
+ # @return [Array(Symbol, untyped)] the error
70
78
  def earliest_error(earliest, val)
71
79
  [:earliest, [earliest, val]]
72
80
  end
73
81
 
74
82
  # Latest applies when value is earlier then earliest
75
- sig { params(latest: TTemporal, val: TTemporal).returns(TError) }
83
+ # @param latest [Date, Time] the latest value
84
+ # @param val [Date, Time] the value that failed
85
+ # @return [Array(Symbol, untyped)] the error
76
86
  def latest_error(latest, val)
77
87
  [:latest, [latest, val]]
78
88
  end
79
89
 
80
90
  # Format applies when value does not match a format
81
- sig { params(format: Object, val: String).returns(TError) }
91
+ # @param format [Object] the format
92
+ # @param val [String] the value that failed
93
+ # @return [Array(Symbol, untyped)] the error
82
94
  def format_error(format, val)
83
95
  [:format, [format, val]]
84
96
  end
@@ -86,139 +98,151 @@ module DataModel
86
98
  ## Messages
87
99
 
88
100
  # Generate a message for a type error
89
- sig { params(cls: T.class_of(Object), value: Object).returns(String) }
101
+ # @param cls [String] the expected class
102
+ # @param value [Object] the value that failed
103
+ # @return [String] the message
90
104
  def type_error_message(cls, value)
91
- "#{value.inspect} is not a #{cls.name}, it is a #{value.class.name}"
105
+ names = Array(cls).join(" or ")
106
+ "#{value.inspect} is not a #{names}, it is a #{value.class.name}"
92
107
  end
93
108
 
94
109
  # Generate a message for a coerce error
95
- sig { params(cls: T.class_of(Object), value: Object).returns(String) }
110
+ # @param cls [String] the expected class
111
+ # @param value [Object] the value that failed
112
+ # @return [String] the message
96
113
  def coerce_error_message(cls, value)
97
- "cannot be coerced to #{cls.name}, it is a #{value.class.name}"
114
+ names = Array(cls).join(" or ")
115
+ "cannot be coerced to #{names}, it is a #{value.class.name}"
98
116
  end
99
117
 
100
118
  # Generate a message for a missing error
101
- sig { params(cls: T.class_of(Object)).returns(String) }
119
+ # @param cls [String, Array<String>] the expected class
120
+ # @return [String] the message
102
121
  def missing_error_message(cls)
103
- "missing value, expected a #{cls.name}"
122
+ names = Array(cls).join(" or ")
123
+ "missing value, expected a #{names}"
104
124
  end
105
125
 
106
126
  # Generate a message for an inclusion error
107
- sig { params(set: T::Array[Symbol]).returns(String) }
127
+ # @param set [Array<Symbol, String>] the set of allowed values
128
+ # @return [String] the message
108
129
  def inclusion_error_message(set)
109
130
  "must be one of #{set.join(', ')}"
110
131
  end
111
132
 
112
133
  # Generate a message for an exclusion error
113
- sig { params(set: T::Array[Symbol]).returns(String) }
134
+ # @param set [Array<Symbol, String>] the set of disallowed values
135
+ # @return [String] the message
114
136
  def exclusion_error_message(set)
115
137
  "must not be one of #{set.join(', ')}"
116
138
  end
117
139
 
118
140
  # Generate a message for a blank error
119
- sig { returns(String) }
141
+ # @return [String] the message
120
142
  def blank_error_message
121
143
  "cannot be blank"
122
144
  end
123
145
 
124
146
  # Generate a message for an extra keys error
125
- sig { params(keys: T::Array[Symbol]).returns(String) }
147
+ # @param keys [Array<Symbol>] the extra keys
148
+ # @return [String] the message
126
149
  def extra_keys_error_message(keys)
127
150
  "more elements found in closed hash then specified children: #{keys.join(', ')}"
128
151
  end
129
152
 
130
153
  # Generate a message for a min error
131
- sig { params(min: Numeric, val: Numeric).returns(String) }
154
+ # @param min [Numeric] the minimum value
155
+ # @param val [Numeric] the value that failed
156
+ # @return [String] the message
132
157
  def min_error_message(min, val)
133
158
  "value is less than the minimum of #{min}, it is #{val}"
134
159
  end
135
160
 
136
161
  # Generate a message for a min error
137
- sig { params(max: Numeric, val: Numeric).returns(String) }
162
+ # @param max [Numeric] the maximum value
163
+ # @param val [Numeric] the value that failed
164
+ # @return [String] the message
138
165
  def max_error_message(max, val)
139
166
  "value is more than the maximum of #{max}, it is #{val}"
140
167
  end
141
168
 
142
169
  # Generate a message for a value that occurs earlier then the specified earliest point
143
- sig { params(earliest: TTemporal, val: TTemporal).returns(String) }
170
+ # @param earliest [Date, Time] the earliest value
171
+ # @param val [Date, Time] the value that failed
172
+ # @return [String] the message
144
173
  def early_error_message(earliest, val)
145
174
  "value #{val} is before #{earliest}"
146
175
  end
147
176
 
148
177
  # Generate a message for a value that occurs later then the specified latest point
149
- sig { params(latest: TTemporal, val: TTemporal).returns(String) }
178
+ # @param latest [Date, Time] the latest value
179
+ # @param val [Date, Time] the value that failed
180
+ # @return [String] the message
150
181
  def late_error_message(latest, val)
151
182
  "value #{val} is after #{latest}"
152
183
  end
153
184
 
154
185
  # Generate a message for a value that does not match the format
155
- sig { params(format: Object, val: String).returns(String) }
186
+ # @param format [Object] the format
187
+ # @param val [String] the value that failed
188
+ # @return [String] the message
156
189
  def format_error_message(format, val)
157
190
  "value #{val} does not match format #{format}"
158
191
  end
159
192
 
160
193
  # Builders
161
194
 
162
- TErrorMessageBuilder = T.type_alias { T.proc.params(ctx: T.untyped).returns(String) }
163
- TErrorMessages = T.type_alias { T::Hash[Symbol, TErrorMessageBuilder] }
164
- TClassValueCtx = T.type_alias { [T.class_of(Object), Object] }
165
- TClassCtx = T.type_alias { T.class_of(Object) }
166
- TSetCtx = T.type_alias { T::Array[Symbol] }
167
- TWithinCtx = T.type_alias { [Numeric, Numeric] }
168
- TWithinTemporalCtx = T.type_alias { [Errors::TTemporal, Errors::TTemporal] }
169
- TFormatCtx = T.type_alias { [Object, String] }
170
-
171
195
  # Get the error message builders
172
- sig { returns(TErrorMessages) }
173
- def self.error_messages
196
+ # @return [Hash{Symbol => Proc}] the error message builders
197
+ def error_messages
174
198
  return {
175
199
  type: lambda do |ctx|
176
- cls, val = T.let(ctx, TClassValueCtx)
200
+ cls, val = ctx
177
201
  type_error_message(cls, val)
178
202
  end,
179
203
 
180
204
  coerce: lambda do |ctx|
181
- cls, val = T.let(ctx, TClassValueCtx)
205
+ cls, val = ctx
182
206
  type_error_message(cls, val)
183
207
  end,
184
208
 
185
209
  missing: lambda do |ctx|
186
- cls = T.let(ctx, TClassCtx)
210
+ cls = ctx
187
211
  missing_error_message(cls)
188
212
  end,
189
213
 
190
214
  inclusion: lambda do |ctx|
191
- set = T.let(ctx, TSetCtx)
215
+ set = ctx
192
216
  inclusion_error_message(set)
193
217
  end,
194
218
 
195
219
  exclusion: lambda do |ctx|
196
- set = T.let(ctx, TSetCtx)
220
+ set = ctx
197
221
  exclusion_error_message(set)
198
222
  end,
199
223
 
200
224
  extra_keys: lambda do |ctx|
201
- set = T.let(ctx, TSetCtx)
225
+ set = ctx
202
226
  extra_keys_error_message(set)
203
227
  end,
204
228
 
205
229
  min: lambda do |ctx|
206
- min, val = T.let(ctx, TWithinCtx)
230
+ min, val = ctx
207
231
  min_error_message(min, val)
208
232
  end,
209
233
 
210
234
  max: lambda do |ctx|
211
- max, val = T.let(ctx, TWithinCtx)
235
+ max, val = ctx
212
236
  max_error_message(max, val)
213
237
  end,
214
238
 
215
239
  earliest: lambda do |ctx|
216
- earliest, val = T.let(ctx, TWithinTemporalCtx)
240
+ earliest, val = ctx
217
241
  early_error_message(earliest, val)
218
242
  end,
219
243
 
220
244
  latest: lambda do |ctx|
221
- latest, val = T.let(ctx, TWithinTemporalCtx)
245
+ latest, val = ctx
222
246
  late_error_message(latest, val)
223
247
  end,
224
248
 
@@ -227,7 +251,7 @@ module DataModel
227
251
  end,
228
252
 
229
253
  format: lambda do |ctx|
230
- format, val = T.let(ctx, TFormatCtx)
254
+ format, val = ctx
231
255
  format_error_message(format, val)
232
256
  end
233
257
  }
@@ -1,12 +1,22 @@
1
- # typed: strict
2
-
3
1
  module DataModel
2
+ # test fixtures for array type
4
3
  module Fixtures::Array
5
4
  extend self
6
- extend T::Sig
7
5
  include Fixtures
8
6
 
9
- sig { returns(Example) }
7
+ # a simple array of any types
8
+ # @return [Example] the example
9
+ def any_array
10
+ Example.new(
11
+ [:array],
12
+ variants: {
13
+ mixed: ["a", 2, [], ::Object.new]
14
+ },
15
+ )
16
+ end
17
+
18
+ # a simple array of strings example
19
+ # @return [Example] the example
10
20
  def string_array
11
21
  Example.new(
12
22
  [:array, :string],
@@ -16,12 +26,13 @@ module DataModel
16
26
  number: [1, ["1"]],
17
27
  missing: nil,
18
28
  numbers: [[1, 2, 3], ["1", "2", "3"]],
19
- other_type: Object.new
29
+ other_type: ::Object.new
20
30
  },
21
31
  )
22
32
  end
23
33
 
24
- sig { returns(Example) }
34
+ # a simple array of strings that wraps single values
35
+ # @return [Example] the example
25
36
  def wrapping_string_array
26
37
  Example.new(
27
38
  [:array, { wrap_single_value: true }, :string],
@@ -31,12 +42,13 @@ module DataModel
31
42
  number: [1, ["1"]],
32
43
  missing: nil,
33
44
  numbers: [[1, 2, 3], ["1", "2", "3"]],
34
- other_type: Object.new
45
+ other_type: ::Object.new
35
46
  },
36
47
  )
37
48
  end
38
49
 
39
- sig { returns(Example) }
50
+ # an optional example
51
+ # @return [Example] the example
40
52
  def optional_string_array
41
53
  Example.new(
42
54
  [:array, { optional: true }, :string],
@@ -47,7 +59,8 @@ module DataModel
47
59
  )
48
60
  end
49
61
 
50
- sig { returns(Example) }
62
+ # an array of optional strings
63
+ # @return [Example] the example
51
64
  def array_optional_string
52
65
  Example.new(
53
66
  [:array, [:string, { optional: true }]],
@@ -1,14 +1,13 @@
1
- # typed: strict
2
-
3
1
  require "bigdecimal/util"
4
2
 
5
3
  module DataModel
4
+ # test fixtures for BigDecimal
6
5
  module Fixtures::BigDecimal
7
6
  include Fixtures
8
- extend T::Sig
9
7
  extend self
10
8
 
11
- sig { returns(Example) }
9
+ # a simple decimal example
10
+ # @return [Example] the example
12
11
  def simple
13
12
  Example.new(
14
13
  [:decimal],
@@ -20,7 +19,8 @@ module DataModel
20
19
  )
21
20
  end
22
21
 
23
- sig { returns(Example) }
22
+ # a decimal example that is optional
23
+ # @return [Example] the example
24
24
  def optional
25
25
  Example.new(
26
26
  [:decimal, { optional: true }],
@@ -30,7 +30,8 @@ module DataModel
30
30
  )
31
31
  end
32
32
 
33
- sig { returns(Example) }
33
+ # a decimal example that has a restriction on the minimum value
34
+ # @return [Example] the example
34
35
  def min
35
36
  Example.new(
36
37
  [:decimal, { min: 5 }],
@@ -41,7 +42,8 @@ module DataModel
41
42
  )
42
43
  end
43
44
 
44
- sig { returns(Example) }
45
+ # a decimal example that has a restriction on the maximum value
46
+ # @return [Example] the example
45
47
  def max
46
48
  Example.new(
47
49
  [:decimal, { max: 5 }],
@@ -1,12 +1,11 @@
1
- # typed: strict
2
-
3
1
  module DataModel
2
+ # test fixtures for boolean type
4
3
  module Fixtures::Boolean
5
- extend T::Sig
6
4
  extend self
7
5
  include Fixtures
8
6
 
9
- sig { returns(Example) }
7
+ # a simple boolean example
8
+ # @return [Example] the example
10
9
  def simple
11
10
  Example.new(
12
11
  [:boolean],
@@ -19,7 +18,8 @@ module DataModel
19
18
  )
20
19
  end
21
20
 
22
- sig { returns(Example) }
21
+ # a boolean example that is optional
22
+ # @return [Example] the example
23
23
  def optional
24
24
  Example.new(
25
25
  [:boolean, { optional: true }],
@@ -1,22 +1,20 @@
1
- # typed: strict
2
-
3
1
  module DataModel
2
+ # Provides fixtures for testing date types
4
3
  module Fixtures::Date
5
- extend T::Sig
6
- extend self
7
4
  include Fixtures
5
+ extend self
8
6
 
9
- sig { returns(::Date) }
7
+ # @return [Date] a date that is used by the #earliest example
10
8
  def earliest_date
11
9
  return ::Date.today - 1
12
10
  end
13
11
 
14
- sig { returns(::Date) }
12
+ # @return [Date] a date that is used by the #latest example
15
13
  def latest_date
16
14
  return ::Date.today + 1
17
15
  end
18
16
 
19
- sig { returns(T::Hash[Symbol, Object]) }
17
+ # @return [Hash{Symbol => untyped}] the variants used by each example
20
18
  def variants
21
19
  today = ::Date.today
22
20
 
@@ -30,22 +28,26 @@ module DataModel
30
28
  }
31
29
  end
32
30
 
33
- sig { returns(Example) }
31
+ # A simple date schema
32
+ # @return [Example] the example
34
33
  def simple
35
34
  Example.new([:date], variants:)
36
35
  end
37
36
 
38
- sig { returns(Example) }
37
+ # A date schema that is optional
38
+ # @return [Example] the example
39
39
  def optional
40
40
  Example.new([:date, { optional: true }], variants:)
41
41
  end
42
42
 
43
- sig { returns(Example) }
43
+ # A date schema that has a restriction on the earliest date
44
+ # @return [Example] the example
44
45
  def earliest
45
46
  Example.new([:date, { earliest: earliest_date }], variants:)
46
47
  end
47
48
 
48
- sig { returns(Example) }
49
+ # A date schema that has a restriction on the latest date
50
+ # @return [Example] the example
49
51
  def latest
50
52
  Example.new([:date, { latest: latest_date }], variants:)
51
53
  end
@@ -1,21 +1,21 @@
1
- # typed: strict
2
-
3
1
  module DataModel
2
+ # A simple abstraction to handle test data
4
3
  class Fixtures::Example
5
- extend T::Sig
6
-
7
- sig { params(schema: TSchema, variants: T::Hash[::Symbol, Object]).void }
4
+ # @param schema [Array] the schema
5
+ # @param variants [Hash{Symbol => untyped}] the variants used by each example
6
+ # @return [Schema] the schema
8
7
  def initialize(schema, variants:)
9
8
  @schema = schema
10
9
  @variants = variants
11
10
  end
12
11
 
13
- sig { returns(Model) }
12
+ # @return [Model] the model
14
13
  def model
15
14
  DataModel.define(@schema)
16
15
  end
17
16
 
18
- sig { params(type: Symbol).returns([Model, Object]) }
17
+ # @param type [Symbol] the variant to use
18
+ # @return [Array(Model, untyped)] a tuple of [model, variant]
19
19
  def [](type)
20
20
  if !@variants.key?(type)
21
21
  raise "#{type} is not a defined variant: #{@variants}"