Ruby on Railsで自動読込されるファイルのルール
相変わらず仕事ではRailsアプリなRubyを書いていて、必然的にRubyに関わる時間が多くなっています。
もともと1.6ぐらいの時にはRubyを結構使っていたので、新機能のキャッチアップが大変だったり、Ruby的な発想に慣れるのに苦労しながらもなんとか仕事になるぐらいにはコードが書けているつもりです。
それにつけても慣れないのがRailsです。(RSpecは慣れたくないぐらい嫌いです)
「設定より規約」を全面に押し出しているのはわかりますが、「その規約知らんかった」が多すぎて嫌になってきています。
例えば、今日ハマったのはmoduleに定義したクラス定義の自動読み込みです。
具体的には、こんなコードを考えます。
code: fuga_fuga.rb
module HogeHoge
class FugaFuga
def say
p 'fuga-!'
end
end
class PiyoPiyo
def say
p 'piyo-!'
end
end
end
あるモジュールにふたつのクラスが属している。とてもシンプルなコードです。
こうして書いたコードをbin/rails c --sandboxなどとして起動したREPL環境で使おうとすると
HogeHoge::FugaFuga.new(...)は問題なく処理できますが、HogeHoge::PiyoPiyo.new(...)はuninitialized constantというエラーで怒られます。
嫌なのは、先にHogeHoge::FugaFuga.new(...)を実行しているとHogeHoge::PiyoPiyo.new(...)が通る点。逆はダメです。
Railsにある程度親しんだ人ならトリックはおわかりだと思います。
そう、Railsでは、ファイル名と読み込みたいクラス名との一致が必要なんだそうですね。
なので、正しくはFugaFugaをfuga_fuga.rbに、PiyoPiyoをpiyo_piyo.rbに分けて書いてやれば、どちらも問題なく読み込まれます。
そういう規約なんだと言われれはそれまでなんですが、普通にirbを使って読み込ませるときはrequireなりloadなりを使って、ファイル単位で処理しているつもりでやっていたので、読み込める状態にあるクラスが存在している同じファイル内の同じモジュールに属するクラスであれば問題なく読まれるだろうと思ったのが間違いでした。
特に順序によってできたりできなかったりという所にひどく頭を悩ませて、解決策に行き着くまで、昨日は半日を潰していしまいました。
Railsのこういう余計な暗黙のルールがあるところ、好きじゃないです。