lib/dry/validation/hint_compiler.rb in dry-validation-0.8.0 vs lib/dry/validation/hint_compiler.rb in dry-validation-0.9.0

- old
+ new

@@ -1,10 +1,10 @@ -require 'dry/validation/error_compiler/input' +require 'dry/validation/message_compiler' module Dry module Validation - class HintCompiler < ErrorCompiler::Input + class HintCompiler < MessageCompiler include Dry::Equalizer(:messages, :rules, :options) attr_reader :rules, :excluded, :cache TYPES = { @@ -19,118 +19,86 @@ time?: Time, hash?: Hash, array?: Array }.freeze - EXCLUDED = [:none?, :filled?, :key?].freeze + EXCLUDED = (%i(key? none? filled?) + TYPES.keys).freeze - DEFAULT_OPTIONS = { name: nil, input: nil, message_type: :hint }.freeze - - EMPTY_MESSAGES = {}.freeze - def self.cache @cache ||= Concurrent::Map.new end def initialize(messages, options = {}) - super(messages, DEFAULT_OPTIONS.merge(options)) - @rules = @options.delete(:rules) - @excluded = @options.fetch(:excluded, EXCLUDED) - @val_type = options[:val_type] + super(messages, options) + @rules = options.fetch(:rules, EMPTY_ARRAY) + @excluded = options.fetch(:excluded, EXCLUDED) @cache = self.class.cache end - def hash - @hash ||= [messages, rules, options].hash + def message_type + :hint end - def with(new_options) - return self if new_options.empty? - super(new_options.merge(rules: rules)) + def message_class + Hint end + def hash + @hash ||= [messages, rules, options].hash + end + def call cache.fetch_or_store(hash) { super(rules) } end - def visit_predicate(node) - predicate, _ = node - - val_type = TYPES[predicate] - - return with(val_type: val_type) if val_type - return EMPTY_MESSAGES if excluded.include?(predicate) - - super + def visit_predicate(node, opts = EMPTY_HASH) + predicate, args = node + return EMPTY_ARRAY if excluded.include?(predicate) || dyn_args?(args) + super(node, opts.merge(val_type: TYPES[predicate])) end - def visit_set(node) - result = node.map do |el| - visit(el) - end - merge(result) + def visit_each(node, opts = EMPTY_HASH) + visit(node, opts.merge(each: true)) end - def visit_each(node) - visit(node) - end - - def visit_or(node) + def visit_or(node, *args) left, right = node - merge([visit(left), visit(right)]) + [Array[visit(left, *args)], Array[visit(right, *args)]].flatten end - def visit_and(node) - left, right = node - - result = visit(left) - - if result.is_a?(self.class) - result.visit(right) - else - visit(right) - end - end - - def visit_implication(node) + def visit_and(node, *args) _, right = node - visit(right) + visit(right, *args) end - def visit_key(node) - name, predicate = node - with(name: Array([*self.name, name])).visit(predicate) - end - alias_method :visit_attr, :visit_key + def visit_schema(node, opts = EMPTY_HASH) + path = node.config.path + rules = node.rule_ast + schema_opts = opts.merge(path: [path]) - def visit_val(node) - visit(node) + rules.map { |rule| visit(rule, schema_opts) } end - def visit_schema(node) - merge(node.rule_ast.map(&method(:visit))) - end - def visit_check(node) - DEFAULT_RESULT + EMPTY_ARRAY end def visit_xor(node) - DEFAULT_RESULT + EMPTY_ARRAY end def visit_not(node) - DEFAULT_RESULT + EMPTY_ARRAY end - def visit_type(node) - visit(node.rule.to_ast) + def visit_type(node, *args) + visit(node.rule.to_ast, *args) end private - def merge(result) - super(result.reject { |el| el.is_a?(self.class) }) + def dyn_args?(args) + args.map(&:last).any? { |a| a.is_a?(UnboundMethod) } end end end end