class Dry::Types::Map

Homogeneous mapping. It describes a hash with unknown keys that match a certain type.

@example

type = Dry::Types['hash'].map(
  Dry::Types['integer'].constrained(gteq: 1, lteq: 10),
  Dry::Types['string']
)

type.(1 => 'right')
# => {1 => 'right'}

type.('1' => 'wrong')
# Dry::Types::MapError: "1" violates constraints (type?(Integer, "1")
#                                                 AND gteq?(1, "1")
#                                                 AND lteq?(10, "1") failed)

type.(11 => 'wrong')
# Dry::Types::MapError: 11 violates constraints (lteq?(10, 11) failed)

@api public

Public Class Methods

new(primitive, key_type: Types["any"], value_type: Types["any"], meta: EMPTY_HASH) click to toggle source
Calls superclass method
# File lib/dry/types/map.rb, line 26
def initialize(primitive, key_type: Types["any"], value_type: Types["any"], meta: EMPTY_HASH)
  super(primitive, key_type: key_type, value_type: value_type, meta: meta)
end

Public Instance Methods

call_safe(hash) { || ... } click to toggle source

@param [Hash] hash

@return [Hash]

@api private

# File lib/dry/types/map.rb, line 67
def call_safe(hash)
  try(hash) { return yield }.input
end
call_unsafe(hash) click to toggle source

@param [Hash] hash

@return [Hash]

@api private

# File lib/dry/types/map.rb, line 56
def call_unsafe(hash)
  try(hash) { |failure|
    raise MapError, failure.error.message
  }.input
end
constrained?() click to toggle source

@return [Boolean]

@api public

# File lib/dry/types/map.rb, line 98
def constrained?
  value_type.constrained?
end
key_type() click to toggle source

@return [Type]

@api public

# File lib/dry/types/map.rb, line 33
def key_type
  options[:key_type]
end
name() click to toggle source

@return [String]

@api public

# File lib/dry/types/map.rb, line 47
def name
  "Map"
end
to_ast(meta: true) click to toggle source

@param meta [Boolean] Whether to dump the meta to the AST

@return [Array] An AST representation

@api public

# File lib/dry/types/map.rb, line 88
def to_ast(meta: true)
  [:map,
   [key_type.to_ast(meta: true),
    value_type.to_ast(meta: true),
    meta ? self.meta : EMPTY_HASH]]
end
try(hash) { |result| ... } click to toggle source

@param [Hash] hash

@return [Result]

@api public

# File lib/dry/types/map.rb, line 76
def try(hash)
  result = coerce(hash)
  return result if result.success? || !block_given?

  yield(result)
end
value_type() click to toggle source

@return [Type]

@api public

# File lib/dry/types/map.rb, line 40
def value_type
  options[:value_type]
end

Private Instance Methods

coerce(input) click to toggle source

@api private rubocop:disable Metrics/PerceivedComplexity rubocop:disable Metrics/AbcSize

# File lib/dry/types/map.rb, line 107
def coerce(input)
  unless primitive?(input)
    return failure(
      input, CoercionError.new("#{input.inspect} must be an instance of #{primitive}")
    )
  end

  output = {}
  failures = []

  input.each do |k, v|
    res_k = key_type.try(k)
    res_v = value_type.try(v)

    if res_k.failure?
      failures << res_k.error
    elsif output.key?(res_k.input)
      failures << CoercionError.new("duplicate coerced hash key #{res_k.input.inspect}")
    elsif res_v.failure?
      failures << res_v.error
    else
      output[res_k.input] = res_v.input
    end
  end

  if failures.empty?
    success(output)
  else
    failure(input, MultipleError.new(failures))
  end
end