We often land on a situation where we want to know all the classes which have been inherited from a given class; One such scenario can be while using Single Table Inheritance in Rails.
Here, we might want to identify those classes that are derived from a class.
Rails ~> 3.0
already has such a feature provided
by ActiveSupport
Class#descendants.
To cater to such requirements in Ruby,
Ruby 3.1 introduced Class#descendants
that returns
an array of classes
directly or indirectly inheriting from the receiver, without
including the receiver or singleton classes.
Before
We can implement Class#descendants
using the code
snippet given below-
class Animal
def self.descendants
ObjectSpace.each_object(Class).select { |klass| klass < self }
end
end
class Mammal < Animal; end
class Dolphin < Mammal; end
class Bat < Mammal; end
class Reptile < Animal; end
class Crocodile < Reptile; end
Animal.descendants
=> [Reptile, Bat, Crocodile, Dolphin, Mammal]
Mammal.descendants
=> [Bat, Dolphin]
Reptile.descendants
=> [Crocodile]
After
class Animal; end
class Mammal < Animal; end
class Dolphin < Mammal; end
class Bat < Mammal; end
class Reptile < Animal; end
class Crocodile < Reptile; end
Animal.descendants
=> [Reptile, Crocodile, Mammal, Bat, Dolphin]
Mammal.descendants
=> [Bat, Dolphin]
Reptile.descendants
=> [Crocodile]
For more discussion related to this change, please refer to this PR.