data_model 0.4.0 → 0.6.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.
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}"