パスワードリセット機能の実装
sourceryのreset_passwordモジュールの導入
$ rails g sorcery:install reset_password --only-submodules
class SorceryResetPassword < ActiveRecord::Migration[5.2] def change add_column :users, :reset_password_token, :string, default: nil add_column :users, :reset_password_token_expires_at, :datetime, default: nil add_column :users, :reset_password_email_sent_at, :datetime, default: nil add_column :users, :access_count_to_reset_password_page, :integer, default: 0 add_index :users, :reset_password_token end end
rails db:migrate
UserMailerという名前でパスワードリセットメール用のMailerを作成
$ rails g mailer UserMailer reset_password_email
sorcery.rbにreset_passwordサブモジュールを追加し、パスワードリセットに使用するActionMailerとしてUserMailerを定義
config/initializers/sorcery.rb
Rails.application.config.sorcery.submodules = [:reset_password] Rails.application.config.sorcery.configure do |config| config.user_config do |user| user.reset_password_mailer = UserMailer end end
ルーティング、コントローラー、viewファイル作成
・コントローラー
rails g controller PasswordResets new create edit update
app/controllers/password_resets_controller.rb
class PasswordResetsController < ApplicationController skip_before_action :require_login def new; end def create @user = User.find_by(email: params[:email]) @user&.deliver_reset_password_instructions! # 「存在しないメールアドレスです」という旨の文言を表示すると、逆に存在するメールアドレスを特定されてしまうため、 # あえて成功時のメッセージを送信させている redirect_to login_path, success: t('.success') end def edit @token = params[:id] @user = User.load_from_reset_password_token(@token) not_authenticated if @user.blank? end def update @token = params[:id] @user = User.load_from_reset_password_token(@token) return not_authenticated if @user.blank? @user.password_confirmation = params[:user][:password_confirmation] if @user.change_password(params[:user][:password]) redirect_to login_path, success: t('.success') else flash.now[:danger] = t('.fail') render :edit end end end
・ルーティングの設定
Rails.application.routes.draw do mount LetterOpenerWeb::Engine, at: '/letter_opener' if Rails.env.development? resources :password_resets, only: %i[new create edit update] end
・viewファイル作成
app/views/password_resets/edit.html.erb
パスワードリセット申請後、送られてきたメールのURLにアクセスすると、表示される画面の実装
<% content_for(:title, t('.title')) %> <div class="container"> <div class="row"> <div class="col col-md-10 offset-md-1 col-lg-8 offset-lg-2"> <h1><%= t('.title') %></h1> <%= form_with model: @user, url: password_reset_path(@token), local: true do |f| %> <%= render 'shared/error_messages', object: f.object %> <div class="form-group"> <%= f.label :email %> <%= @user.email %> </div> <div class="form-group"> <%= f.label :password %> <%= f.password_field :password, class: 'form-control' %> </div> <div class="form-group"> <%= f.label :password_confirmation %> <%= f.password_field :password_confirmation, class: 'form-control' %> </div> <div class="actions"> <p class="text-center"> <%= f.submit class: 'btn btn-primary' %> </p> </div> <% end %> </div> </div> </div>
app/views/password_resets/new.html.erb
<% content_for(:title, t('.title')) %> <div class="container"> <div class="row"> <div class="col-md-10 offset-md-1 col-lg-8 offset-lg-2"> <h1><%= t('.title') %></h1> <%= form_with url: password_resets_path, local: true do |f| %> <div class="form-group"> <%= f.label :email, t(User.human_attribute_name(:email)) %><br /> <%= f.email_field :email, class: 'form-control' %> </div> <%= f.submit t('password_resets.new.submit'), class: 'btn btn-primary' %> <% end %> </div> </div> </div>
app/views/user_sessions/new.html.erb
<%= link_to (t '.password_forget'), new_password_reset_path %>
メール文の作成
app/views/user_mailer/reset_password_email.html.erb
<p><%= @user.decorate.full_name %>様</p> <p>===============================================</p> <p>パスワード再発行のご依頼を受け付けました。</p> <p>こちらのリンクからパスワードの再発行を行ってください。</p> <p><a href="<%= @url %>"><%= @url %></a></p>
app/views/user_mailer/reset_password_email.text.erb
<%= @user.decorate.full_name %>様 =============================================== パスワード再発行のご依頼を受け付けました。 こちらのリンクからパスワードの再発行を行ってください。 <%= @url %>
ユーザーにメールを送信するメソッド部分
app/mailers/user_mailer.rb
class UserMailer < ApplicationMailer def reset_password_email(user) @user = User.find(user.id) @url = edit_password_reset_url(@user.reset_password_token) mail(to: user.email, subject: t('defaults.password_reset')) end end
Gemfileにletter_opener_webを追加
group :development do gem 'letter_opener_web', '~> 1.0' end
bundle install
config/environments/development.rbに設定を追加
config.action_mailer.delivery_method = :letter_opener_web config.action_mailer.default_url_options = Settings.default_url_options.to_h
config/environments/test.rb
config.action_mailer.default_url_options = Settings.default_url_options.to_h
環境変数設定
gem 'config'
bundle install
gemの機能で設定ファイルを生成
rails g config:install
カスタマイズ可能な設定ファイルconfig/initializers/config.rbとデフォルト設定ファイルのセットを生成 → config/settings.yml
config/settings/development.yml
config/settings/production.yml
config/settings/test.yml
config/settings/development.yml
default_url_options: host: 'localhost:3000'
config/settings/test.ym
default_url_options: host: 'localhost:3000'
参考文献