Search code examples
ruby

Look up all descendants of a class in Ruby


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.)


Solution

  • Here is an example:

    class Parent
      def self.descendants
        ObjectSpace.each_object(Class).select { |klass| klass < self }
      end
    end
    
    class Child < Parent
    end
    
    class GrandChild < Child
    end
    
    puts Parent.descendants
    puts Child.descendants
    

    puts Parent.descendants gives you:

    GrandChild
    Child
    

    puts Child.descendants gives you:

    GrandChild