LoginSignup
50
83

More than 1 year has passed since last update.

[Rails]paranoiaを使わずに退会機能を実装する(ユーザーを論理削除する)

Last updated at Posted at 2020-02-10

実装すること

paranoiaを使わずに、ユーザーの退会機能を作成するために下記のコードを書いていきます。
①ユーザーを論理削除する。
②退会ユーザーをログアウトさせる。
③退会ユーザーはログインできなくする。

ページ設計

マイページ(users/show.html.erb)で退会できるようにします。

Userテーブル定義

is_deletedカラムを作成し、デフォルトをfalseにしておきます。
退会ユーザーのis_deletedをtrueにすることで退会ユーザーのデータは残したまま、退会しているかどうかを区別できるようにします。

カラム名 カラム説明 データ型 デフォルト
ID ユーザーID integer
name ユーザー名 string
is_deleted 削除フラグ datetime FALASE
created_at 登録日 datetime NOW
updated_at 更新日 boolean NOW

Userモデルの作成

Userモデルはdeviseを使用してモデルを作成していきます。

deviseの導入・Userモデルの作成

Gemfile.
gem 'devise'
$ bundle install
$ rails g devise:install
$ rails g devise user name:string is_deleted:boolean
$ rails g devise:views

コントローラの作成・編集

$ rails g controller users

users_controller.rb

hideアクションを作成します。
@user.update(is_deleted: true)で、@userのis_deletedカラムをtrueにupdateします。
reset_sessionで、ユーザーをログアウトさせます。
redirect_to root_pathで、ログアウト後ルートパスに飛ばします。

app/controllers/users_controller.rb

    def show
		@user = User.find(params[:id])
    end

    def hide
		@user = User.find(params[:id])
		#is_deletedカラムにフラグを立てる(defaultはfalse)
    	@user.update(is_deleted: true)
    	#ログアウトさせる
    	reset_session
    	flash[:notice] = "ありがとうございました。またのご利用を心よりお待ちしております。"
    	redirect_to root_path
	end

ルーティングの作成

hideアクションのルーティングを作成します。
as: 'users_hide'で、showアクションと間違われないようURL名を指定します。

config/routes.rb
Rails.application.routes.draw do

  devise_for :users

  resources :users
  put "/users/:id/hide" => "users#hide", as: 'users_hide'
end

退会ボタンの作成

マイページ(users/show.html.erb)

if user_signed_in? && @user.id == current_user.idで、ユーザーがログインしていて且つログインユーザーであれば退会ボタンを表示するようにしています。
"data-confirm" => "本当に退会しますか?"で退会ボタンクリック時にアラートが出るようにしています。

app/views/users/show.html

<% if user_signed_in? && @user.id == current_user.id %>
		<%= link_to "退会", users_hide_path(current_user), method: :put, "data-confirm" => "本当に退会しますか?", class: "btn btn-outline-danger" %>
<% end %>

退会ユーザーはログインできなくする

user.rb

ログインする時に退会済み(is_deleted==true)のユーザーを弾くためのメソッドを作成します。
super && (self.is_deleted == false)で、userのis_deletedがfalseならtrueを返すようにしています。

app/models/user.rb
class User < ApplicationRecord

  def active_for_authentication?
    super && (self.is_deleted == false)
  end

end

sessions_controller.rb

if (@user.valid_password?(params[:user][:password])で、入力されたパスワードが正しいことを確認しています。
(@user.active_for_authentication? == false))で、@userのactive_for_authentication?メソッドがfalseであるかどうかを確認しています。
・上記の2点が当てはまれば、ログインページにリダイレクトし、エラーメッセージを表示するようにしています。

app/controllers/sessions_controller.rb

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

sessions/new.html.erb

エラーメッセージを表示するため、<%= flash[:error] %>をお好きなところに追記してください。

app/views/sessions/new.html

<%= flash[:error] %>

最後に

最後までご覧いただきありがとうございます。
初学者ですので間違っていたり、分かりづらい部分もあるかと思います。
何かお気付きの点がございましたら、お気軽にコメントいただけると幸いです。

参考

特定のユーザのアカウントは残しつつ、ログインできないようにしたい
https://blog.edwardkenfox.com/post/90435229476/%E7%89%B9%E5%AE%9A%E3%81%AE%E3%83%A6%E3%83%BC%E3%82%B6%E3%81%AE%E3%82%A2%E3%82%AB%E3%82%A6%E3%83%B3%E3%83%88%E3%81%AF%E6%AE%8B%E3%81%97%E3%81%A4%E3%81%A4%E3%83%AD%E3%82%B0%E3%82%A4%E3%83%B3%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%84%E3%82%88%E3%81%86%E3%81%AB%E3%81%97%E3%81%9F%E3%81%84

RailsでDeviseを使っていて、入力されたパスワードが正しいかどうかを自前で実装したい場合
https://qiita.com/knt45/items/49f8ad2bdef906dca302

50
83
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
50
83