概要
この記事ではRuby on Railsを例として「論理削除とはなんぞ」や、
というのをざっくり解説したいと思います。
謝辞
- 株式会社X-HACKさんでPARKLoTというTwitterインスタントウィンサービスのバックエンド開発をお手伝いさせていただいております。本記事ではその経験で得られた知識をアウトプットしています。ありがとうございます。
- 参考にさせていただいた記事は以下の通りです。ありがとうございます。
物理削除と論理削除の違い
データベースのデータを削除する機会はよくあると思います。
- ユーザーの退会処理
- コメントの削除
- mixiの恥ずかしい黒歴史記事の削除
などなど。
ここで、データの削除の仕方として、2つの方法があります。
- データを完全に削除してしまう →**「物理削除」**
- データを残しながら削除したかように扱う →**「論理削除」**
物理削除の例
たとえば、思春期時代に書いた恥ずかしいポエムがネット上に残っていたとしましょう。
これに気づいた投稿者ポエマーAくんとしては、なんとしてもこのデータを地球上から消し去りたいはずです。
その場合は**「物理削除」**でデータを消してあげるべきでしょう。
class Api::V1::PoemController < ApplicationController
def destroy
@poem = Poem.find_by(id: params[:id])
@poem.destroy # ←データを完全に消去(物理削除)
render json: {messages: ["ポエムを削除しました"]}, status:200
end
end
論理削除の例
しかし、もしかしたらさらに10年後、ポエマーAくんは大人になり、
若かった頃の自分がどんなことを考えていたのか、振り返ってみたくなる日が来るかもしれません。
あんなに恥ずかしかった内容も、笑って振り返れる日が来るかもしれません。
その場合、「物理削除」したポエムは永遠に戻ってこないので、
「あぁ…消さなければよかった…」と後悔する可能性があります。
そんな場合は、**「論理削除」**が適切です。
「論理削除」とはつまり、「削除したかのように扱う」ということです。
いやだからその論理削除ってなんやねんという方のために、
論理削除の具体例を上げてみます。
(正確にはちょっと違うかもしれませんが)
- 契約書など重要な書類で、間違った部分を二重線で消して書き直す (二重線を引いた部分を「削除」したことにする)
- 遊戯王カードで死んだモンスターを墓地に送る (カードは残っているが墓地ゾーンに置くことで死んだことにする)
- 「昨日の晩は酔っていて何も覚えていない。覚えていないのだから何もなかった。いいね?」(なにかをやらかしたという事実は消せないのでとりあえず何も無かった事にする)
などなど、実は日常的に論理削除っぽいことが使われているのです。
べんりですね!!おとなはきたない。
Railsのコントローラーで書いてみるとこんな感じでしょう。
class Api::V1::PoemController < ApplicationController
def destroy
# データを消さずにdeleted_atカラムに「削除した日付」を記録し削除したことにする(論理削除)
@poem.update!(deleted_at: DateTime.now)
render json: {messages: ["ポエムを削除しました"]}, status:200
end
end
ポイントはdestroyメソッドを使わずに、updateメソッドでカラムを更新しているだけ、という点です。
そして、deleted_atという削除日を記録するためのカラムが必要になります。
論理削除の注意点
しかし残念ながらこれだけでは論理削除したはずの
恥ずかしいポエムは普通に一覧などで表示されてしまいます。
これは大変いけません。いけませんよ!!!
class Api::V1::PoemController < ApplicationController
def index
@poems = Poem.all # 論理削除したポエムまで一覧表示されてしまう
render json: @poems, status:200
end
end
id | title | content | deleted_at |
---|---|---|---|
1 | 普通のポエム | いい感じの内容 | nil |
2 | 恥ずかしいポエム | 大変恥ずかしい内容 | 2022-02-05 |
3 | 普通のポエム | いい感じの内容 | nil |
4 | 普通のポエム | いい感じの内容 | nil |
5 | 普通のポエム | いい感じの内容 | nil |
※そもそも恥ずかしくないポエムなどあるのかという点はここでは議論しません。
対策
論理削除したポエムを表示させないように、deleted_atカラムを使ってソートしてあげましょう。
class Api::V1::PoemController < ApplicationController
def index
# deleted_atがnilであれば論理削除していないので、
# 下記のように書くと論理削除した恥ずかしいポエムを除いて一覧表示してくれる
@poems = Poem.where(deleted_at: nil)
render json: @poems, status:200
end
end
id | title | content | deleted_at |
---|---|---|---|
1 | 普通のポエム | いい感じの内容 | nil |
3 | 普通のポエム | いい感じの内容 | nil |
4 | 普通のポエム | いい感じの内容 | nil |
5 | 普通のポエム | いい感じの内容 | nil |
また、showアクションでもdeleted_atがnilの場合は、表示させないようにしてあげると良いでしょう。
(今回は割愛します)
まとめ
一般的なサービスであればデータが残っていた方が何かと便利なので、「論理削除」の出番は多いかと思います。
一方で個人的には恥ずかしいポエムは物理削除されるべきと考えます。頼むぞmixi・・・!