acts_as_paranoidをdiscardへ移行する
業務にて、acts_as_paranoidを使って論理削除を実装していたのをdiscardへ置き換えたので記しておきます。
・acts_as_paranoid
・discardacts_as_paranoidはactiveRecordのdestroyメソッドを上書きしているのですが、ほかのgemとの組み合わせにより消したくないレコードが消えてしまう状況になってしまいました。
そのためacts_as_paranoidを脱し、元々のメソッドを上書きしていない論理削除のgemとしてdiscardを使うことになりました。
discardはdestroyメソッドの上書きではなく、該当カラムのupdate処理のようです。
以下、今回行った対応。
deleted_atカラムをdiscardへ流用
discardは論理削除判定に使うカラムを指定することができます。deleted_at
を指定することでacts_as_paranoid用に用意したdeleted_at
カラムをそのまま使うことができます。
class Hoge < ApplicationRecord
include Discard::Model
self.discard_column = :deleted_at
destroyメソッドをdiscardメソッドへ
@user.destroy
など、destroyやdestroy!していたところをdiscard, discard!などに置き換えます。
discard_all
なども。使っているところを検索して置き換えました。
scope
with_deleted
, only_deleted
なscopeが無くなるので、
scope :with_deleted, -> { with_discarded }
scope :only_deleted, -> { with_discarded.discarded }
discardをラップすることで流用しました。
deleted?メソッド
deleted?
メソッドが無くなるのでdiscardのメソッドをラップすることで対応しました。
Modelにインスタンスメソッドとして
def deleted?
discarded?
end
を生やし、内部でdiscarded?を呼んでいます。
dependent: :destroy対応
dependent: :destroy
など削除系で子のレコードを削除していたところも対応が必要でした。
after_discard :destroy_children
などを設定し、
destroy_children
メソッドの中で明示的に子のレコードを削除しました。
コールバック対応
before_destroy
-> before_discard
after_destroy
-> after_discard
に置き換えて対応、
validates_as_paranoid
validates_as_paranoid
validates_uniqueness_of_without_deleted :email
これらも使えなくなるので対応が必要でした。
やっていることはdeleted_at
がnilの条件を追加しているだけなので、
validates_uniqueness_of :email, conditions: -> { where(deleted_at: nil) }
に置き換えました。
acts_as_paranoid
discardのissueに
があったのでこの対応で大丈夫そう。注意
destroy
をdiscard
へ置き換えましたが、二つはreturnする値が異なります。
destroy
はインスタンスを返すのに対して、discard
はbooleanを返します。
具体的には
hoge.destroy.reload
とテストコードで書いているところがあったのを
hoge.discard
hoge.reload
と置き換えました。
終わり
Railsの元々のメソッドなどをオーバーライドするようなgemは気をつけたい。
Discussion