Skip to content

Commit 432be60

Browse files
committed
Make sorting more consistent
Keep sorting as similar as possible for input and output. The goal of sorting here is only move parents to in front of children Or when there is a ranking function, sort the whole tree. Sorting now keeps closer to the input values No longer blows away original sort when no order specified It still has trouble sorting with custom sort method when not all parent objects are present (it can't sort something not present)
1 parent bdf39ea commit 432be60

File tree

2 files changed

+19
-22
lines changed

2 files changed

+19
-22
lines changed

Diff for: lib/ancestry/class_methods.rb

+17-22
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,12 @@ def orphan_strategy= orphan_strategy
2929

3030
# Arrangement
3131
def arrange options = {}
32-
# Get all nodes ordered by ancestry and start sorting them into an empty hash
33-
arrange_nodes self.ancestry_base_class.reorder(options.delete(:order)).where(options)
32+
# Get all nodes and start sorting them into an empty hash
33+
scope = self.ancestry_base_class
34+
if (order = options.delete(:order))
35+
scope = scope.order(order)
36+
end
37+
arrange_nodes scope.where(options)
3438
end
3539

3640
# Arrange array of nodes into a nested hash of the form
@@ -61,28 +65,19 @@ def arrange_serializable options={}, nodes=nil, &block
6165

6266
# Pseudo-preordered array of nodes. Children will always follow parents,
6367
# for ordering nodes within a rank provide block, eg. Node.sort_by_ancestry(Node.all) {|a, b| a.rank <=> b.rank}.
68+
# TODO: Fix case when parents are missing and a sort is specified
6469
def sort_by_ancestry(nodes, &block)
65-
arranged = nodes if nodes.is_a?(Hash)
66-
67-
unless arranged
68-
presorted_nodes = nodes.sort do |a, b|
69-
a_cestry, b_cestry = a.ancestry || '0', b.ancestry || '0'
70-
71-
if block_given? && a_cestry == b_cestry
72-
yield a, b
73-
else
74-
a_cestry <=> b_cestry
75-
end
70+
if nodes.is_a?(Hash) || block_given?
71+
nodes = arrange_nodes(nodes) unless nodes.is_a?(Hash)
72+
73+
nodes = nodes.sort { |(a, a_children), (b, b_children)| yield(a, b) } if block_given?
74+
nodes.inject([]) do |sorted_nodes, (node, children)|
75+
sorted_nodes << node
76+
sorted_nodes += sort_by_ancestry(children, &block) unless children.blank?
77+
sorted_nodes
7678
end
77-
78-
arranged = arrange_nodes(presorted_nodes)
79-
end
80-
81-
arranged.inject([]) do |sorted_nodes, pair|
82-
node, children = pair
83-
sorted_nodes << node
84-
sorted_nodes += sort_by_ancestry(children, &block) unless children.blank?
85-
sorted_nodes
79+
else
80+
nodes.sort { |a, b| (b.path_ids - a.path_ids).empty? ? 1 : 0 }
8681
end
8782
end
8883

Diff for: test/concerns/sort_by_ancestry_test.rb

+2
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ def test_sort_by_ancestry_with_block
5353
assert_equal [n1, n5, n2].map(&:id), model.sort_by_ancestry([n2, n1, n5], &sort).map(&:id)
5454
# does not work for all children no parents
5555
# assert_equal [n5, n3, n4, n6].map(&:id), model.sort_by_ancestry([n3, n4, n5, n6], &sort).map(&:id)
56+
# non ranked works for paginated mid section with missing parents and children works
57+
assert_equal [n3, n2, n4].map(&:id), model.sort_by_ancestry([n3, n2, n4]).map(&:id)
5658
# ranked does not work for ranked case with missing parents
5759
# assert_equal [n3, n2, n4].map(&:id), model.sort_by_ancestry([n3, n2, n4], &sort).map(&:id)
5860
end

0 commit comments

Comments
 (0)