Skip to content

Arranging an array as a tree (was: arrange_as_array)

Keenan Brock edited this page Mar 11, 2023 · 1 revision

If you want to have your tree in an ordered List accordingly to the tree structure (for example to represent the children in a sorted out list in a select), you can use this snippet:

class Node < ActiveRecord::Base
  has_ancestry
end

a = Node.create(:name => "a")
b = Node.create(:name => "b")
c = Node.create(:name => "c", :parent => b)
d = Node.create(:name => "d", :parent => b)
e = Node.create(:name => "e", :parent => c)

Node.sort_by_ancestry(Node.ordered_by_ancestry_and(:name)).each{|n| puts "#{'-' * n.depth} #{n.name}" }
 - a
 - b
 -- c
 --- e
 -- d

Node.sort_by_ancestry(Node.ordered_by_ancestry_and(:name => :desc)).each{|n| puts "#{'-' * n.depth} #{n.name}" }
 - b
 - a
 -- d
 -- c
 --- e

# using ruby to sort fixes some edge cases
sort_by_name = Proc.new {|a, b| a <=> b}
reverse_sort_by_name = Proc.new {|a, b| b <=> a}

Node.sort_by_ancestry(Node.all, &sort_by_name).each{ |n| puts "#{'-' * n.depth} #{n.name}" }
Node.sort_by_ancestry(Node.all, &reverse_sort_by_name).each{|n| puts "#{'-' * n.depth} #{n.name}" }

Note: If you want to sort by `created_at`, most applications will be served sorting by `id`.