lib/data_model/errors.rb in data_model-0.4.0 vs lib/data_model/errors.rb in data_model-0.5.0
- old
+ new
@@ -1,234 +1,258 @@
-# typed: strict
-
module DataModel
# Provide Error building functionality as a mixin
module Errors
- include Kernel
- extend T::Sig
extend self
- TTemporal = T.type_alias { T.any(::Date, ::Time, ::DateTime) }
-
## Constructors
# Type error applies when a value is not of the expected type
- sig { params(cls: T.class_of(Object), value: Object).returns(TError) }
+ # @param cls [String, Array(String)] the expected class
+ # @param value [Object] the value that failed
+ # @return [Array(Symbol, untyped)] the error
def type_error(cls, value)
[:type, [cls, value]]
end
# Coerce error applies when a value cannot be coerced to the expected type
- sig { params(cls: T.class_of(Object), value: Object).returns(TError) }
+ # @param cls [String] the expected class
+ # @param value [Object] the value that failed
+ # @return [Array(Symbol, untyped)] the error
def coerce_error(cls, value)
[:coerce, [cls, value]]
end
# Missing error applies when a value is missing
- sig { params(cls: T.class_of(Object)).returns(TError) }
+ # @param cls [String, Array<String>] the expected class
+ # @return [Array(Symbol, untyped)] the error
def missing_error(cls)
[:missing, cls]
end
# Inclusion error applies when a value is not in a set of allowed values
- sig { params(set: T::Array[T.any(Symbol, String)]).returns(TError) }
+ # @param set [Array<Symbol, String>] the set of allowed values
+ # @return [Array(Symbol, untyped)] the error
def inclusion_error(set)
[:inclusion, set]
end
# Exclusive error applies when a value is in a set of disallowed values
- sig { params(set: T::Array[T.any(Symbol, String)]).returns(TError) }
+ # @param set [Array<Symbol, String>] the set of disallowed values
+ # @return [Array(Symbol, untyped)] the error
def exclusion_error(set)
[:exclusion, set]
end
# Blank error applies when a value is blank
- sig { returns(TError) }
+ # @return [Array(Symbol, untyped)] the error
def blank_error
[:blank, nil]
end
# Extra keys error applies when a hash has extra keys
- sig { params(keys: T::Array[Symbol]).returns(TError) }
+ # @param keys [Array<Symbol>] the extra keys
+ # @return [Array(Symbol, untyped)] the error
def extra_keys_error(keys)
[:extra_keys, keys]
end
# Min applies when value is less then the minimum
- sig { params(min: Numeric, val: Numeric).returns(TError) }
+ # @param min [Numeric] the minimum value
+ # @param val [Numeric] the value that failed
+ # @return [Array(Symbol, untyped)] the error
def min_error(min, val)
[:min, [min, val]]
end
# Max applies when value is less then the minimum
- sig { params(min: Numeric, val: Numeric).returns(TError) }
+ # @param min [Numeric] the minimum value
+ # @param val [Numeric] the value that failed
+ # @return [Array(Symbol, untyped)] the error
def max_error(min, val)
[:max, [min, val]]
end
# Earliest applies when value is earlier then earliest
- sig { params(earliest: TTemporal, val: TTemporal).returns(TError) }
+ # @param earliest [Date, Time] the earliest value
+ # @param val [Date, Time] the value that failed
+ # @return [Array(Symbol, untyped)] the error
def earliest_error(earliest, val)
[:earliest, [earliest, val]]
end
# Latest applies when value is earlier then earliest
- sig { params(latest: TTemporal, val: TTemporal).returns(TError) }
+ # @param latest [Date, Time] the latest value
+ # @param val [Date, Time] the value that failed
+ # @return [Array(Symbol, untyped)] the error
def latest_error(latest, val)
[:latest, [latest, val]]
end
# Format applies when value does not match a format
- sig { params(format: Object, val: String).returns(TError) }
+ # @param format [Object] the format
+ # @param val [String] the value that failed
+ # @return [Array(Symbol, untyped)] the error
def format_error(format, val)
[:format, [format, val]]
end
## Messages
# Generate a message for a type error
- sig { params(cls: T.class_of(Object), value: Object).returns(String) }
+ # @param cls [String] the expected class
+ # @param value [Object] the value that failed
+ # @return [String] the message
def type_error_message(cls, value)
- "#{value.inspect} is not a #{cls.name}, it is a #{value.class.name}"
+ names = Array(cls).join(" or ")
+ "#{value.inspect} is not a #{names}, it is a #{value.class.name}"
end
# Generate a message for a coerce error
- sig { params(cls: T.class_of(Object), value: Object).returns(String) }
+ # @param cls [String] the expected class
+ # @param value [Object] the value that failed
+ # @return [String] the message
def coerce_error_message(cls, value)
- "cannot be coerced to #{cls.name}, it is a #{value.class.name}"
+ names = Array(cls).join(" or ")
+ "cannot be coerced to #{names}, it is a #{value.class.name}"
end
# Generate a message for a missing error
- sig { params(cls: T.class_of(Object)).returns(String) }
+ # @param cls [String, Array<String>] the expected class
+ # @return [String] the message
def missing_error_message(cls)
- "missing value, expected a #{cls.name}"
+ names = Array(cls).join(" or ")
+ "missing value, expected a #{names}"
end
# Generate a message for an inclusion error
- sig { params(set: T::Array[Symbol]).returns(String) }
+ # @param set [Array<Symbol, String>] the set of allowed values
+ # @return [String] the message
def inclusion_error_message(set)
"must be one of #{set.join(', ')}"
end
# Generate a message for an exclusion error
- sig { params(set: T::Array[Symbol]).returns(String) }
+ # @param set [Array<Symbol, String>] the set of disallowed values
+ # @return [String] the message
def exclusion_error_message(set)
"must not be one of #{set.join(', ')}"
end
# Generate a message for a blank error
- sig { returns(String) }
+ # @return [String] the message
def blank_error_message
"cannot be blank"
end
# Generate a message for an extra keys error
- sig { params(keys: T::Array[Symbol]).returns(String) }
+ # @param keys [Array<Symbol>] the extra keys
+ # @return [String] the message
def extra_keys_error_message(keys)
"more elements found in closed hash then specified children: #{keys.join(', ')}"
end
# Generate a message for a min error
- sig { params(min: Numeric, val: Numeric).returns(String) }
+ # @param min [Numeric] the minimum value
+ # @param val [Numeric] the value that failed
+ # @return [String] the message
def min_error_message(min, val)
"value is less than the minimum of #{min}, it is #{val}"
end
# Generate a message for a min error
- sig { params(max: Numeric, val: Numeric).returns(String) }
+ # @param max [Numeric] the maximum value
+ # @param val [Numeric] the value that failed
+ # @return [String] the message
def max_error_message(max, val)
"value is more than the maximum of #{max}, it is #{val}"
end
# Generate a message for a value that occurs earlier then the specified earliest point
- sig { params(earliest: TTemporal, val: TTemporal).returns(String) }
+ # @param earliest [Date, Time] the earliest value
+ # @param val [Date, Time] the value that failed
+ # @return [String] the message
def early_error_message(earliest, val)
"value #{val} is before #{earliest}"
end
# Generate a message for a value that occurs later then the specified latest point
- sig { params(latest: TTemporal, val: TTemporal).returns(String) }
+ # @param latest [Date, Time] the latest value
+ # @param val [Date, Time] the value that failed
+ # @return [String] the message
def late_error_message(latest, val)
"value #{val} is after #{latest}"
end
# Generate a message for a value that does not match the format
- sig { params(format: Object, val: String).returns(String) }
+ # @param format [Object] the format
+ # @param val [String] the value that failed
+ # @return [String] the message
def format_error_message(format, val)
"value #{val} does not match format #{format}"
end
# Builders
- TErrorMessageBuilder = T.type_alias { T.proc.params(ctx: T.untyped).returns(String) }
- TErrorMessages = T.type_alias { T::Hash[Symbol, TErrorMessageBuilder] }
- TClassValueCtx = T.type_alias { [T.class_of(Object), Object] }
- TClassCtx = T.type_alias { T.class_of(Object) }
- TSetCtx = T.type_alias { T::Array[Symbol] }
- TWithinCtx = T.type_alias { [Numeric, Numeric] }
- TWithinTemporalCtx = T.type_alias { [Errors::TTemporal, Errors::TTemporal] }
- TFormatCtx = T.type_alias { [Object, String] }
-
# Get the error message builders
- sig { returns(TErrorMessages) }
- def self.error_messages
+ # @return [Hash{Symbol => Proc}] the error message builders
+ def error_messages
return {
type: lambda do |ctx|
- cls, val = T.let(ctx, TClassValueCtx)
+ cls, val = ctx
type_error_message(cls, val)
end,
coerce: lambda do |ctx|
- cls, val = T.let(ctx, TClassValueCtx)
+ cls, val = ctx
type_error_message(cls, val)
end,
missing: lambda do |ctx|
- cls = T.let(ctx, TClassCtx)
+ cls = ctx
missing_error_message(cls)
end,
inclusion: lambda do |ctx|
- set = T.let(ctx, TSetCtx)
+ set = ctx
inclusion_error_message(set)
end,
exclusion: lambda do |ctx|
- set = T.let(ctx, TSetCtx)
+ set = ctx
exclusion_error_message(set)
end,
extra_keys: lambda do |ctx|
- set = T.let(ctx, TSetCtx)
+ set = ctx
extra_keys_error_message(set)
end,
min: lambda do |ctx|
- min, val = T.let(ctx, TWithinCtx)
+ min, val = ctx
min_error_message(min, val)
end,
max: lambda do |ctx|
- max, val = T.let(ctx, TWithinCtx)
+ max, val = ctx
max_error_message(max, val)
end,
earliest: lambda do |ctx|
- earliest, val = T.let(ctx, TWithinTemporalCtx)
+ earliest, val = ctx
early_error_message(earliest, val)
end,
latest: lambda do |ctx|
- latest, val = T.let(ctx, TWithinTemporalCtx)
+ latest, val = ctx
late_error_message(latest, val)
end,
blank: lambda do
blank_error_message
end,
format: lambda do |ctx|
- format, val = T.let(ctx, TFormatCtx)
+ format, val = ctx
format_error_message(format, val)
end
}
end
end