ライブラリのバージョンアップ等で親クラスが子クラスが持つ特定の定数に依存するようになりエラーが発生することがあり。。。
特定のクラスを継承したクラスの中で特定の定数を持たないクラスを探すコードを書いたのメモしておきます📝
サンプルコード
例えば、以下のような子クラスに定義されたATTRIBUTES
を参照して、hashを作るようなメソッドが親クラスに実装されていて、一部の子クラスにATTRIBUTES
が定義されていないケースをサンプルにしています。
今回のケースではEnglishName
がATTRIBUTES
を持たないのでEnglishName.new.attributes
実行時にuninitialized constant EnglishName::ATTRIBUTES
が発生しています。
class BaseName def attributes self.class::ATTRIBUTES.inject({}) do |result, attr| result.tap { result[attr] = public_send(attr) } end end end class JapaneseName < BaseName ATTRIBUTES = [:first_name, :last_name] def first_name 'Taro' end def last_name 'Yamada' end end class EnglishName< BaseName def first_name 'John' end def middle_name 'Fitzgerald' end def last_name 'Smith' end end JapaneseName.new.attributes #=> {:first_name=>"Taro", :last_name=>"Yamada"} EnglishName.new.attributes #=> `attributes': uninitialized constant EnglishName::ATTRIBUTES (NameError)
任意の定数を持たない特定のクラスを継承したクラスを見つけるコード
今回はActiveSupportのコア拡張を使ってコードを作成します🚃
以下がエラーが発生する、BaseName
を継承していて定数ATTRIBUTES
を持たないクラスを取得するスクリプトです。
parent_class = Base target_const = :ATTRIBUTES puts parent_class.subclasses.select do |sub| sub.constants.exclude?(target_const) end #=> EnglishName
subclasses
で子クラスの配列を取得してconstants
でそれぞれの子クラスの持つ定数を取得して、ATTRIBUTES
を持たないクラスを取得しています💻
おわりに
RubyとActiveSupportのコア拡張を使うと割と自由にクラスを探索出来て便利ですね✨