ActiveRecordを使っていたところ、意外な挙動をすることがありましたが、実はRubyの標準機能で実現できることでした。
initialize…されない!?
ActiveRecordにある処理を組む過程で、(素直にafter_initializeを使えばいいものを)何を思ったかinitializeのオーバーライドを行って実装する…というように書いてしまったのですが、そのinitialize内の処理が、ときどきしか実行されないということに気づきました。
調べてみると、ActiveRecordを本当にnewする際にはinitializeが呼ばれるのですが、ActiveRecord::Relationから実体化するなど、DBから引いてきたときにはinitializeは走らないとのことでした。
Ruby標準で作れる、未初期化オブジェクト
では、一体どんな手法を使えばinitializeしないオブジェクトを作れるのだろうと調べてみたら、じつは標準ライブラリにClass#allocateというのがあって、これを使うとまさに「特定のクラスだけど、inializeしていないオブジェクト」を作れるということでした。
ActiveRecordの場合は、「どうせすぐにデータを詰めるのだから、initializeは無駄」という最適化なのでしょうが、なかなか使う機会の少ない機能かなという気もしています。
余談
initializeをオーバーライドする際に、引数は直接superに投げるだけで、オーバーライドした中では使わない、というような状況の場合、変数名を省略することもできます。
def initialize(*)
#元の引数、ブロックはそのままsuperへ
super
#引数を使わない拡張処理
end