Collecting Recursively

by Sean Cribbs

Yesterday I was working with an acts_as_tree model and wanted to get all children of the current model as an array. Since there's no descendants method, this is what I came up with.

module Enumerable
  def rcollect(&block)
    self.map do |item|
      collection = block.call(item).compact rescue []
      if collection && !collection.empty?
        [item, collection.rcollect(&block)]
      else
        item
      end
    end
  end
end

class Object
  def recurse_collecting(&block)
    [self, block.call(self).compact.rcollect(&block)]
  end
end

Then when I want the model and all its children I do:

model.recurse_collecting(&:children)

May not be useful to everyone, but I found it to be a fun exercise.

© 2006-present Sean CribbsGithub PagesTufte CSS