deviseを使用した退会機能

# 初学者の備忘録
初学者の備忘録です。今回は前に投稿した[devise](https://qiita.com/Kooszs12/items/4bf3e25c4d3deda8b309)を使用した退会機能編
＊論理的削除の退会機能です。（参考URL：https://zenn.dev/goldsaya/articles/ee812461bbea6b）


## 実装
【１】　カラム追加
退会機能には退会フラグカラムが必要になります。まずはカラムの追加からになりますが、すでに追加している場合はスキップして大丈夫です。
退会フラグには退会済みと退会していない状態の２つの状態が存在しています。なのでデータ型はboolean型を使用して、default: falseと記述することでデフォルトでユーザーが登録した時に自動で退会前という状態のデータが保存されます。
```ruby:db/migrate/（年月日時分秒）_devise_create_users.rb
t.boolean "is_deleted", default: false, null: false
```
マイグレーションファイルを変更したら忘れずにUp状態にしましょう。

【２】　ルーティング
退会と退会確認用のルーティングを記述していきます。退会確認ページが必要ない場合は退会用のルーティングだけで大丈夫です。
```diff_ruby:config/routes.rb
scope module: :user do
    root "homes#top"
    # マイページ
    get 'users/mypage/:id' => 'users#show', as: :users_mypage
    # 退会確認ページ
    +get 'users/confirm_withdraw' => 'users#confirm_withdraw', as: :users_confirm_withdraw
    # 退会機能
    +patch 'users/withdraw' => 'users#withdraw'
    end

```

【３】　退会処理
退会確認ページと退会処理をする記述をuser/controllersに記述します。
```diff_ruby:app/controllers/user/users_controller.rb
class User::UsersController < ApplicationController

# 退会確認
  def confirm_withdraw
    # ログインしているユーザー本人のデータ
    @user = current_user
  end

  # 退会
  def withdraw
    # ログインしているユーザー本人のデータ
    @user = current_user
    # is_deletedカラムをtrueに更新して退会させる。
    @user.update(is_deleted: true, name: "退会済み")
    # 退会した時点でログアウトする
    reset_session
    # 成功メッセージ
    redirect_to root_path, notice: "ご利用ありがとうございました"
  end

end
```
<details>
  <summary>補足</summary>
  
# 例
if article.save
  flash[:notice] = "登録が完了しました。"
  redirect_to root_path
else
    
</details>

【４】　退会メソッド定義
退会しているのか、該当するユーザーがいないのか判断させるメソッドを記述していきます。実装しなくても問題はありませんが、ユーザー側のことを考えると実装した方がいいと思います。
```diff_ruby:app/controllers/user/sessions_controller.rb
class User::SessionsController < Devise::SessionsController

# ユーザーcreate前にreject_userを呼び出す
  before_action :reject_user, only: [:create]

 :
 :


  protected

  # 退会済みのユーザーがログインできないようにする（退会処理とは別）
  def reject_user
    @user = User.find_by(email: params[:user][:email])
    # 存在しているかどうか分岐
    if @user
      # 退会フラグが退会済みか有効化判断
      if @user.valid_password?(params[:user][:password]) && (@user.is_deleted == true)
        flash[:notice] = "退会済みです。再度ご登録をしてご利用ください"
        redirect_to new_user_registration_path
      end
    else
      # そもそも存在していなかった場合
      flash[:notice] = "該当するユーザーが見つかりません"
    end
  end

end

```


【５】　退会ボタン
必要な箇所に退会確認ボタンを実装し、退会確認ページを表示、退会する、しないのボタンを作成していきます。

- 退会確認ページへのボタン
```diff_ruby:app/views/user/必要ファイル
<!--退会確認ボタン-->
<%= link_to "退会", users_confirm_withdraw_path, class: "btn btn-danger btn-block" %>
```

- 退会確認ページ
```diff_ruby:app/views/user/必要ファイル
<!--退会確認ページ-->
<div class="content">
  <div class="row">
    <div class="col-md-8 mx-auto text-center">
      <h2 class="mb-5">本当に退会しますか？</h2>
      <p>
        退会すると、会員登録情報や<br>
        これまでの御朱印履歴が閲覧できなくなります。<br>
        退会する場合は、「退会する」をクリックしてください。
      </p>

      <%= link_to "退会しない", users_mypage_path(@user), :class => "btn btn-info btn-block" %>
      <%= link_to "退会する", users_withdraw_path(@user), method: :patch, :class => "btn btn-danger btn-block", data: { confirm: "本当に退会しますか？" }  %>

    </div>
  </div>
</div>
```

あとは動作確認をして終了です。お疲れ様でした。

<details>
  <summary>おまけ</summary>
  
 今回は論理的削除でしたが、物理的削除も可能です。ですが論理的削除の方がおすすめです。
物理削除だと全て消えてしまいますが、論理的削除ならば退会になっただけでデータベースに残るので後から復活したり、ユーザーが投稿した内容は残るからです。
（参考URL：https://99gen-blog.com/rails-logical-deletion/）
    
</details>