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