class Dry::Schema::Macros::DSL
Macro specialization used within the DSL
@api public
Public Instance Methods
Like `each` but sets `array?` type-check
@example a list of strings
required(:tags).array(:str?)
@example a list of hashes
required(:tags).array(:hash) do required(:name).filled(:string) end
@return [Macros::Core]
@api public
# File lib/dry/schema/macros/dsl.rb, line 179 def array(...) append_macro(Macros::Array) do |macro| macro.value(...) end end
@api private
# File lib/dry/schema/macros/dsl.rb, line 202 def custom_type? schema_dsl.custom_type?(name) end
Specify predicates that should be applied to each element of an array
This is a simpler building block than `array` macro, use it when you want to provide `array?` type-check with other rules manually.
@example a list of strings
required(:tags).value(:array, min_size?: 2).each(:str?)
@example a list of hashes
required(:tags).value(:array, min_size?: 2).each(:hash) do required(:name).filled(:string) end
@return [Macros::Core]
@api public
# File lib/dry/schema/macros/dsl.rb, line 159 def each(...) append_macro(Macros::Each) do |macro| macro.value(...) end end
Prepends `:filled?` predicate
@example with a type spec
required(:name).filled(:string)
@example with a type spec and a predicate
required(:name).filled(:string, format?: /\w+/)
@return [Macros::Core]
@api public
# File lib/dry/schema/macros/dsl.rb, line 80 def filled(*args, **opts, &block) extract_type_spec(args) do |*predicates, type_spec:, type_rule:| append_macro(Macros::Filled) do |macro| macro.call(*predicates, type_spec: type_spec, type_rule: type_rule, **opts, &block) end end end
Specify a nested hash with enforced `hash?` type-check
@example
required(:tags).hash do required(:name).value(:string) end
@api public
# File lib/dry/schema/macros/dsl.rb, line 135 def hash(...) append_macro(Macros::Hash) do |macro| macro.call(...) end end
Set type specification and predicates for a maybe value
@example
required(:name).maybe(:string)
@see Macros::Key#value
@return [Macros::Key]
@api public
# File lib/dry/schema/macros/dsl.rb, line 98 def maybe(*args, **opts, &block) extract_type_spec(args, nullable: true) do |*predicates, type_spec:, type_rule:| append_macro(Macros::Maybe) do |macro| macro.call(*predicates, type_spec: type_spec, type_rule: type_rule, **opts, &block) end end end
Specify a nested hash without enforced `hash?` type-check
This is a simpler building block than `hash` macro, use it when you want to provide `hash?` type-check with other rules manually.
@example
required(:tags).value(:hash, min_size?: 1).schema do required(:name).value(:string) end
@return [Macros::Core]
@api public
# File lib/dry/schema/macros/dsl.rb, line 120 def schema(...) append_macro(Macros::Schema) do |macro| macro.call(...) end end
Set type spec
@example
required(:name).type(:string).value(min_size?: 2)
@param [Symbol, Array
, Dry::Types::Type] spec
@return [Macros::Key]
@api public
# File lib/dry/schema/macros/dsl.rb, line 196 def type(spec) schema_dsl.set_type(name, spec) self end
@overload value(*predicates, **predicate_opts)
Set predicates without and with arguments @param [Array<Symbol>] predicates @param [Hash] predicate_opts @example with a predicate required(:name).value(:filled?) @example with a predicate with arguments required(:name).value(min_size?: 2) @example with a predicate with and without arguments required(:name).value(:filled?, min_size?: 2) @example with a block required(:name).value { filled? & min_size?(2) }
@return [Macros::Core]
@api public
# File lib/dry/schema/macros/dsl.rb, line 61 def value(*args, **opts, &block) extract_type_spec(args) do |*predicates, type_spec:, type_rule:| append_macro(Macros::Value) do |macro| macro.call(*predicates, type_spec: type_spec, type_rule: type_rule, **opts, &block) end end end
Private Instance Methods
@api private
# File lib/dry/schema/macros/dsl.rb, line 209 def append_macro(macro_type) macro = macro_type.new(schema_dsl: schema_dsl, name: name) yield(macro) if chain trace << macro self else macro end end
@api private rubocop: disable Metrics/PerceivedComplexity
# File lib/dry/schema/macros/dsl.rb, line 224 def extract_type_spec(args, nullable: false, set_type: true) type_spec = args[0] unless schema_or_predicate?(args[0]) predicates = Array(type_spec ? args[1..] : args) type_rule = nil if type_spec resolved_type = resolve_type(type_spec, nullable) if type_spec.is_a?(::Array) type_rule = type_spec.map { |ts| new(chain: false).value(ts) }.reduce(:|) else type_predicates = predicate_inferrer[resolved_type] predicates.replace(type_predicates + predicates) unless type_predicates.empty? return self if predicates.empty? end end type(resolved_type) if set_type && resolved_type if type_rule yield(*predicates, type_spec: nil, type_rule: type_rule) else yield(*predicates, type_spec: type_spec, type_rule: nil) end end
@api private
# File lib/dry/schema/macros/dsl.rb, line 255 def resolve_type(type_spec, nullable) resolved = schema_dsl.resolve_type(type_spec) if type_spec.is_a?(::Array) || !nullable || resolved.optional? resolved else schema_dsl.resolve_type([:nil, resolved]) end end
@api private
# File lib/dry/schema/macros/dsl.rb, line 266 def schema_or_predicate?(arg) arg.is_a?(Dry::Schema::Processor) || (arg.is_a?(Symbol) && arg.to_s.end_with?(QUESTION_MARK)) end