Ruby on Rails

【Rails】データを削除しても履歴を取れるように、論理削除を使おう

バートリーのさいとうです。

今回は

【Rails】削除しても履歴を取れるように、論理削除を使おう

というテーマで、実務からの学びを共有したいと思います。

もし、「履歴を残す形でデータを取り扱いたい!」という要望に応えようとした時
どのように実装しますか?

僕なら、論理削除を使います。

論理削除とは、

データは削除された扱いになるよのように、データ自体は残っているけど、扱いとしては削除済みにすること

https://wa3.i-3-i.info/word18493.html

ということです。つまり
データをユーザーから見えなくするけど、DBにはデータが残っているよ
ってことですね。

ただ、論理削除と言っても

  • 論理削除を実装するために、やるべきことがわからない
  • 論理削除したデータをどのように活用するべきかがわからない

と思いますので、今回はRailsでgemなしで

  • データを論理削除し、さらに活用する方法がわかる
  • 履歴としてデータを表示するための方法がわかる

ように解説していきます。

論理削除を活用して、履歴が取れるアプリケーションを作っていきましょう!

(※)Railsには、論理削除が手軽にできるparanoiaというgemも存在します。もしgemが利用可能であれば、公式githubこちらの記事等を参考にしてみてください。

論理削除をする方法

いくつかステップを用意したので、一つずつ見ていきましょう。
目次は以下の通りです。

  • カラムの追加
  • 論理削除用のメソッド定義
  • 実際にメソッドを利用するとどうなるか

カラムの追加

論理削除をするためには、「データを削除された扱い」にする必要があります。

そこで、論理削除したいモデルにカラムを追加し、その値を削除したかどうかのフラッグ(旗)として利用します。

実際に、履歴として残したいTagモデルを想定しましょう。

タグモデルは以下のような構成になっています。

# Table name: tags

#  id         :integer          not null, primary key
#  name       :string           not null
#  created_at :datetime         not null
#  updated_at :datetime         not null

ここに、フラッグとして利用するdeleted_at (datetime型)を付与します。

class AddDeletedAtToTags < ActiveRecord::Migration
  def change
    add_column :tags, :deleted_at, :datetime
  end
end

これでdb:migrateを行った結果こうなります。

# Table name: tags

#  id         :integer          not null, primary key
#  name       :string           not null
#  created_at :datetime         not null
#  updated_at :datetime         not null
#  deleted_at :datetime

これで、tagsテーブルにフラッグ用のカラムを追加することができました。

論理削除用のメソッドを定義

では次に、論理削除を行うためのメソッドを定義していきます。

先ほどのTagモデルに、delete!メソッドを記載します。

# Table name: tags

#  id         :integer          not null, primary key
#  name       :string           not null
#  created_at :datetime         not null
#  updated_at :datetime         not null

class Tag < ActiveRecord::Base
  def delete!
    self.deleted_at = Time.now
    save!
  end

処理としては、delete!メソッドが呼び出されたら、

  1. 対象のレコードのdeleted_atカラムに現在時刻を代入
  2. 保存する

の二段階になっています。deleted_atはdatetime型なので、時刻や日付を入れる必要がありますね。

これで、論理削除用のメソッドが定義できました。
では、実際にメソッドを利用してみましょう。

実際にメソッドを利用すると

タグの削除ボタンがViewに存在し、そのボタンを押下すると論理削除が行われる仕様にしましょう。

<div>
  <%= link_to "削除", delete_tags_path, method: :delete%>
</div>

コントローラーではこのようにします。

class TagsController  < ApplicationController
  def index
  end

  def delete
    tag = Tag.find(params[:id])
    tag.delete!
    redirect_to :index
  end
end

これで、DBを見にいくと

こんなふうに、deleted_atに日付が入力されていると思います。

これで、DBへの保存が完了しました。

では最後に、このデータを活用するための方法に触れて終わりにします。

論理削除したデータの活用

この記事のタイトルにもあるように、論理削除ができると、履歴を取ることができるようになったりします。

論理削除したかどうかで検索条件を作る

例えば、これまでに論理削除したタグを一覧にして出力したいと考えた時には、以下のように記述することができます。

class TagsController  < ApplicationController
  def index
    deleted_tags = Tag.where.not(:deleted_at: nil).order("desc")
  end

  def delete
    tag = Tag.find(params[:id])
    tag.delete!
    redirect_to :index
  end
end

これをViewで展開してあげると、論理削除されたレコードの一覧が表示されるようになります。

この他にも、「8月に削除したタグ」などといったように検索条件を指定することも可能です。

また、ユーザーの退会機能を作れたりもするでしょう。

リンク先の記事を参考にしてみてください。

まとめ

今回は、【Rails】削除しても履歴を取れるように、論理削除を使おう、というテーマで解説してきました。

gemはとても便利ですが、自作することでgemの仕組みを理解できるようになるので、おすすめです。

このブログは、月に15本を目標に、実務から学んだプログラミングのあれこれを発信しています。

誰かのためになれば、嬉しいです。

最後まで読んでいただき、ありがとうございました。

それでは。

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA