論理削除
データをまんま消すと復旧したいときに困ってしまうので、消されたことにしておくが、実際は消さないという実装方法
やるまえに、本当に論理削除じゃないとダメなのかどうか、よくよく考えた方が良いです!!!
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なしでやろうとすると面倒ですね。。