@kyanny's blog

My life. Opinions are my own.

STI で継承したモデルのクラス名を参照したら uninitialized constant エラー

STI and uninitialized constant error | Blogger cat

これとまったく同じ状況になった。 STI (Single Table Inheritance) を使って継承した子のモデルのクラス名(定数)を参照すると NameError: uninitialized constant が発生する。先に親のモデルのクラス名を一回参照したあとでは発生しない。

これは Rails のモジュールロードの仕組みに起因していて、

class Script < ActiveRecord::Base
end

class ScriptTask < Script
end

class ScriptComponent < Script
end

この例だと Script という定数が未定義だったら script.rb を探す。同様に ScriptTask なら script_task.rb を探す。ここで期待したファイルがないとエラーになるようだ。これを回避するために require_dependency を使え、というアドバイスもよく見つかる。

で、 STI 使った親クラスと子クラスを同じファイルに書いていて、ファイル名が親クラスと対応するものの場合、子クラスと対応する名前のファイルがないのでエラーになるということ。なので子クラスは別のファイルに書いてやればいい。

# script.rb
class Script < ActiveRecord::Base
end
# script_task.rb
class ScriptTask < Script
end
# script_component.rb
class ScriptComponent < Script
end