Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Added class method to sort nodes by ancestry.

  • Loading branch information...
commit 5614a3b74da69ccdd3dca28869c2575146b07fb3 1 parent c3d2274
@kueda kueda authored
Showing with 39 additions and 4 deletions.
  1. +26 −4 lib/ancestry/class_methods.rb
  2. +13 −0 test/has_ancestry_test.rb
View
30 lib/ancestry/class_methods.rb
@@ -36,14 +36,36 @@ def arrange options = {}
self.base_class.ordered_by_ancestry_and options.delete(:order)
end
# Get all nodes ordered by ancestry and start sorting them into an empty hash
- scope.all(options).inject(ActiveSupport::OrderedHash.new) do |arranged_nodes, node|
+ arrange_nodes scope.all(options)
+ end
+
+ # Arrange array of nodes into a nested hash of the form
+ # {node => children}, where children = {} if the node has no children
+ def arrange_nodes(nodes)
+ # Get all nodes ordered by ancestry and start sorting them into an empty hash
+ nodes.inject(ActiveSupport::OrderedHash.new) do |arranged_nodes, node|
# Find the insertion point for that node by going through its ancestors
node.ancestor_ids.inject(arranged_nodes) do |insertion_point, ancestor_id|
insertion_point.each do |parent, children|
# Change the insertion point to children if node is a descendant of this parent
insertion_point = children if ancestor_id == parent.id
- end; insertion_point
- end[node] = ActiveSupport::OrderedHash.new; arranged_nodes
+ end
+ insertion_point
+ end[node] = ActiveSupport::OrderedHash.new
+ arranged_nodes
+ end
+ end
+
+ # Pseudo-preordered array of nodes. Children will always follow parents,
+ # but the ordering of nodes within a rank depends on their order in the
+ # array that gets passed in
+ def sort_by_ancestry(nodes)
+ arranged = nodes.is_a?(Hash) ? nodes : arrange_nodes(nodes.sort_by{|n| n.ancestry || '0'})
+ arranged.inject([]) do |sorted_nodes, pair|
+ node, children = pair
+ sorted_nodes << node
+ sorted_nodes += sort_by_ancestry(children) unless children.blank?
+ sorted_nodes
end
end
@@ -134,4 +156,4 @@ def rebuild_depth_cache!
end
end
end
-end
+end
View
13 test/has_ancestry_test.rb
@@ -688,4 +688,17 @@ def test_arrange_order_option
end
end
end
+
+ def test_sort_by_ancestry
+ AncestryTestDatabase.with_model do |model|
+ n1 = model.create!
+ n2 = model.create!(:parent => n1)
+ n3 = model.create!(:parent => n2)
+ n4 = model.create!(:parent => n2)
+ n5 = model.create!(:parent => n1)
+
+ arranged = model.sort_by_ancestry(model.all.sort_by(&:id).reverse)
+ assert_equal [n1, n2, n4, n3, n5].map(&:id), arranged.map(&:id)
+ end
+ end
end
Please sign in to comment.
Something went wrong with that request. Please try again.