Railsでクラス数が増えてくるとフォルダ分けしたくなることがあります。その場合、Javaのパッケージと同じように、モデルをフォルダ分けして、モジュール下に宣言してやることになります。以下のような感じです。
class ModuleName::ModelName < ActiveRecord::Base
end
ところが、belongs_toとかhas_manyとかの関連を解決する際に、以下のようなエラーが出て手がつけられなくなることがあります。悪名高きActiveSupportの「XXX is not missing constant YYY」ですね。
ArgumentError in Hogehoge/Fugafuga#nanika
ModuleName is not missing constant ModelName
<<中略>>
c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:253:in
`load_missing_constant'
c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:468:in
`const_missing'
c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:486:in
`send'
c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.1.2/lib/active_support/dependencies.rb:486:in
`const_missing'
c:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.1.2/lib/active_record/base.rb:1912:in `compute_type'
c:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.1.2/lib/active_record/reflection.rb:133:in `send'
c:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.1.2/lib/active_record/reflection.rb:133:in `klass'
c:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.1.2/lib/active_record/associations/
belongs_to_association.rb:44:in `find_target'
c:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.1.2/lib/active_record/associations/
association_proxy.rb:192:in `load_target'
c:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.1.2/lib/active_record/associations/
association_proxy.rb:99:in `reload'
c:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.1.2/lib/active_record/associations.rb:1092:in `image'
<<中略>>
Railsのソースコードを追った感じでは、load_missing_constantメソッドの中でModuleName.const_defined?(ModelName)していて、これtrueを返すと、上記の例外を投げます。嫌なにおいがぷんぷんとするのですが、あまり深追いしないようにします。
で、この現象、モデルやコントローラの中で、「ModelName」で呼び出していると発生するのですが、「ModuleName::ModelName」と書いてやると発生しなくなります。必ず再現するわけでもないようで、結構長いこと私はこの現象が発生していることに気づきませんでした。
結構はまったのが、本現象は、単一テーブル継承でtypeにモジュール名無しのモデル名を書き込んでしまっても発生することです。
本現象はRails2.1.2で発生していますが2.3.2でも発生しているっぽいです。この問題で2時間くらい悩んでしまった。。。