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