はじめに
Deviseを使用する中で、特定の状況においてConfirmationメールの送信に使われるテンプレートのパスを変更する必要が生じました。Deviseの公式Wikiにはガイドラインが記載されていましたが、Rails7ではなぜかその方法では解決できなかったため、Deviseのソースコードを分析し、別の解決策を探りました。
方法 1: headers_for メソッドのオーバーライド
Deviseでは、Devise::Mailer
のHelpers
モジュール内にある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
DeviseMailer
でheaders_for
メソッドをオーバーライドし、super
とmerge!
を使用してテンプレートパスを変更できます。
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::Mailer
のHelpers
モジュール内の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つの方法を見てきました。プロジェクトの状況に応じて適切に使用してください。