Thursday, February 21, 2008

Massage Rails better_nested_set full_set into a hierarchy - JSON

better_nested_set is a great Rails plugin for working with certain types of hierarchical data. The typical example where better_nested_set is used is for a threaded message board. better_nested_set will allow you to pull in a message and all its descendants with a single full_set call. The data that is returned includes a level field that allows you to indent the messages to indicate the appropriate parental relationships.

Sometimes, however, it may be necessary to take that full_set and turn it into a hierarchical data structure. For example when working with Ext JS you may want to feed this data to a tree control that needs a hierarchical JSON representation of the data. Here is some sample code that will do the necessary data massaging:

# Returns hierarchical data structure rooted at this node. When converting to
# json make sure to remove :parent to avoid circular reference:
# message.full_hierarchy.to_json(:only => [:id, :subject, :children, ...])
def full_hierarchy
the_full_set = full_set
ancestry = [build_node(the_full_set.shift)]
while !the_full_set.empty?
next_node = build_node(the_full_set.shift)
while next_node[:level] <= ancestry.last[:level]
ancestry.pop
end
ancestry.last[:children] << next_node
ancestry.last[:leaf] = false
next_node[:parent] = ancestry.last
ancestry << next_node
end
ancestry[0]
end
private
# active record Message to node for hierarchy
def build_node(message)
ret = {}
ret[:id] = message.id
ret[:subject] = message.subject
ret[:message] = message.message
ret[:level] = message.level
ret[:account_id] = message.account_id
ret[:author] = message.account.login
ret[:children] = []
ret[:parent] = nil
ret[:leaf] = true
ret
end
view raw gistfile1.rb hosted with ❤ by GitHub