[Rails] 退会機能(論理削除)


ポートフォリオに実装した退会機能のメモです。

実装

Userモデルにカラムを追加

Userが退会済みかどうかを判断するためのbooleanカラムを追加していきます。
ちなみにUserモデルはdeviseで追加したことを想定しています。

ターミナル
rails g migration AddIsValidToUsers is_valid:boolean
db/migrate/20210617022549_add_is_valid_to_users.rb
class AddIsValidToUsers < ActiveRecord::Migration[6.1]
  def change
    add_column :users, :is_valid, :boolean, default: true, null: false
  end
end
ターミナル
rails db:migrate

退会処理

退会画面と退会処理を作っていきます。

config/routes.rb
get '/accounts/:id/unsubscribe' => 'accounts#unsubscribe', as: 'unsubscribe'
patch '/accounts/:id/withdrawal' => 'accounts#withdrawal', as: 'withdrawal'

退会画面を表示する画面用のgetリクエストのunsubscribeと先程作成したUserカラムのbooleanを更新するpatchリクエストのwithdrawalのルーティングを作ります。

続いてController

app/controllers/accounts_controller.rb
def unsubscribe
  @user = User.find(params[:id])
end

def withdrawal
  @user = User.find(params[:id])
  @user.update(is_valid: false)
  reset_session
  flash[:notice] = "退会処理を実行いたしました"
  redirect_to root_path
end

unsubscribeではuser_idを取得
withdrawalでは退会のためのbooleanを更新して退会したらroot_pathに飛ばしているだけです。

次にviewです。

app/views/accounts/unsbscribe.html.haml
.container 
  %h2 退会お手続き
  %p
    退会手続きをされますと、全てのサービスがご利用いただけなくなります。
    %br
    再度ご利用をいただく場合には、新規登録のお手続きが必要になります。
    %br
    本当に退会してよろしいですか?
  = link_to "退会する", withdrawal_path, method: :patch, data: { confilm: "本当に退会しますか?" }
  = link_to "退会しない", root_path

退会するを押したらlink_toで先程のControllerのwithdrawalアクションに飛んでbooleanを更新する流れです。

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

退会したらログインできなくしていきます。

app/models/user.rb
def active_for_authentication?
  super && (is_valid == true)
end

モデルに制約を設定します。

app/controllers/users/sessions_controller.rb
class Users::SessionsController < Devise::SessionsController
   protected

  def reject_user
    @user = User.find(params[:id])
      if @user 
        if @user.valid_password?(params[:user][:password]) &&  (@user.active_for_authentication? == true)
        redirect_to new_user_registration
      end
    end
  end
end

Controllerで退会済みUserはログインできなくしていきます。
valid_password?でパスワードが正しいかどうか、
active_for_authentication? == trueで先程設定したモデルの制約がtrueの場合はログインせずログインページにリダイレクトされるようにしています。

これで完成です。

参考