【devise】新規登録とメールアドレス変更で異なるテンプレートを使用する

## はじめに
deviseでメールアドレス変更を行おうとすると、デフォルトでは認証メールは新規登録と同じテンプレートを使用する様になっていました。
しかし、新規登録とメールアドレス変更でメールの内容を変更したい。試行錯誤して設定を行ったので、備忘録に。

テンプレート変更の設定にフォーカスした内容になっていますので、deviseでのメールアドレス変更の基本的な詳しい設定方法は他の記事をご覧ください。
私は[rails deviceを使用したメールアドレス変更](https://qiita.com/mone_pi/items/ca132baa3f432947fc96)を参考にしました。

## 環境
* rails 7
* **devise導入済み**
* **メール認証を含む新規登録〜ログイン**
* **メールアドレス変更実装済み**

## やり方

deviseをオーバーライドしてメールアドレス変更用の認証メールの`confirmation_on_edit_address_instructions`を追加する

  ```app/controllers/users/answers_controller.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
    
        def reset_password_instructions(record, token, opts={})
          @token = token
          devise_mail(record, :reset_password_instructions, opts)
        end
    
        def unlock_instructions(record, token, opts={})
          @token = token
          devise_mail(record, :unlock_instructions, opts)
        end
    
        def confirmation_on_edit_address_instructions(record, token, opts={})
          @token = token
          devise_mail(record, :confirmation_on_edit_address_instructions, opts)
        end
     end
end
```

追加した`confirmation_on_edit_address_instructions`をメールアドレス変更時に送信する様にdeviseの`send_reconfirmation_instructions`をオーバーライドする。

```app/models/user.rb
  def send_reconfirmation_instructions
    @reconfirmation_required = false
    unless @skip_confirmation_notification
      send_on_edit_address_confirmation_instructions
    end
  end

  def send_on_edit_address_confirmation_instructions
    unless @raw_confirmation_token
      generate_confirmation_token!
    end
    opts = pending_reconfirmation? ? { to: unconfirmed_email } : { }
    send_devise_notification(:confirmation_on_edit_address_instructions, @raw_confirmation_token, opts)
  end
  ```


`confirmation_on_edit_address_instructions`のviewはこんな感じ。

```app/views/users/mailer/confirmation_on_edit_address_instructions.html.erb
<div>
  <p>※本メールは、自動的に配信しています。
  こちらのメールは送信専用のため、直接ご返信いただいてもお問合せにはお答えできませんので、あらかじめご了承ください。</p>

  <p>以下のURLよりメールアドレスの変更手続きを完了してください。</p>

<p><%= link_to 'メールアドレスを変更する', confirmation_address_url(@resource, confirmation_token: @token) %></p>
```

ルーティングにトークンを設定
```config/routes.rb
get 'users/confirm_address/:confirmation_token', :to => "users/confirmations#confirmation_address", :as => "confirmation_address", :only_path => false
```
```app/controllers/users/confirmations_controller.rb
  def confirmation_address
    self.resource = resource_class.confirm_by_token(params[:confirmation_token])
    yield resource if block_given?

    if resource.errors.empty?
      redirect_to after_address_hoge_path
    else
      sign_out
      redirect_to fuga_path, flash: { alert: '無効なURLです。' }
    end
  end
```

## 最後に
プログラミング学習中の初学者です。
内容の誤りや他に良い方法があれば、コメント等で教えていただけると幸いです。

## 参考記事
[rails deviceを使用したメールアドレス変更](https://qiita.com/mone_pi/items/ca132baa3f432947fc96)
[Deviseで新規登録時とメールアドレス変更時のテンプレートを分ける](https://qiita.com/haman29/items/2f1cbfb3fa5606c38e52)