lib/metaractor/errors.rb in metaractor-1.2.1 vs lib/metaractor/errors.rb in metaractor-2.0.0

- old
+ new

@@ -1,28 +1,102 @@ +require 'sycamore' require 'forwardable' - module Metaractor - class Error < StandardError; end - class InvalidError < Error; end + class Errors + extend Forwardable - module Errors - def fail_with_error!(*args) - context.fail_with_error!(*args) + def initialize + @tree = Sycamore::Tree.new end - def fail_with_errors!(*args) - context.fail_with_errors!(*args) + def_delegators :@tree, :to_h, :empty? + + def add(error: {}, errors: {}) + trees = [] + [error, errors].each do |h| + tree = nil + if h.is_a? Metaractor::Errors + tree = Sycamore::Tree.from(h.instance_variable_get(:@tree)) + else + tree = Sycamore::Tree.from(h) + end + + unless tree.empty? + if tree.nodes.any? {|node| tree.strict_leaf?(node) } + raise ArgumentError, "Invalid hash!" + end + trees << tree + end + end + + trees.each do |tree| + @tree.add(tree) + end + @tree.compact end - def add_error(*args) - context.add_error(*args) + def full_messages(tree = @tree) + messages = [] + tree.each_path do |path| + messages << message_from_path(path) + end + + messages end + alias to_a full_messages - def add_errors(*args) - context.add_errors(*args) + def full_messages_for(*path) + child_tree = @tree.fetch_path(path) + + if child_tree.strict_leaves? + child_tree = @tree.fetch_path(path[0..-2]) + end + + full_messages(child_tree) end - def error_messages - context.error_messages + def dig(*path) + result = @tree.dig(*path) + + if result.strict_leaves? + result.nodes + else + result.to_h + end + end + alias [] dig + + def include?(*elements) + if elements.size == 1 && + elements.first.is_a?(Hash) + @tree.include?(*elements) + else + full_messages.include?(*elements) + end + end + + def slice(*paths) + new_tree = Sycamore::Tree.new + + paths.each do |path| + if @tree.include_path?(path) + new_tree[path] = @tree[path].dup + end + end + + new_tree.to_h + end + + private + + def message_from_path(path) + path_elements = [] + path.parent&.each_node do |node| + unless node == :base + path_elements << node.to_s + end + end + + "#{path_elements.join('.')} #{path.node.to_s}".lstrip end end end