4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

株式会社スピードリンクジャパンAdvent Calendar 2023

Day 6

【Devise】メーラーのテンプレートパスをカスタマイズする

Last updated at Posted at 2023-12-06

はじめに

Deviseを使用する中で、特定の状況においてConfirmationメールの送信に使われるテンプレートのパスを変更する必要が生じました。Deviseの公式Wikiにはガイドラインが記載されていましたが、Rails7ではなぜかその方法では解決できなかったため、Deviseのソースコードを分析し、別の解決策を探りました。

方法 1: headers_for メソッドのオーバーライド

Deviseでは、Devise::MailerHelpersモジュール内にあるheaders_forメソッドを通じて、メール送信に必要な全てのヘッダ情報を生成します。このメソッドは、メールの件名(subject)、受信者(to)、送信者(from)、返信先アドレス(reply_to)、テンプレートパス(template_path)、そしてテンプレート名(template_name)を含むハッシュを作成します。

Devise::Mailersヘルパーのheaders_forメソッド
https://github.com/heartcombo/devise/blob/main/lib/devise/mailers/helpers.rb#L31

module Devise
  module Mailers
    module Helpers
      ...
      protected

      def headers_for(action, opts)
        headers = {
          subject: subject_for(action),
          to: resource.email,
          from: mailer_sender(devise_mapping),
          reply_to: mailer_reply_to(devise_mapping),
          template_path: template_paths,
          template_name: action
        }.merge(opts)
        @email = headers[:to]
        headers
      end
      ...
    end
  end
end

DeviseMailerheaders_forメソッドをオーバーライドし、supermerge!を使用してテンプレートパスを変更できます。

DeviseMailerのheaders_forメソッド

class DeviseMailer < Devise::Mailer
  include Devise::Controllers::UrlHelpers
  
  def headers_for(action, opts)
    super.merge!({template_path: 'my_mailer'}) # app/views/my_mailer
  end
end

この方法では、headers_forメソッド内でsuperを呼び出し、Devise::MailerHelpersモジュール内のheaders_forメソッドを実行してから、結果を受け取ります。その後merge!メソッドを使用して返されたハッシュのtemplate_pathを希望のパス(例:'my_mailer')に更新します。これによりDeviseに新しいディレクトリでのメールテンプレートを使用するよう指示します。

方法 2: template_paths メソッドのオーバーライド

次はもっと直接的で簡単な方法です。Deviseはtemplate_pathsメソッドを使用してメールテンプレートのパスを決定します。template_pathsメソッドは、文字列で構成されたパスを要素とする配列を返します。

Devise::Mailersヘルパーのtemplate_pathsメソッド
https://github.com/heartcombo/devise/blob/main/lib/devise/mailers/helpers.rb#L58

module Devise
  module Mailers
    module Helpers
      ...
      protected

      def template_paths
        template_path = _prefixes.dup
        template_path.unshift "#{@devise_mapping.scoped_path}/mailer" if self.class.scoped_views?
        template_path # ["devise_mailer', 'devise/mailer']
      end
      ...
    end
  end
end

template_pathsメソッドをオーバーライドし、戻り値を変更することで、メールテンプレートのパスを簡単に変更できます。

DeviseMailerのtemplate_pathsメソッド

class DeviseMailer < Devise::Mailer
  include Devise::Controllers::UrlHelpers

  def template_paths
    ['my_mailer'] # app/views/my_mailer
  end
end

この方法では、簡単に希望するパスを配列に入れて返すだけです。

結論

Deviseのテンプレートパスを変更する方法として、headers_forメソッドのオーバーライドとtemplate_pathsメソッドのオーバーライドの2つの方法を見てきました。プロジェクトの状況に応じて適切に使用してください。

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?