Techioz Blog

Ruby でクラスのすべての子孫を検索する

概要

Ruby ではクラス階層を簡単に登ることができます。

String.ancestors     # [String, Enumerable, Comparable, Object, Kernel]
Enumerable.ancestors # [Enumerable]
Comparable.ancestors # [Comparable]
Object.ancestors     # [Object, Kernel]
Kernel.ancestors     # [Kernel]

階層を下降する方法もありますか?これをやりたいのですが

Animal.descendants      # [Dog, Cat, Human, ...]
Dog.descendants         # [Labrador, GreatDane, Airedale, ...]
Enumerable.descendants  # [String, Array, ...]

しかし、子孫メソッドはないようです。

(この質問は、基本クラスから派生した Rails アプリケーション内のすべてのモデルを検索してリストしたいために発生します。そのようなモデルを操作できるコントローラーがあり、新しいモデルを追加できるようにしたいと考えています。コントローラーを変更する必要はありません。)

解決策

以下に例を示します。

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

put Parent.descendants は次のようになります。

GrandChild
Child

put Child.descendants は次のようになります。

GrandChild