railsでAction Mailerを使っていて、メールのテンプレートを条件分岐で一部変更したい、なんてときに使える方法。

メール送信クラスからmailメソッドを実行するときにtemplate_pathtemplate_nameの引数に具体的な格納先を指定すればOK。

例えばapp/mailers/hello_mailer.rbというクラスがあって、以下のようなコードになっている場合。

class HelloMailer < ApplicationMailer
  def mail_to_user(user_id)
    @user = User.find(user_id)
    mail(to: @user.email, subject: 'こんにちは!')
  end
end

テンプレートの場所はデフォルトだとapp/views/hello_mailer/mail_to_user.text.erbみたいになる。

このテンプレートの場所をapp/views/mails/hello_mailer/hello_hello.text.erbにしたいときは以下のようにオプションを指定すればOK。

viewsから下のディレクトリをtemplate_pathに指定して、ファイル名はtemplate_nameに指定する。

class HelloMailer < ApplicationMailer
  def mail_to_user(user_id)
    @user = User.find(user_id)
    mail(to: @user.email, subject: 'こんにちは!', template_path: 'mails/hello_mailer', template_name: 'hello_hello')
  end
end

もちろん以下のようにifで内部的に分岐してもOK。

余談だけど、メールは誤送信とかしたときのリカバリが高コストなこともあり、分岐をしたら分岐ごとにテストコードを書いておきたい。

class HelloMailer < ApplicationMailer
  def mail_to_user(user_id)
    @user = User.find(user_id)
    if @user.special?
      mail(to: @user.email, subject: 'あなただけに特別なお知らせ!', template_path: 'mails/hello_mailer', template_name: 'hello_hello')
    else
      mail(to: @user.email, subject: 'こんにちは!')
    end
  end
end

テンプレートを内部処理で分岐させたいときにも有効なんだけど、メールの種類が増えてきたときにviews直下にmailerごとのディレクトリがあるとごちゃついて嫌になるときがある。

そんなときはメール用のディレクトリとしてviews/mailsみたいのを作って、そこにmailerごとにディクレトリ&ファイルを置いておくとわかりやすくて管理しやすくなっておすすめ。

この記事の環境情報

  • Ruby on Rails 7.0.4
  • actionmailer 7.0.4
  • バナナを買い忘れた