Help us understand the problem. What is going on with this article?

Railsで論理削除(soft delete)を実装する(discard gem利用)

環境

  • Rails 5.2.3
  • Ruby 2.6.5
  • Discard 1.1.0

Gemの選択に要注意

  • paranoiaは、自らのREAMDEで「新規にプロジェクトに導入するのは非推奨」としている。
  • 同READMEで推奨されているdiscardを使う。

非推奨の背景

  • ActiveRecordのdeletedestroyをoverrideしているため、開発者が予期しない挙動をする。
  • dependent: :destroy関連のレコードは削除(物理削除)される(※開発者が期待する動作ではない)。

上記に伴い、バグフィックスと、Railsの新しいバージョンへの対応は行うが、新しいfeatureは受け付けていない。

Discardの導入

Gemのインストール

Gemfile
gem "discard"
$ bundle install

db migration

posts テーブルに適応する例。

$ rails generate migration add_discarded_at_to_posts discarded_at:datetime:index

以下のようなファイルが生成される。

class AddDiscardedAtToPosts < ActiveRecord::Migration[5.2]
  def change
    add_column :posts, :discarded_at, :datetime
    add_index :posts, :discarded_at
  end
end
$ rails db:migrate

モデルに定義追加

class Post < ApplicationRecord
  include Discard::Model
end

使い方

削除

destroyの代わりに、discardを使う。

@post.discard

コマンド実行例

# 削除
post.discard       # => true
# 確認
post.discarded?    # => true

# 強制削除。既に削除済の場合は、exceptionが発生する。
post.discard!      # => true
post.discard!      # Discard::RecordNotDiscarded: Failed to discard the record

# 削除したレコードを元に戻す
post.undiscard     # => true
post.undiscard!    # => Discard::RecordNotUndiscarded: Failed to undiscard the record
post.discarded_at  # => nil

# 削除した日時を確認
post.discarded_at  # => Mon, 21 Oct 2019 14:34:41 JST +09:00

# 削除されたレコード一覧
Post.discarded     # => [#<Post:0x00007fc04dbe3010 ...]
# 削除されていないレコード一覧
Post.kept          # => []

default_scopeの導入について

デフォルトでは、Post.allは削除されたレコードも含めて返す。
この挙動を変えて削除されていないものだけ返すようにするには、default_scope -> { kept }を設定する。

class Post < ApplicationRecord
  include Discard::Model
  default_scope -> { kept }
end

Post.all                       # 削除されていないレコードのみ
Post.with_discarded            # 全てのレコード
Post.with_discarded.discarded  # 削除されたレコードのみ
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした