lib/dry/schema/macros/value.rb in dry-schema-1.4.3 vs lib/dry/schema/macros/value.rb in dry-schema-1.5.0

- old
+ new

@@ -1,8 +1,9 @@ # frozen_string_literal: true -require 'dry/schema/macros/dsl' +require "dry/schema/path" +require "dry/schema/macros/dsl" module Dry module Schema module Macros # A macro used for specifying predicates to be applied to values from a hash @@ -11,34 +12,46 @@ class Value < DSL # @api private def call(*predicates, **opts, &block) schema = predicates.detect { |predicate| predicate.is_a?(Processor) } + type_spec = opts[:type_spec] + if schema current_type = schema_dsl.types[name] updated_type = if array_type?(current_type) build_array_type(current_type, schema.type_schema) else schema.type_schema end - schema_dsl.set_type(name, updated_type) + import_steps(schema) + + type(updated_type) unless custom_type? && !current_type.respond_to?(:of) end - trace.evaluate(*predicates, **opts) + trace_opts = opts.reject { |key, _| key == :type_spec || key == :type_rule } - type_spec = opts[:type_spec] - if block && type_spec.equal?(:hash) - hash(&block) - elsif block - trace.append(new(chain: false).instance_exec(&block)) + if (type_rule = opts[:type_rule]) + trace.append(type_rule).evaluate(*predicates, **trace_opts) + trace.append(new(chain: false).instance_exec(&block)) if block + else + trace.evaluate(*predicates, **trace_opts) + + if block && type_spec.equal?(:hash) + hash(&block) + elsif type_spec.is_a?(::Dry::Types::Type) && hash_type?(type_spec) + hash(type_spec) + elsif block + trace.append(new(chain: false).instance_exec(&block)) + end end if trace.captures.empty? - raise ArgumentError, 'wrong number of arguments (given 0, expected at least 1)' + raise ArgumentError, "wrong number of arguments (given 0, expected at least 1)" end each(type_spec.type.member) if type_spec.respond_to?(:member) self @@ -47,21 +60,30 @@ # @api private def array_type?(type) primitive_inferrer[type].eql?([::Array]) end + def hash_type?(type) + primitive_inferrer[type].eql?([::Hash]) + end + # @api private def build_array_type(array_type, member) if array_type.respond_to?(:of) array_type.of(member) else - raise ArgumentError, <<~ERROR.split("\n").join(' ') + raise ArgumentError, <<~ERROR.split("\n").join(" ") Cannot define schema for a nominal array type. Array types must be instances of Dry::Types::Array, usually constructed with Types::Constructor(Array) { ... } or Dry::Types['array'].constructor { ... } ERROR end + end + + # @api private + def import_steps(schema) + schema_dsl.steps.import_callbacks(Path[[*path, name]], schema.steps) end # @api private def respond_to_missing?(meth, include_private = false) super || meth.to_s.end_with?(QUESTION_MARK)