lib/dry/validation/schema/value.rb in dry-validation-0.7.4 vs lib/dry/validation/schema/value.rb in dry-validation-0.8.0
- old
+ new
@@ -2,78 +2,98 @@
module Dry
module Validation
class Schema
class Value < DSL
- attr_reader :type, :schema_class
+ attr_reader :type, :schema_class, :schema, :type_map
def initialize(options = {})
super
@type = options.fetch(:type, :key)
@schema_class = options.fetch(:schema_class, ::Class.new(Schema))
+ @options = options.merge(type: @type, schema_class: @schema_class)
+ @type_map = parent && parent.root? ? parent.type_map : {}
end
- def configure(&block)
- klass = ::Class.new(schema_class, &block)
- @schema_class = klass
+ def predicates(mod)
+ @registry = options[:registry] = schema_class.predicates(mod)
+ end
+
+ def input(type)
+ schema_class.config.input = type
self
end
- def root?
- name.nil?
+ def key(name, &block)
+ warn 'key is deprecated - use required instead.'
+
+ required(name, &block)
end
- def class
- Value
+ def required(name, type_spec = nil, &block)
+ rule = define(name, Key, &block)
+
+ if type_spec
+ type_map[name] = type_spec
+ end
+
+ rule
end
def schema(other = nil, &block)
- schema = Schema.create_class(self, other, &block)
- hash?.and(schema)
+ @schema = Schema.create_class(self, other, &block)
+ type_map.update(@schema.type_map)
+ hash?.and(@schema)
end
def each(*predicates, &block)
left = array?
right =
if predicates.size > 0
- inferred = predicates
- .reduce(Value.new) { |a, e| a.__send__(*::Kernel.Array(e)) }
-
- create_rule([:each, inferred.to_ast])
+ create_rule([:each, infer_predicates(predicates, new).to_ast])
else
- val = Value[name].instance_eval(&block)
+ val = Value[
+ name, registry: registry, schema_class: schema_class.clone
+ ].instance_eval(&block)
- create_rule([:each, [:set, val.rule_ast]])
+ if val.type_map?
+ if root?
+ @type_map = [val.type_map]
+ else
+ type_map[name] = [val.type_map]
+ end
+ end
+
+ create_rule([:each, val.to_ast])
end
rule = left.and(right)
add_rule(rule) if root?
rule
end
def when(*predicates, &block)
- left = predicates
- .reduce(Check[path, type: type]) { |a, e| a.__send__(*::Kernel.Array(e)) }
+ left = infer_predicates(predicates, Check[path, type: type, registry: registry])
- right = Value.new(type: type)
+ right = Value.new(type: type, registry: registry)
right.instance_eval(&block)
add_check(left.then(create_rule(right.to_ast)))
self
end
def rule(id = nil, **options, &block)
if id
- val = Value[id]
+ val = Value[id, registry: registry]
res = val.instance_exec(&block)
else
id, deps = options.to_a.first
- val = Value[id]
+ val = Value[id, registry: registry]
res = val.instance_exec(*deps.map { |name| val.value(name) }, &block)
end
add_check(val.with(rules: [res.with(deps: deps || [])]))
end
@@ -85,23 +105,88 @@
rule(conf => [conf, name]) { |left, right| left.eql?(right) }
end
def value(name)
- check(name, rules: rules)
+ check(name, registry: registry, rules: rules)
end
def check(name, options = {})
Check[name, options.merge(type: type)]
end
+ def configure(&block)
+ klass = ::Class.new(schema_class, &block)
+ @schema_class = klass
+ @registry = klass.registry
+ self
+ end
+
+ def root?
+ name.nil?
+ end
+
+ def type_map?
+ ! type_map.empty?
+ end
+
+ def schema?
+ ! @schema.nil?
+ end
+
+ def class
+ Value
+ end
+
+ def new
+ self.class.new(registry: registry, schema_class: schema_class.clone)
+ end
+
+ def key?(name)
+ create_rule([:val, registry[:key?].curry(name).to_ast])
+ end
+
+ def predicate(name, *args)
+ registry.ensure_valid_predicate(name, args)
+ registry[name].curry(*args)
+ end
+
+ def node(input, *args)
+ if input.is_a?(::Symbol)
+ [type, [name, predicate(input, *args).to_ast]]
+ elsif input.respond_to?(:rule)
+ [type, [name, [:type, input]]]
+ elsif input.is_a?(::Class) && input < ::Dry::Types::Struct
+ [type, [name, [:schema, Schema.create_class(self, input)]]]
+ elsif input.is_a?(Schema)
+ [type, [name, schema(input).to_ast]]
+ else
+ [type, [name, input.to_ast]]
+ end
+ end
+
private
+ def infer_predicates(predicates, infer_on)
+ predicates.map { |predicate|
+ name, *args = ::Kernel.Array(predicate).first
+
+ if name.is_a?(Schema)
+ infer_on.schema(name)
+ else
+ infer_on.__send__(name, *args)
+ end
+ }.reduce(:and)
+ end
+
def method_missing(meth, *args, &block)
- val_rule = create_rule([:val, [:predicate, [meth, args]]])
+ val_rule = create_rule([:val, predicate(meth, *args).to_ast])
if block
- val = Value.new.instance_eval(&block)
+ val = new.instance_eval(&block)
+
+ type_map.update(val.type_map) if val.type_map?
+
new_rule = create_rule([:and, [val_rule.to_ast, val.to_ast]])
add_rule(new_rule)
else
val_rule