Skip to content

Instantly share code, notes, and snippets.

@hlubek
Created October 20, 2009 14:36
Show Gist options
  • Select an option

  • Save hlubek/214283 to your computer and use it in GitHub Desktop.

Select an option

Save hlubek/214283 to your computer and use it in GitHub Desktop.
A nested array method for awesome nested set
class Foo < ActiveRecord::Base
acts_as_nested_set
extend NestedSet::Helper
# Return a nested array
# representation of foo objects
def self.as_tree
result_to_array(find(:all, :order => quoted_left_column_name))
end
end
module NestedSet
module Helper
def result_to_array(result, options = {}, &block)
array = []
inner_recursion = options.delete(:inner_recursion)
result_set = inner_recursion ? result : result.dup
parent_id = (options.delete(:parent_id) || result_set.first[result_set.first.parent_column_name]) rescue nil
level = options[:level] || 0
options[:children] ||= 'children'
options[:methods] ||= []
options[:nested] = true unless options.key?(:nested)
options[:symbolize_keys] = true unless options.key?(:symbolize_keys)
if options[:only].blank? && options[:except].blank?
options[:except] = [:left_column, :right_column, :parent_column].inject([]) do |ex, opt|
column = acts_as_nested_set_options[opt].to_sym
ex << column unless ex.include?(column)
ex
end
end
siblings = options[:nested] ? result_set.select { |s| s[s.parent_column_name] == parent_id } : result_set
siblings.each do |sibling|
result_set.delete(sibling)
node = block_given? ? block.call(sibling, level) : Serializer.new(sibling, :only => options[:only], :except => options[:except], :methods => options[:methods]).serializable_record
if options[:nested]
opts = options.merge(:parent_id => sibling.id, :level => level + 1, :inner_recursion => true)
childnodes = result_to_array(result_set, opts, &block)
node[options[:children]] = childnodes if !childnodes.empty? && node.respond_to?(:[]=)
end
array << (options[:symbolize_keys] && node.respond_to?(:symbolize_keys) ? node.symbolize_keys : node)
end
unless inner_recursion
result_set.each do |orphan|
node = (block_given? ? block.call(orphan, level) : Serializer.new(orphan, :only => options[:only], :except => options[:except], :methods => options[:methods]).serializable_record)
array << (options[:symbolize_keys] && node.respond_to?(:symbolize_keys) ? node.symbolize_keys : node)
end
end
array
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment