class Dry::Types::Hash::Schema
@see Dry::Types::Default::Callable#evaluate
@see Dry::Types::Default#evaluate
(see {Schema#resolve_missing_value})
Basic {Schema} evaluates default values for keys missing in input hash
hashes with explicit schemas and coercible values using the built-in types.
The built-in Hash type has constructors that you can use to define
def call(hash)
-
(Hash{Symbol => Object})
-
Parameters:
-
hash
(Hash
) --
def call(hash) coerce(hash) end
def coerce(hash)
-
(Hash{Symbol => Object})
-
Parameters:
-
hash
(Hash
) --
def coerce(hash) resolve(hash) do |type, key, value| begin type.call(value) rescue ConstraintError => e raise SchemaError.new(key, value, e.result) rescue TypeError, ArgumentError => e raise SchemaError.new(key, value, e.message) end end end
def initialize(_primitive, **options)
(**options)
-
:key_transform_fn
(String
) -- -
:member_types
(Hash{Symbol => Definition}
) --
Parameters:
-
options
(Hash
) -- -
_primitive
(Class
) --
def initialize(_primitive, **options) @member_types = options.fetch(:member_types) meta = options[:meta] || EMPTY_HASH key_fn = meta.fetch(:key_transform_fn, NO_TRANSFORM) @transform_key = Dry::Types::FnContainer[key_fn] super end
def resolve(hash)
def resolve(hash) result = {} hash.each do |key, value| k = transform_key.(key) if member_types.key?(k) result[k] = yield(member_types[k], k, value) elsif strict? raise UnknownKeysError.new(*unexpected_keys(hash.keys)) end end if result.size < member_types.size resolve_missing_keys(result, &Proc.new) end result end
def resolve_missing_keys(result)
def resolve_missing_keys(result) member_types.each do |k, type| next if result.key?(k) if type.default? result[k] = yield(type, k, Undefined) elsif !type.meta[:omittable] raise MissingKeyError, k end end end
def schema(type_map)
-
(Schema)
-
Parameters:
-
type_map
({Symbol => Definition}
) --
def schema(type_map) member_types = self.member_types.merge(transform_types(type_map)) Schema.new(primitive, **options, member_types: member_types, meta: meta) end
def strict
-
(Schema)
-
def strict meta(strict: true) end
def strict?
-
(Boolean)
-
def strict? meta.fetch(:strict, false) end
def to_ast(meta: true)
-
(Array)
- An AST representation
Parameters:
-
meta
(Boolean
) -- Whether to dump the meta to the AST
def to_ast(meta: true) [ :hash_schema, [ member_types.map { |name, member| [:member, [name, member.to_ast(meta: meta)]] }, meta ? self.meta : EMPTY_HASH ] ] end
def try(hash)
-
(Object)
- if coercion fails and a block is given -
(Logic::Result)
-
Other tags:
- Yieldreturn: -
Other tags:
- Yieldparam: failure -
Parameters:
-
hash
(Hash
) --
def try(hash) if hash.is_a?(::Hash) success = true output = {} begin result = try_coerce(hash) do |key, member_result| success &&= member_result.success? output[key] = member_result.input member_result end rescue ConstraintError, UnknownKeysError, SchemaError, MissingKeyError => e success = false result = e end else success = false output = hash result = "#{hash} must be a hash" end if success success(output) else failure = failure(output, result) block_given? ? yield(failure) : failure end end
def try_coerce(hash)
-
(Hash{Symbol => Object})
-
Parameters:
-
hash
(Hash
) --
def try_coerce(hash) resolve(hash) do |type, key, value| yield(key, type.try(value)) end end
def unexpected_keys(keys)
-
(Array
-)
Parameters:
-
keys
(Array
) --
def unexpected_keys(keys) keys.map(&transform_key) - member_types.keys end
def valid?(hash)
-
(Boolean)
-
Parameters:
-
hash
(Hash
) --
def valid?(hash) result = try(hash) result.success? end
def with_key_transform(proc = nil, &block)
-
(Schema)
-
Parameters:
-
block
(#call, nil
) -- -
proc
(#call, nil
) --
def with_key_transform(proc = nil, &block) fn = proc || block if fn.nil? raise ArgumentError, "a block or callable argument is required" end handle = Dry::Types::FnContainer.register(fn) meta(key_transform_fn: handle) end