devise 新規登録時にパスワードリセットメールを送信したいのでやってみた

システム管理者のみが新規登録できる状態を想定してます。ログイン画面で新規登録できることは想定していませんので、あしからず。
システム管理者が新規登録した際に、登録したユーザーにパスリセットのメールを送りたい！
なにせ、システム管理者から通知するのは面倒、メール文面にパスワードを載せるのはセキュリティ上よくない。
なので、通知してリンクから直接パスワードを変更してもらうようにする。

## ActionMailerの設定
`app/controller/application_controller.rb`に記載します。

```app/controller/application_controller.rb
class ApplicationController < ActionController::Base
  before_action :set_host

  def set_host
    Rails.application.routes.default_url_options[:host] = request.host_with_port
  end
end
```

パスリセットメールを送る際にHelperを通るようで、`ActionView::Template::Error (Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true)`のエラーが出ていたので入れてます。

## リセットメールテンプレートのパス設定
テンプレートはこのファイルになります -> `app/views/devise/mailer/reset_password_instructions.html.erb`

```app/views/devise/mailer/reset_password_instructions.html.erb
<p>Hello <%= @resource.email %>!</p>

<p>Someone has requested a link to change your password. You can do this through the link below.</p>

<p><%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %></p>

<p>If you didn't request this, please ignore this email.</p>
<p>Your password won't change until you access the link above and create a new one.</p>

```
デフォルトはこの状態。
`edit_password_url`を作成しているルートにあわせてください。僕の場合は `edit_user_password_url`にしました＼(^o^)／


## 新規登録時にメール送る
deviseの登録はここ -> `app/controllers/users/registrations_controller.rb`

```app/controllers/users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
  before_action :configure_sign_up_params, only: :create
  prepend_before_action :require_no_authentication, only: :cancel
  prepend_before_action :authenticate_scope!, only: %i[new create]
  prepend_before_action :set_minimum_password_length, only: :new

  # GET /resource/sign_up
  def new
    super
  end

  # POST /resource
  def create
    build_resource(sign_up_params)
    resource.save
    yield resource if block_given?
    if resource.persisted?
      if resource.active_for_authentication?
        set_flash_message! :success, :signed_up
        sign_up(resource_name, current_user)

        # 登録したアカウントにパスワードリセットメール送信
        self.resource = resource_class.send_reset_password_instructions(resource_params)

        redirect_to admins_path
      else
        set_flash_message! :notice, :"signed_up_but_#{resource.inactive_message}"
        expire_data_after_sign_in!
        respond_with resource, location: after_inactive_sign_up_path_for(resource)
      end
    else
      clean_up_passwords resource
      set_minimum_password_length
      respond_with resource
    end
  end
・
・
・
```

devise元のregistrations_controller.rb/createアクションをオーバーライドしています。
あと、なんかいろいろ設定もしていますのでデフォルトとはちょっと違います。
`sign_up(resource_name, current_user)`は登録したユーザーでログインし直さないように変更を加えてます。
その下！
`self.resource = resource_class.send_reset_password_instructions(resource_params)`
を追記してください。
これで`reset_password_token`が作成されます。
`edit_password_path(@resource, reset_password_token: @token)`(僕の場合は`edit_user_password_path`)へリダイレクトできるようになります。

## リセット画面

```app/views/devise/passwords/edit.html.erb
<h2>Change your password</h2>
<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| %>
  <%= devise_error_messages! %>
  <%= f.hidden_field :reset_password_token %>

  <div class="field">
    <%= f.label :password, "New password" %><br />
    <% if @minimum_password_length %>
      <em>(<%= @minimum_password_length %> characters minimum)</em><br />
    <% end %>
    <%= f.password_field :password, autofocus: true, autocomplete: "off" %>
  </div>

  <div class="field">
    <%= f.label :password_confirmation, "Confirm new password" %><br />
    <%= f.password_field :password_confirmation, autocomplete: "off" %>
  </div>

  <div class="actions">
    <%= f.submit "Change my password" %>
  </div>
<% end %>

<%= render "devise/shared/links" %>
```
自分のお好きなように文言やスタイルを変更するだけ！（上はデフォ）


## 最後に
直接パスワード変更画面にリダイレクトしても無理です。
そこで何が必要だったかというと`reset_password_token`。
`edit_password_path`にユーザー情報と作成された`reset_password_token`を渡さないといけないということでした。
これに気づくのにかなり時間がかかった。。。
同じようなことをしたい人の助力となれますよーに。

あとでブログにかこう。