Skip to content

Commit d25877b

Browse files
committed
Fixup Sorting
Make sorting more consistent The 2 cases are - no rank function: only move parents to in front of children - rank function: sort each level with ranking function
1 parent cbaa20a commit d25877b

File tree

2 files changed

+33
-28
lines changed

2 files changed

+33
-28
lines changed

lib/ancestry/class_methods.rb

+6-10
Original file line numberDiff line numberDiff line change
@@ -70,17 +70,13 @@ def arrange_serializable options={}, nodes=nil, &block
7070
# Pseudo-preordered array of nodes. Children will always follow parents,
7171
# for ordering nodes within a rank provide block, eg. Node.sort_by_ancestry(Node.all) {|a, b| a.rank <=> b.rank}.
7272
def sort_by_ancestry(nodes, &block)
73-
arranged = nodes if nodes.is_a?(Hash)
74-
75-
unless arranged
73+
if nodes.is_a?(Hash)
74+
arranged = nodes
75+
else
7676
presorted_nodes = nodes.sort do |a, b|
77-
a_cestry, b_cestry = a.ancestry || '0', b.ancestry || '0'
78-
79-
if block_given? && a_cestry == b_cestry
80-
yield a, b
81-
else
82-
a_cestry <=> b_cestry
83-
end
77+
r = a.ancestor_ids <=> b.ancestor_ids
78+
r = yield(a, b) if r == 0 && block_given?
79+
r
8480
end
8581

8682
arranged = arrange_nodes(presorted_nodes)

test/concerns/sort_by_ancestry_test.rb

+27-18
Original file line numberDiff line numberDiff line change
@@ -8,40 +8,49 @@ def test_sort_by_ancestry
88
# - n3
99
# - n4
1010
# - n5
11+
# - n6
1112
n1 = model.create!
1213
n2 = model.create!(:parent => n1)
1314
n3 = model.create!(:parent => n2)
1415
n4 = model.create!(:parent => n2)
1516
n5 = model.create!(:parent => n1)
17+
n6 = model.create!(:parent => n5)
18+
nodes = [n1, n2, n3, n4, n5, n6]
1619

17-
records = model.sort_by_ancestry(model.all.sort_by(&:id).reverse)
18-
if records[1] == n2
19-
if records[2] == n3
20-
assert_equal [n1, n2, n3, n4, n5].map(&:id), records.map(&:id)
21-
else
22-
assert_equal [n1, n2, n4, n3, n5].map(&:id), records.map(&:id)
23-
end
24-
else
25-
if records[3] == n3
26-
assert_equal [n1, n5, n2, n3, n4].map(&:id), records.map(&:id)
27-
else
28-
assert_equal [n1, n5, n2, n4, n3].map(&:id), records.map(&:id)
29-
end
30-
end
20+
# n1 needs to move to front, and n2 needs to move in front of n4, n3
21+
assert_equal [n1, n5, n6, n2, n4, n3].map(&:id), model.sort_by_ancestry(model.all.sort_by(&:id).reverse).map(&:id)
22+
# none are parents
23+
#assert_equal [n5, n4, n3].map(&:id), model.sort_by_ancestry([n5, n4, n3]).map(&:id)
24+
# at the same level
25+
assert_equal [n3, n4].map(&:id), model.sort_by_ancestry([n3, n4]).map(&:id)
26+
# n1 needs to move below both
27+
assert_equal [n1, n5, n2].map(&:id), model.sort_by_ancestry([n5, n2, n1]).map(&:id)
28+
# n1 needs to move below even a double descendant
29+
#assert_equal [n1, n5, n4].map(&:id), model.sort_by_ancestry([n5, n4, n1]).map(&:id)
3130
end
3231
end
3332

3433
def test_sort_by_ancestry_with_block
3534
AncestryTestDatabase.with_model :extra_columns => {:rank => :integer} do |model|
35+
# - n1 (0)
36+
# - n5 (0)
37+
# - n3 (3)
38+
# - n2 (1)
39+
# - n4 (0)
40+
# - n6 (1)
3641
n1 = model.create!(:rank => 0)
3742
n2 = model.create!(:rank => 1)
38-
n3 = model.create!(:rank => 0, :parent => n1)
43+
n3 = model.create!(:rank => 3, :parent => n1)
3944
n4 = model.create!(:rank => 0, :parent => n2)
40-
n5 = model.create!(:rank => 1, :parent => n1)
45+
n5 = model.create!(:rank => 0, :parent => n1)
4146
n6 = model.create!(:rank => 1, :parent => n2)
4247

43-
records = model.sort_by_ancestry(model.all.sort_by(&:rank).reverse) {|a, b| a.rank <=> b.rank}
44-
assert_equal [n1, n3, n5, n2, n4, n6].map(&:id), records.map(&:id)
48+
sort = -> (a, b) { a.rank <=> b.rank }
49+
records = model.sort_by_ancestry(model.all.sort_by(&:rank).reverse, &sort)
50+
# all parents, all children
51+
assert_equal [n1, n5, n3, n2, n4, n6].map(&:id), records.map(&:id)
52+
# all parents, some children
53+
assert_equal [n1, n5, n2].map(&:id), model.sort_by_ancestry([n2, n1, n5],&sort).map(&:id)
4554
end
4655
end
4756
end

0 commit comments

Comments
 (0)