はじめに
今回はユーザー退会処理の機能、退会後同じメールアドレスとパスワードではログインできないようにする方法を記載します。
開発環境、前提条件
- AWS Cloud9
- Ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-linux]
- Rails 6.1.7.3
- Deviseのインストールが完了していて、ユーザーの新規登録やログインができる状態。
Userテーブル定義
is_deleted
カラムを作成し、デフォルトをfalseにしておきます。
退会ユーザーのis_deleted
をtrueにすることで退会ユーザーのデータは残したまま、退会しているかどうかを区別できるようにします。
カラム名 | カラム説明 | データ型 | デフォルト |
---|---|---|---|
ID | ユーザーID | integer | |
name | ユーザー名 | string | |
is_deleted | 削除フラグ | datetime | FALASE |
created_at | 登録日 | datetime | NOW |
updated_at | 更新日 | boolean | NOW |
users.controllerの編集
hide
アクションを作成します。
・@user.update(is_deleted: true)
で、@userのis_deletedカラムをtrueにupdateします。
・reset_session
で、ユーザーをログアウトさせます。
・redirect_to root_path
で、ログアウト後ルートパスに飛ばします。
index
アクションを作成します。
・退会済みのユーザーは
、is_deletedカラムがtrueに設定されているため、このページに表示されません。
def index
@users = User.where(is_deleted: false) #users/indexページでは、is_deletedカラムがfalseのユーザーのみが表示されます
end
def hide
@user = User.find(params[:id])
@user.update(is_deleted: true) #is_deletedカラムにフラグを立てる(defaultはfalse)
reset_session
flash[:notice] = "ありがとうございました。またのご利用を心よりお待ちしております。"
redirect_to root_path
end
しかしこのままでは直接URLに"user/:id"を入力するとユーザーの詳細情報を確認することができてしまいます。
そこでusers.controller
に追記しましょう。
class UsersController < ApplicationController
before_action :check_user_status, only:[:show]
.
.
.
private
def check_user_status
user = User.find(params[:id])
if user.is_deleted
redirect_to root_path
end
end
end
この記述ではshowアクションが呼び出される前にcheck_user_status
メソッドが呼び出され、指定されたユーザーのis_deleted
カラムがtrueかどうかチェックし、退会済みの場合はroot_path
にリダイレクトされます。
こうすることで直接URLを叩いても退会済みのユーザの詳細ページを閲覧することはできません。
ルーティングの作成
hide
アクションのルーティングを作成します。
as: 'users_hide'
で、showアクションと間違われないようURL名を指定します。
Rails.application.routes.draw do
devise_for :users
resources :users do
member do
delete :hide, as: 'users_hide'
end
end
end
退会ボタンの作成
ユーザー編集ページ(users/:id/edit.html.erb)
if user_signed_in? && @user.id == current_user.id
で、ユーザーがログインしていて且つログインユーザーであれば退会ボタンを表示するようにしています。
"data-confirm" => "本当に退会しますか?"
で退会ボタンクリック時にアラートが出るようにしています。
<div class="form_group">
<% if user_signed_in? && @user.id == current_user.id %>
<%= link_to "退会", users_hide_user_path(current_user), method: :delete, "data-confirm" => "本当に退会しますか??", class: "btn btn-outline-danger" %>
<% end %>
</div>
退会ユーザーはログインできなくする
user.rb
ログインする時に退会済み(is_deleted==true)のユーザーを弾くためのメソッドを作成します。
super && (self.is_deleted == false)
で、userのis_deletedがfalseならtrueを返すようにしています。
#退会ユーザーはログインできなくする
def actuve_for_authentication?
super && (self.is_deleted == false)
end
sessions_controller.rb
・if (@user.valid_password?(params[:user][:password])
で、入力されたパスワードが正しいことを確認しています。
・(@user.active_for_authentication? == false))
で、@userのactive_for_authentication?メソッドがfalseであるかどうかを確認しています。
・上記の2点が当てはまれば、ログインページにリダイレクトし、エラーメッセージを表示するようにしています。
class Users::SessionsController < Devise::SessionsController
before_action :reject_user, only: [:create]
protected
def reject_user
@user = User.find_by(email: params[:user][:email].downcase)
if @user
if (@user.valid_password?(params[:user][:password]) && (@user.active_for_authentication? == false))
flash[:error] = "退会済みです。"
redirect_to new_user_session_path
end
else
flash[:error] = "必須項目を入力してください。"
end
end
end
便利なフラッシュメッセージの記述
通常フラッシュメッセージの表示は<%= flash[:error] %>
とすると思いますが毎回ページごとに記述するよりも簡単な方法があります。
application.html.erbファイルに以下のコードを追加して、フラッシュメッセージが表示されるようにします。
<% flash.each do |key, value| %>
<div class="alert alert-<%= key %>">
<%= value %>
</div>
<% end %>
このコードは、コントローラーで設定されたフラッシュメッセージをループで処理し、それぞれのメッセージを表示します。keyには:notice、:alertなどのフラッシュの種類が、valueにはメッセージの内容が入ります。
BootStrap
をインストール済みの場合はフラッシュメッセージの配置を帰ることも可能です。以下例
<% flash.each do |key, value| %>
<div class="alert alert-<%= key %> alert-dismissible fade show position-fixed fixed-top w-25 ml-auto mt-3 mr-3" role="alert">
<%= value %>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<% end %>
このコードでは、position-fixed, fixed-top, w-25, ml-auto, mt-3, mr-3 クラスを使用して、フラッシュメッセージを画面右上に配置しています。
以上で実装完了です。コメント、いいねお待ちしてます!!