2
0

More than 3 years have passed since last update.

Rails で gem を使わず論理削除を実装する方法

Last updated at Posted at 2021-03-11

論理削除

データをまんま消すと復旧したいときに困ってしまうので、消されたことにしておくが、実際は消さないという実装方法

やるまえに、本当に論理削除じゃないとダメなのかどうか、よくよく考えた方が良いです!!!

paranoia は非推奨

前の現場などでは、よく見たparanoia ですが公式のお達しの通り、ActiveRecordのdeleteとdestroyを上書きしちゃうので新しいプロジェクトに入れるのはおすすめしないっすとあります。
https://github.com/rubysherpas/paranoia

Notice:

paranoia has some surprising behaviour (like overriding ActiveRecord's delete and destroy) and is not recommended for new projects. See discard's README for more details.

Paranoia will continue to accept bug fixes and support new versions of Rails but isn't accepting new features.

Gemを使わず実装してみる

default_scope + リレーション でなんとなくやりたいことはできるのかなと思いました。

嫌われがちなdefault_scopeですが、用途を限定したら良いのではないかと思っています。
参考 : https://qiita.com/yokochi@github/items/730418b0c7f36ded5b5f

class Parent < ApplicationRecord
  default_scope { where(deleted_at: nil) }
  scope :with_deleted, -> { unscope(where: :deleted_at) }
end

このように定義しておけば、gemを使わなくても呼び出し時にはdeleted_at に値が入っているものを除外してくれます。

$ Parent.all
=> SELECT `parents`.* FROM `parents` WHERE `parents`.`deleted_at` IS NULL 

$ Parent.with_deleted.all
=> SELECT `parents`.* FROM `parents` 

子データから論理削除済みの親データを参照したい

状況によっては不便になるので良し悪しですが、

親と子でリレーションが成立しているとき、

class Child < ApplicationRecord
  belongs_to :parent
end

parentに紐づくchildが作成された後に、parentが論理削除された場合には、既に削除済みのデータは呼べません

$ child.parent
=> nil 

リレーションがある場合にはdeleted_atを無視したい場合には条件を設定します。(管理画面とかで過去データを表示する時に役に立ちました)

class Child < ApplicationRecord
  belongs_to :parent, -> { with_deleted }
end

論理削除したい

都度やるの面倒ですが、腹を括って .soft_destroy といった名前でdeleted_at に時間を埋めるメソッドを追加するしかないかなーと思います

まとめ

やっぱ論理削除をgemなしでやろうとすると面倒ですね。。

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