0
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?

【rails】devise mailer.previewの作成方法

Posted at

はじめに

こんにちは。アメリカ在住で独学エンジニアを目指している Taira です。
現在、Rails アプリを devise を用いて作成しています。

会員登録画面の実装が完了したのですが、そのメールの内容を確認したいと思い、Rails チュートリアルで test/mailers/previews/user_mailer_preview.rb を実装したことを思い出しました。
そこで devise でもその機能を実装しようと考え、Rails チュートリアルを参照しつつ devise のソースコードの中から必要な情報を抽出して devise_mailer_preview.rb を作成しました。

Rails チュートリアルで実装したコード

class UserMailerPreview < ActionMailer::Preview
  # Preview this email at
  # http://localhost:3000/rails/mailers/user_mailer/account_activation
  def account_activation
    user = User.first
    user.activation_token = User.new_token
    UserMailer.account_activation(user)
  end
end

上記が実際に Rails チュートリアルで実装したコードです。
ここでポイントとなるのは、

  • ActionMailer::Preview を継承すること
  • メールで使用するトークンを設定すること
  • from や to、subject を設定するメソッドの実装をすること

devise での mailer_preview の実装

1. confirmation_token の生成

devise のソースコード devise/lib/devise.rb を参照すると、以下のような記述があります。

module Devise
  autoload :TokenGenerator, 'devise/token_generator'
  # ...省略
  mattr_accessor :token_generator
  @@token_generator = nil
end

ここで token 生成の処理が書かれており、devise モジュール内で token_generator というクラス変数が設定されていることがわかります。

さらに、devise/lib/devise/token_generator.rb には以下のような内容があります(一部省略)。

def generate(klass, column)
  key = key_for(column)
  loop do
    raw = Devise.friendly_token
    enc = OpenSSL::HMAC.hexdigest(@digest, key, raw)
    break [raw, enc] unless klass.to_adapter.find_first({ column => enc })
  end
end

これを参考に、confirmation_token を以下のように設定できます。

raw, enc = Devise.token_generator.generate(User, :confirmation_token)
user.confirmation_token ||= enc

ここで使用するのは、エンコードされた encconfirmation_token として設定します。

2. devise の mailer メソッドの利用

devise/app/mailers/devise/mailer.rb を参照すると、

if defined?(ActionMailer)
  class Devise::Mailer < Devise.parent_mailer.constantize
    include Devise::Mailers::Helpers

    def confirmation_instructions(record, token, opts = {})
      @token = token
      devise_mail(record, :confirmation_instructions, opts)
    end

この confirmation_instructions メソッドを利用して、最終的に mailer_preview を以下のように実装できます。

# Preview all emails at http://localhost:3000/rails/mailers/devise_mailer
class DeviseMailerPreview < ActionMailer::Preview
  # http://localhost:3000/rails/mailers/devise_mailer/confirmation_instructions
  def confirmation_instructions
    user = User.first
    raw, enc = Devise.token_generator.generate(User, :confirmation_token)
    user.confirmation_token ||= enc
    Devise::Mailer.confirmation_instructions(user, user.confirmation_token)
  end
end

【追記】devise のメソッドを使用して preview を表示させる

#Preview all emails at http://localhost:3000/rails/mailers/devise_mailer

class DeviseMailerPreview < ActionMailer::Preview

  # http://localhost:3000/rails/mailers/devise_mailer/confirmation_instructions
  def
    user = User.last
    user.send_confirmation_instructions # enc_tokenをuserのconfirmation_tokenに設定
    raw_token = user.instance_variable_get(:@raw_confirmation_token) # userオブジェクトの@raw_confirmation_tokenを取得
    Devise::Mailer.confirmation_instructions(user, raw_token)
  end

  # http://localhost:3000/rails/mailers/devise_mailer/email_changed
  def email_changed
    user = User.last
    Devise::Mailer.email_changed(user)
  end

  # http://localhost:3000/rails/mailers/devise_mailer/reset_password_instructions
  def reset_password_instructions
    user = User.last
    raw_token = user.send_reset_password_instructions # 返り値がraw_tokenとなるのでinstance_variable_getは不要
    Devise::Mailer.reset_password_instructions(user, raw_token)
  end
end

confirmation_instructionsreset_password_instructionsの上記のメソッドはソースコードに書いてあるので見てみてください

参考資料

0
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
0
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?