1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
# frozen_string_literal: true
require 'dry/equalizer'
require 'dry/core/deprecations'
module Dry
module Types
# Schema is a hash with explicit member types defined
#
# @api public
class Schema < Hash
# Proxy type for schema keys. Contains only key name and
# whether it's required or not. All other calls deletaged
# to the wrapped type.
#
# @see Dry::Types::Schema
class Key
extend ::Dry::Core::Deprecations[:'dry-types']
include Type
include Dry::Equalizer(:name, :type, :options, inspect: false, immutable: true)
include Decorator
include Builder
include Printable
# @return [Symbol]
attr_reader :name
# @api private
def initialize(type, name, required: Undefined, **options)
required = Undefined.default(required) do
type.meta.fetch(:required) { !type.meta.fetch(:omittable, false) }
end
unless name.is_a?(::Symbol)
raise ArgumentError, "Schemas can only contain symbol keys, #{name.inspect} given"
end
super(type, name, required: required, **options)
@name = name
end
# @api private
def call_safe(input, &block)
type.call_safe(input, &block)
end
# @api private
def call_unsafe(input)
type.call_unsafe(input)
end
# @see Dry::Types::Nominal#try
#
# @api public
def try(input, &block)
type.try(input, &block)
end
# Whether the key is required in schema input
#
# @return [Boolean]
#
# @api public
def required?
options.fetch(:required)
end
# Control whether the key is required
#
# @overload required
# @return [Boolean]
#
# @overload required(required)
# Change key's "requireness"
#
# @param [Boolean] required New value
# @return [Dry::Types::Schema::Key]
#
# @api public
def required(required = Undefined)
if Undefined.equal?(required)
options.fetch(:required)
else
with(required: required)
end
end
# Make key not required
#
# @return [Dry::Types::Schema::Key]
#
# @api public
def omittable
required(false)
end
# Turn key into a lax type. Lax types are not strict hence such keys are not required
#
# @return [Lax]
#
# @api public
def lax
__new__(type.lax).required(false)
end
# Dump to internal AST representation
#
# @return [Array]
#
# @api public
def to_ast(meta: true)
[
:key,
[
name,
required,
type.to_ast(meta: meta)
]
]
end
# @see Dry::Types::Meta#meta
#
# @api public
def meta(data = nil)
if data.nil? || !data.key?(:omittable)
super
else
self.class.warn(
'Using meta for making schema keys is deprecated, ' \
'please use .omittable or .required(false) instead' \
"\n" + Core::Deprecations::STACK.()
)
super.required(!data[:omittable])
end
end
private
# @api private
def decorate?(response)
response.is_a?(Type)
end
end
end
end
end
|