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