ActionMailerの個別のクラスで、interceptorみたいなことをやりたい
ActionMailerにはinterceptorという機能があって、メールを送信するときにいろいろと処理を挟むことができます。
class TsukaInterceptor
def self.delivering_email(message)
message.title = "[development] #{message.title}"
end
end
みたいなクラスを作っておいて、initializerなどで
ActionMailer::Base.register_interceptor(TsukaInterceptor) if Rails.env.development?
とやっておけば、development環境で送信するメールのサブジェクトには、すべて [development]
がつくようになります。
interceptorクラスのクラスメソッド delivering_email
に渡される引数 message
は、Mail::Messageクラスのオブジェクトです。
というようにinterceptorはとても便利なのですが、ActionMailer全体に影響してしまうので、個別のActionMailerクラスで別のことをやりたいときに困ります。
たとえば、あるActionMailerクラスを使ってdevelopment環境からメール送信をするときだけ、メールのあて先を変更したいとき。
interceptorを使っちゃうと全部のMailerに影響してしまうし、inteceptorクラスのdelivering_emailメソッド内で切り分けようとしても、Mail::MessageオブジェクトからはActionMailer::Baseクラスはわからないのです。
どうしようかなとちょっと悩んでtwitterでつぶやいたら、1分後くらいに元同僚のK和さんが「AbstractController::Callbacksを使ったらいいですよ」と教えてくれました。
さっそくやってみます。
class TsukaMailer < ActionMailer::Base
if Rails.env.development?
include AbstractController::Callbacks
after_filter :check_to
def check_to
message.to = "tsuka@example.com"
end
private :check_to
end
def hoge
...
end
end
としたら、development環境のときだけ、メールのあて先がすべて check_to
メソッドの中で指定したものに変わりました。
message
というのは、Mail::Messageオブジェクトで、以下のように attr_internal
宣言されているのでこういうふうにアクセスできます。
https://github.com/rails/rails/blob/4-1-stable/actionmailer/lib/action_mailer/base.rb#L558