前提
deviseを用いた会員登録機能実装済み
管理者機能実装済み
https://qiita.com/NZTK/items/7868b2897ff1c46ee338
(管理者機能追加)
環境
Ruby2.5.5
Rails 5.2.3
使用gem
- devise
- paranoia
準備
gemの導入
gem 'paranoia'
$bundle install
カラム編集
rails g migration AddColumnToUsers deleted_at: datetime
class AddColumnToUsers < ActiveRecord::Migration[5.2]
def change
add_column :users, :deleted_at, :datetime
end
end
モデル編集
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
acts_as_paranoid #追加
end
これで論理削除ができるようになりました。
確認
rails c
を実行し、ユーザーが正しく論理削除できているか確認してみます。
User.find(1)
User Load (8.8ms) SELECT "users".* FROM "users" WHERE "users"."deleted_at" IS NULL AND "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
+----+---------+-----------------------+----------------------+------------------------+---------------------+-----------------------+------------------------+--------+------------+
| id | email | encrypted_password | reset_password_token | reset_password_sent_at | remember_created_at | created_at | updated_at | admin | deleted_at |
+----+---------+-----------------------+----------------------+------------------------+---------------------+-----------------------+------------------------+--------+------------+
| 1 | 1@1.com | $2a$11$C146AIA186C... | | | | 2019-07-10 05:40:5... | 2019-07-16 06:27:09... | false | |
+----+---------+-----------------------+----------------------+------------------------+---------------------+-----------------------+------------------------+--------+------------+
User.find(1).destroy
User Load (2.5ms) SELECT "users".* FROM "users" WHERE "users"."deleted_at" IS NULL AND "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
User Update (5.2ms) UPDATE "users" SET "deleted_at" = ?, "updated_at" = ? WHERE "users"."id" = ? [["deleted_at", "2019-07-17 14:48:44.544469"], ["updated_at", "2019-07-17 14:48:44.544500"], ["id", 1]]
(5.3ms) commit transaction
+----+---------+-----------------------+----------------------+------------------------+---------------------+-----------------------+------------------------+--------+--------------------+
| id | email | encrypted_password | reset_password_token | reset_password_sent_at | remember_created_at | created_at | updated_at | admin | deleted_at |
+----+---------+-----------------------+----------------------+------------------------+---------------------+-----------------------+------------------------+--------+--------------------+
| 1 | 1@1.com | $2a$11$C146AIA186C... | | | | 2019-07-10 05:40:5... | 2019-07-16 06:27:09... | false | 2019-07-17 14:48...|
+----+---------+-----------------------+----------------------+------------------------+---------------------+-----------------------+------------------------+--------+--------------------+
こんな感じでdeleted_at
カラムにUser.destroy
を実行した時間が入っていれば成功です。
復活させたい場合は、User.restore(1)
を実行すればdeleted_at
から時刻表示が消え、ユーザーが復活しています。
削除状態ではUser.all
では表示されないので、User.with_deleted
を用いて削除されたユーザーもまとめて出力することができます。削除済みユーザーのみを出す場合はUser.only_deleted
を使います。
ユーザー管理してみる
https://qiita.com/NZTK/items/7868b2897ff1c46ee338
この記事で作ったユーザー一覧を元に作っていきます。
管理者権限持ちユーザーのみがこのページへと飛んでこれるようになっています。
class UsersController < ApplicationController
before_action user_admin, only: [:index, :user_restore]
def index
@users = User.with_deleted #変更
end
def user_restore
@user = User.only_deleted.find(params[:id]).restore
redirect_to users_path
end
private
def user_admin
@users = User.with_deleted #変更
if current_user.admin == false
redirect_to users_path
else
render action: "index"
end
end
end
@users = User.with_deleted
により、削除済みユーザーも表示できるようにします。
<table>
<thead>
<tr>
<th>ID</th>
<th>メールアドレス</th>
<th>削除/復元</th>
</tr>
</thead>
<tbody>
<% @users.each do |user| %>
<tr>
<td><%= user.id %></td>
<td><%= user.email %></td>
#ここから
<% unless user.deleted_at? %>
<td><%= link_to "編集", edit_user_path(user.id) %></td>
<td><%= link_to "アカウント削除", user, data: { confirm: "退会させますか?" }, method: :delete %></td>
<% else %>
<td><%= link_to "アカウント復元", user_restore_user_path(user), method: :patch %></td>
<% end %>
#ここまで説明します
</tr>
<% end %>
</tbody>
</table>
resourses: users do
member do
patch 'user_restore'
end
end
unless user.deleted_at?
で対象ユーザーのdeleted_at
カラムがtrue
かfalse
を調べています。今回のdeleted_atカラムは基本的にからであることを前提に考えているので、unless
を用いています。
deleted_at
がfalse
の場合、<td><%= link_to "編集", edit_user_path(user.id) %></td>
と<%= link_to "アカウント削除", user, data: { confirm: "退会させますか?" }, method: :delete %>
で編集ページへのリンクとアカウント削除用のリンクを表示させ、true
の場合は<%= link_to "アカウント復元", user_restore_user_path(user), method: :patch %>
でアカウント復元用のボタンを表示させています。
繰り返しの中で個別に分けられたものを変数user
としてコントローラーにわたし、only_deleted
で削除済みのデータから探し出したUserを.rstore
で復元し、users_path
で元の一覧画面に戻しています。
今回の復元処理はdeleted_at
カラムに存在する日付データを空にしてアップデートしているので、methodはpatchを用いています。
まとめ
論理削除は便利ですが、多用するとデータベースを圧迫する恐れがあるので多用しないほうがいいかもしれません。復元が簡単にできるのはとても便利です。