I can easily ascend the class hierarchy in Ruby:
String.ancestors # [String, Enumerable, Comparable, Object, Kernel]
Enumerable.ancestors # [Enumerable]
Comparable.ancestors # [Comparable]
Object.ancestors # [Object, Kernel]
Kernel.ancestors # [Kernel]
Is there any way to descend the hierarchy as well? I'd like to do this
Animal.descendants # [Dog, Cat, Human, ...]
Dog.descendants # [Labrador, GreatDane, Airedale, ...]
Enumerable.descendants # [String, Array, ...]
but there doesn't seem to be a descendants
method.
(This question comes up because I want to find all the models in a Rails application that descend from a base class and list them; I have a controller that can work with any such model and I'd like to be able to add new models without having to modify the controller.)
Alternatively (updated for ruby 1.9+):
Ruby 1.8 compatible way:
Note that this won't work for modules. Also, YourRootClass will be included in the answer. You can use Array#- or another way to remove it.
You can
require 'active_support/core_ext'
and use thedescendants
method. Check out the doc, and give it a shot in IRB or pry. Can be used without Rails.This method will return a multidimensional hash of all of an Object's descendants.
Ruby Facets has Class#descendants,
It also supports a generational distance parameter.
A simple version that give an array of all the descendants of a class:
Using descendants_tracker gem may help. The following example is copied from the gem's doc:
This gem is used by the popular virtus gem, so I think it's pretty solid.