ActionMailでmailを実行しない場合は、NullMailが返却される
事象
ActionMailer::Base
を継承したクラスのメソッドをコール時に、メソッド内で mail
が呼び出されていない場合は、 ActionMailer::Base::NullMail
が返却される。(通常は Mail::Message
)
ちなみに、 deliver_now などのメソッドを実行しても、エラーとならずに nil が返却されるだけなので気づきにくい
経緯
mail を deliver_now した後に、 mail の subject を取得したかった。しかし、mail.subject で、 nil しか取得できない。
class TestMailer < ActionMailer::Base
def test_mail
# selfだとdeliver_now時にエラーになる
if TestMailer.use_api?
# using Send Grid API
else
mail(to: "to@example.com", subject: "test mail")
end
end
def self.use_api?
Rails.env.production?
end
end
mail = TestMailer.test_mail
mail.deliver_now
mail.subject # <= nil
解決
mailメソッドは呼ぶが、apiを使用した場合は、送信しない。
class TestMailer < ActionMailer::Base
def test_mail
# selfだとdeliver_now時にエラーになる
if TestMailer.use_api?
# using Send Grid API
else
mail(to: "to@example.com", subject: "test mail")
end
end
def self.deliverable?
!self.use_api?
end
def self.use_api?
Rails.env.production?
end
end
mail = TestMailer.test_mail
mail.deliver_now if TestMailer.deliverable?
mail.subject # <= "test mail"
tips
deliver_now時にもう一度、処理を行われる?
if TestMailer.use_api?
で self
を敢えて指定していません。
selfを指定すると TestMailer.test_mail
時はエラーにならないのですが、 deliver_now
実行時に、 NoMethodError: undefined method 'use_api?'
とエラーが発生します。