2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[初心者]Gem『paranoia』を用いたユーザー管理をやってみた

Posted at

前提

deviseを用いた会員登録機能実装済み
管理者機能実装済み
https://qiita.com/NZTK/items/7868b2897ff1c46ee338
(管理者機能追加)

環境

Ruby2.5.5
Rails 5.2.3

使用gem

  • devise
  • paranoia

準備

gemの導入

Gemfile
gem 'paranoia'
$bundle install

カラム編集

rails g migration AddColumnToUsers deleted_at: datetime
xxx_add_column_to_users
class AddColumnToUsers < ActiveRecord::Migration[5.2]
  def change
    add_column :users, :deleted_at, :datetime
  end
end

モデル編集

user.rb
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
この記事で作ったユーザー一覧を元に作っていきます。
管理者権限持ちユーザーのみがこのページへと飛んでこれるようになっています。

users_controller
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により、削除済みユーザーも表示できるようにします。

users/index.html.erb

<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>
routes.rb
resourses: users do
  member do
    patch 'user_restore'
   end
end

unless user.deleted_at?で対象ユーザーのdeleted_atカラムがtruefalseを調べています。今回のdeleted_atカラムは基本的にからであることを前提に考えているので、unlessを用いています。
deleted_atfalseの場合、<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を用いています。

まとめ

論理削除は便利ですが、多用するとデータベースを圧迫する恐れがあるので多用しないほうがいいかもしれません。復元が簡単にできるのはとても便利です。

2
4
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
2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?