lib/arel/enhance/node.rb in arel_toolkit-0.4.1 vs lib/arel/enhance/node.rb in arel_toolkit-0.4.2

- old
+ new

@@ -1,19 +1,18 @@ module Arel module Enhance class Node attr_reader :object attr_reader :parent - attr_reader :path + attr_reader :local_path attr_reader :fields attr_reader :children attr_reader :root_node attr_reader :context def initialize(object) @object = object - @path = Path.new @root_node = self @fields = [] @children = {} @dirty = false @context = {} @@ -49,16 +48,16 @@ def remove mutate(nil, remove: true) end - def replace(new_node) - mutate(new_node) + def replace(new_arel_node) + mutate(new_arel_node) end def add(path_node, node) - node.path = path.append(path_node) + node.local_path = path_node node.parent = self node.root_node = root_node @children[path_node.value.to_s] = node end @@ -105,21 +104,33 @@ def query(**kwargs) Arel::Enhance::Query.call(self, kwargs) end + def full_path + the_path = [local_path] + current_parent = parent + + while current_parent + the_path.unshift current_parent.local_path + current_parent = current_parent.parent + end + + the_path.compact + end + protected - attr_writer :path + attr_writer :local_path attr_writer :parent attr_writer :root_node # rubocop:disable Metrics/AbcSize # rubocop:disable Metrics/CyclomaticComplexity # rubocop:disable Metrics/PerceivedComplexity def recursive_inspect(string, indent = 1) - string << "<#{inspect_name} #{path.inspect}\n" + string << "<#{inspect_name} #{full_path.inspect}\n" string << "#{spacing(indent)}sql = #{to_sql}\n" unless to_sql.nil? string << "#{spacing(indent)}parent = #{parent.nil? ? nil.inspect : parent.inspect_name}" string << "\n" unless children.length.zero? children.each do |key, child| string << "#{spacing(indent)}#{key} =\n" @@ -133,10 +144,11 @@ ">\n" else "#{spacing(indent - 1)}>\n" end end + # rubocop:enable Metrics/AbcSize # rubocop:enable Metrics/CyclomaticComplexity # rubocop:enable Metrics/PerceivedComplexity attr_writer :object @@ -152,14 +164,20 @@ end def deep_copy_object # https://github.com/mvgijssel/arel_toolkit/issues/97 new_object = Marshal.load(Marshal.dump(object)) + self.object = new_object - each do |node| - selected_object = node.path.dig_send(new_object) - node.object = selected_object + recursive_update_object(new_object) + end + + def recursive_update_object(arel_tree) + children.each_value do |child| + tree_child = arel_tree.send(*child.local_path.method) + child.object = tree_child + child.recursive_update_object(tree_child) end end def mark_as_dirty return if dirty? @@ -175,31 +193,37 @@ # rubocop:disable Metrics/AbcSize def mutate(new_node, remove: false) root_node.mark_as_dirty parent_object = parent.object - new_node = [] if remove && object.is_a?(Array) + new_arel_node = new_node.is_a?(Arel::Enhance::Node) ? new_node.object : new_node + new_arel_node = [] if remove && object.is_a?(Array) - if parent_object.respond_to?("#{path.current.value}=") - parent_object.send("#{path.current.value}=", new_node) + if parent_object.respond_to?("#{local_path.value}=") + parent_object.send("#{local_path.value}=", new_arel_node) - elsif parent_object.instance_values.key?(path.current.value) - parent_object.instance_variable_set("@#{path.current.value}", new_node) + elsif parent_object.instance_values.key?(local_path.value) + parent_object.instance_variable_set("@#{local_path.value}", new_arel_node) - elsif path.current.arguments? && parent_object.respond_to?(path.current.method[0]) + elsif local_path.arguments? && parent_object.respond_to?(local_path.method[0]) if remove - parent_object.delete_at(path.current.value) + parent_object.delete_at(local_path.value) else - parent_object[path.current.value] = new_node + parent_object[local_path.value] = new_arel_node end else - raise "Don't know how to replace `#{path.current.value}` in #{parent_object.inspect}" + raise "Don't know how to replace `#{local_path.value}` in #{parent_object.inspect}" end - new_parent_tree = Visitor.new.accept_with_root(parent_object, parent) - parent.parent.add(parent.path.current, new_parent_tree) - new_parent_tree[path.current.value] + if new_node.is_a?(Arel::Enhance::Node) + parent.add(local_path, new_node) + parent[local_path.value] + else + new_parent_tree = Visitor.new.accept_with_root(parent_object, parent) + parent.parent.add(parent.local_path, new_parent_tree) + new_parent_tree[local_path.value] + end end # rubocop:enable Metrics/PerceivedComplexity # rubocop:enable Metrics/CyclomaticComplexity # rubocop:enable Metrics/AbcSize end