Rubyはメタプログラミングに秀でた言語ですが、メタプログラミングを多用したRailsなどでは、思わぬ挙動にハマることがあります。
REPLコンソール
irb
やpry
、Railsの画面内に表示させるweb-console
など各種ありますが、入力したものをその場で実行するREPLコンソールは便利なものです…が、これが罠になった例がありました。
REPLコンソールでは、入力して実行したコードの結果を表示するのですが、表示のために#to_s
、あるいは#inspect
と言ったメソッドを実行します。通常であれば特に問題ない操作なのですが、ときにはそれでオブジェクトが状態を変えてしまうことがありえます。
メーラーと中身
Rails標準で搭載されているActionMailerですが、これもまた黒魔術を多用した構成となっています。そして、メーラーを作成してREPLで評価すると、以下のようになります。
> SomeMailer.some_method(args)
=> #<Mail::Message ....>
実はこの時点で、もう罠にハマっています。
実際の動作
メーラーで作成したもののクラスはActionMailer::MessageDelivery
というものです。このクラスは、delivery_now
など配信制御系のメソッドを除けば、内部で持つMail::Message
へのDelegator
となっているので、#inspect
を実行すればその瞬間にメール生成処理が走って、そのインスタンスの詳細を返しています。
さらに、このメールを.deliver_later
しようとした場合、事前にMail::Message
を生成してしまっているとエラーになります。
結論
REPLで「結果を表示する」こと自体も1つの処理で、時にはそれが原因でオブジェクトそのものが挙動を変化させてしまうことすら、ありえます。挙動がドキュメントやコードで確認できるものについては、結果を鵜呑みにせず、資料を丁寧に追っていくほうが正解かもしれません。