Railsのdevelopment環境で開発をしている際に、表題のタイトルのエラーが発生したため調査をしました。
development環境のみで発生するのは以下の設定が要因です。
config.cache_classes = false
Python
この設定は、アプリケーション・サーバーを再起動せずにコードの変更を反映させることができるようになります。変更対象のソースコードは予めconfig.autoload_pathsに追加しておいたパスのものが監視されています。
発生条件は以下のようなケースです。
class Hoge
def fuga
Fuga.new
end
end
Python
hoge = Hoge.new
ActiveSupport::Dependencies.clear # ソースコード変更を検知してreloadが実行されたと仮定
hoge.fuga # ここで発生
Python
rubyのクラスは定数として管理されています。クラス名を参照するということは、rubyにおいては定数を参照しているということになります。
そして、初回起動時に全てのクラスが読み込まれますが、reload時には全ては読み込まれません。reloadが発生すると定数が全てクリアされ、アクセスしたクラスを再度loadし直すという挙動になっています。
ActiveSupport::Dependencies.clearが呼び出されると、All or Nothingで定数がクリアされるので、reload後はアクセスした度に読み込み直していくことになります。
上記の通り、問題は2点存在します。
この場合、1. のケースを防ぐならunloadableというメソッドをクラスにつけることで回避することができるはず。 …①
また、2.を防ぐためには、以下2通りの方法が考えられます。
解決方法を3つ提示しました。ので整理して実際に順に試してみます。