I'm using the awesome_nested_set plugin in my Rails project. I have two models that look like this (simplified):
class Customer < ActiveRecord::Base
  has_many :categories
end
class Category < ActiveRecord::Base
  belongs_to :customer
  # Columns in the categories table: lft, rgt and parent_id
  acts_as_nested_set :scope => :customer_id
  validates_presence_of :name
  # Further validations...
end
The tree in the database is constructed as expected. All the values of parent_id, lft and rgt are correct. The tree has multiple root nodes (which is of course allowed in awesome_nested_set).
Now, I want to render all categories of a given customer in a correctly sorted tree like structure: for example nested <ul> tags. This wouldn't be too difficult but I need it to be efficient (the less sql queries the better).
Update: Figured out that it is possible to calculate the number of children for any given Node in the tree without further SQL queries: number_of_children = (node.rgt - node.lft - 1)/2. This doesn't solve the problem but it may prove to be helpful.
It would be nice if nested sets had better features out of the box wouldn't it.
The trick as you have discovered is to build the tree from a flat set:
see below:
def tree_from_set(set) #set must be in order
  buf = START_TAG(set[0])
  stack = []
  stack.push set[0]
  set[1..-1].each do |node|
    if stack.last.lft < node.lft < stack.last.rgt
      if node.leaf? #(node.rgt - node.lft == 1)
        buf << NODE_TAG(node)
      else
        buf << START_TAG(node)
        stack.push(node)
      end
    else#
      buf << END_TAG
      stack.pop
      retry
    end
  end
  buf <<END_TAG
end
def START_TAG(node) #for example
  "<li><p>#{node.name}</p><ul>"
end
def NODE_TAG(node)
  "<li><p>#{node.name}</p></li>"
end
def END_TAG
  "</li></ul>"
end 
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With