🦦

Rails 退会機能実装

2023/05/22に公開
2

はじめに

現在チーム開発中、プログラミング2ヶ月目の初学者です🔰

deviseを使用して退会機能を実装しましたので、メモとして残します!

論理削除と物理削除

まず、退会機能の論理削除と物理削除ってなに??

⭐️論理削除とは

テーブルに削除フラグを項目として用意し、そのTRUE/FALSEで削除をされたかどうか管理する方法

メリット

  • データの復旧が可能
  • 削除したデータも検索などで参照できる

デメリット

  • データが実質減らないので、ストレージを圧迫する可能性がある

⭐️物理削除とは

SQLでDELETE文を発行してレコードを削除すること

メリット

  • レコードが削除される為、ストレージを圧迫しにくい
  • 論理削除と比べると実装が容易(destroyアクションの活用)

デメリット

  • 簡単に復元したり、削除されたデータを参照できない

https://99gen-blog.com/rails-logical-deletion/

退会用カラムの追加

退会管理用のカラムの追加を行う!

rails g migration AddIsDeletedToCustomers is_deleted:boolean

このカラムにデフォルト値(false)を設定し、登録した直後は false が設定されるようにする🙆🏻‍♀️

schema.rb
create_table "customers", force: :cascade do |t|
  t.boolean "is_deleted", default: false, null: false
end

ルーティング

論理削除用に任意の名前のルーティングを作成。(アクション名が被ってはいけない!)

routes.rb
Rails.application.routes.draw do
 # 顧客用
devise_for :customers
:
 # 会員側のルーティング設定
scope module: :public do
  root to: 'homes#top'
  # customers
 get  '/customers/mypage' => 'customers#show'
 get  '/customers/information/edit' => 'customers#edit'
 patch  '/customers/information' => 'customers#update'
+ # 退会確認画面
+ get  '/customers/check' => 'customers#check'
+ # 論理削除用のルーティング
+ patch  '/customers/withdraw' => 'customers#withdraw'
:
end

退会画面の作成

退会画面を表示させて、本当に退会するか確認してもらう。

public/customers/check.html.erb
<h1>本当に退会しますか?</h1>
  <p>
    退会すると、会員登録情報や<br>
    これまでの購入履歴が閲覧できなくなります。<br>
    退会する場合は、「退会する」をクリックしてください。
  </p>

  <%= link_to "退会しない", customers_mypage_path, :class => "btn btn-primary ms-3" %>
  <%= link_to "退会する", customers_withdraw_path, method: :patch, :class => "btn btn-danger ms-3", data: { confirm: "本当に退会しますか?" }  %>

data: { confilm: "本当に退会しますか?" } の記述により、退会ボタンを押した時に確認ボックスが出現する!

2度の操作を挟むことにより、手違いによる退会を防いでいる💪🏻

コントローラー

  • @customer.update(is_deleted: true) = current_customerが持つ、is_deletedカラムをtrueにupdateして、退会状態にする。
  • reset_session = セッション情報を全て削除
  • redirect_to root_path = 退会後トップ画面に遷移

Sessionとは

  • ページ遷移しても以前入力した情報を保持することができる機能
  • sessionは明示的に削除されるまで消えない
public/customers_controller.rb
class Public::CustomersController < ApplicationController
  def withdraw
    @customer = Customer.find(current_customer.id)
    # is_deletedカラムをtrueに変更することにより削除フラグを立てる
    @customer.update(is_deleted: true)
    reset_session
    flash[:notice] = "退会処理を実行いたしました"
    redirect_to root_path
  end
end

モデルに制約をかける

ログイン時に退会済みのユーザーが同じアカウントでログイン出来ないようにする。

models/costomer.rb
class Customer < ApplicationRecord
  # is_deletedがfalseならtrueを返すようにしている
  def active_for_authentication?
    super && (is_deleted == false)
  end
end

session_controller.rb

退会処理を行った会員が、同じアカウントでログイン出来ないようにする。

同じアカウントでログインしようとすると、新規会員登録画面へ遷移します!

  • @customer = Customer.find_by(email: params[:customer][:email]) =  ログイン時に入力されたメールアドレスに対応するユーザーが存在するか探す。

  • @customer.valid_password?(params[:customer][:password]) = 入力されたパスワードが正しいことを確認。

  • (@customer.is_deleted == true) = @customerのactive_for_authentication?メソッドがfalseであるかどうか

public/session_controller.rb
class Public::SessionsController < Devise::SessionsController
  before_action :reject_customer, only: [:create]
  
  protected
  
  def reject_end_user
    @end_user = EndUser.find_by(email: params[:end_user][:email])
    if @end_user
      if @end_user.valid_password?(params[:end_user][:password]) && (@end_user.is_deleted == true)
        flash[:notice] = "退会済みです。再度ご登録をしてご利用ください"
        redirect_to new_end_user_registration_path
      else
        flash[:notice] = "項目を入力してください"
      end
    else
      flash[:notice] = "該当するユーザーが見つかりません"
    end
  end
end
  • find_byメソッド
    ID をもとに検索を行う find メソッドに対し、ID 以外のカラムからも検索を行い
    該当する1件を取得するメソッド

今回の場合は、Customer モデルから入力された email を検索し、該当する 1 件を取得する用途で使用

  • valid_password?メソッド
    特定のアカウントのパスワードと入力されたパスワードが一致しているかを
    確認するためのDevise が用意しているメソッド

今回の場合は、find_by メソッドで特定したアカウントのパスワードとログイン画面で入力されたパスワードが一致しているかを確認する用途で使用

🌱参考にさせていただいた記事

https://qiita.com/Wata16/items/9e05596afb671e540365

https://qiita.com/bty__/items/358d0a425193b12c969a


終わった後に書いているのと確認が充分にできていないので
もしかしたら記述もれや間違いがあるかもしれないです🥲

Discussion

AirichanAirichan

さやかさん!大変だとおもうけどファイティン!🥹👍🏻

sayasaya

めちゃくちゃ時間に追われている、、😂ありがとう!!あいりちゃんも面接ファイト💪🏻