lib/mongoid_tree.rb in mongoid_tree-0.2.0 vs lib/mongoid_tree.rb in mongoid_tree-0.3.0
- old
+ new
@@ -1,13 +1,17 @@
module Mongoid
module Acts
module Tree
extend ActiveSupport::Concern
include Comparable
-
+
included do
- references_many :children, :class_name => self.name, :stored_as => :array, :inverse_of => :parents do
+ references_many :children,
+ :class_name => self.name,
+ :stored_as => :array,
+ :inverse_of => :parents,
+ :dependent => :destroy do
def <<(*objects)
objects.flatten.each_with_index do |object, index|
reverse_key = reverse_key(object)
if object.position == nil
# This one sets the position for a new object added via children << object
@@ -16,52 +20,69 @@
# Stores the parents path into it's own path array.
#raise @parent.inspect
object.send(reverse_key).concat(@parent.send(reverse_key))
end
super(objects)
-
+
end
end
-
- #referenced_in :parent, :class_name => self.name, :inverse_of => :children
- references_many :parents, :class_name => self.name, :stored_as => :array, :inverse_of => :children
-
+
+ references_many :parents,
+ :class_name => self.name,
+ :stored_as => :array,
+ :inverse_of => :children
+
# This stores the position in the children array of the parent object.
# Makes it easier to flatten / export / import a tree
field :position, :type => Integer
field :depth, :type => Integer
end
module InstanceMethods
-
+
def parent
self.parents.last
end
-
+
def depth
self.parents.count
end
-
+
#Comparable
def <=> (another_node)
self.position <=> another_node.position
end
-
-
- # TODO change this into a Mongoid Query
+
+ # Returns the whole subtree including itself as array
def depth_first
result = [self]
- if children.empty?
+ if self.child_ids.empty?
return result
else
- self.children.each do |child|
+ self.children.sort.each do |child|
result += child.depth_first
end
end
return result
end
+ alias :dfs :depth_first
+ # Returns the whole subtree including itself as array
+ def breadth_first
+ result = []
+ queue = [self]
+ while !queue.empty?
+ node = queue.shift
+ result << node
+ node.children.sort.each do |child|
+ queue << child
+ end
+ end
+ return result
+ end
+ alias :bfs :breadth_first
+
def insert_before( new_child )
new_child.position = self.position
self.parent.children.each do |child|
if child.position >= new_child.position
child.position += 1
@@ -77,12 +98,33 @@
child.position += 1
end
end
self.parent.children << new_child
end
+
+ def move_to(target_node)
+ # unhinge - I was getting a nil on another implementation, so this is a bit longer but works
+ child_ids_array = self.parent.child_ids.clone
+ child_ids_array.delete(self.id)
+ parent.update_attributes(:child_ids => child_ids_array )
+ self.update_attributes(:parent_ids => [])
+ # and append
+ target_node.children << self
+ # recurse through subtree
+ self.rebuild_paths
+ end
+
+ def rebuild_paths
+ self.update_path
+ self.children.each do |child|
+ child.rebuild_paths
+ end
+ end
+
+ def update_path
+ self.update_attributes(:parent_ids => self.parent.parent_ids + [self.parent.id])
+ end
+
end
-
-
-
end
end
-end
\ No newline at end of file
+end