日曜ITエンジニア劇場

日曜に勉強した情報の整理と、挑戦する新たな技術(私にとって)のつまづきポイントを綴っていきます。

ActiveRecord覚書/論理削除(paranoia)


参考資料

1.手順とGemについて

qiita.com

 ↑
ありがとうございます!
あまりの便利さに驚愕しました🤩
論理削除のGem必ずあると信じてたら、やっぱりあった!!

2.公式サイト

github.com

3.RubyGems.org

rubygems.org


目的、動機

「マスタテーブルを作るのなら、論理削除したい!」
と思い立ち、Gemを調べたところ今回のparanoiaに辿り着いた。


環境

$ sw_vers  
ProductName:    Mac OS X  
ProductVersion: 10.15.4  
$ sqlite3 -version  
3.28.0    
$ ruby -v  
ruby 2.6.2p47 (2019-03-13 revision 67232) [x86_64-darwin19]  
$ rails -v  
Rails 6.0.3.1  

手順

1.Gemfileにparanoiaを追記して、インストール。

1−1.Gemfileに追記

※バージョン等詳細については参考資料3を参照
Gemfile

# 論理削除  
gem 'paranoia', '~> 2.4', '>= 2.4.2'  

1−2.インストール

bundle install  

2.modelを生成する。

※既存のmodelに追加する方法は参考資料1を参照ください。

$ rails g model recipe name:string deleted_at:datetime  
Running via Spring preloader in process 2887  
      invoke  active_record  
      create    db/migrate/20200526035626_create_recipes.rb  
      create    app/models/recipe.rb  
      invoke    rspec  
      create      spec/models/recipe_spec.rb  

3.マイグレーションファイルをDBに反映

$ rails db:migrate  
== 20200526035626 CreateRecipes: migrating ====================================  
-- create_table(:recipes)  
   -> 0.0026s  
== 20200526035626 CreateRecipes: migrated (0.0029s) ===========================  

4.生成したmodelにacts_as_paranoidを追記する。

app/models/recipe.rb

class Recipe < ApplicationRecord  
  acts_as_paranoid  
end  

5.コンソールで動作確認

# データを変数に格納  
irb(main):001:0> recipe = Recipe.first  
   (2.1ms)  SELECT sqlite_version(*)  
  Recipe Load (1.3ms)  SELECT "recipes".* FROM "recipes" WHERE "recipes"."deleted_at" IS NULL ORDER BY "recipes"."id" ASC LIMIT ?  [["LIMIT", 1]]  
=> #<Recipe id: 2, name: "肉じゃが", deleted_at: nil, created_at: "2020-05-26 04:28:27", updated_at: "2020-05-26 04:28:27">  
  
irb(main):002:0> recipe  
=> #<Recipe id: 2, name: "肉じゃが", deleted_at: nil, created_at: "2020-05-26 04:28:27", updated_at: "2020-05-26 04:28:27">  
  
# `destroy`で論理削除  
irb(main):003:0> recipe.destroy  
   (0.2ms)  begin transaction  
  Recipe Update (0.6ms)  UPDATE "recipes" SET "deleted_at" = ?, "updated_at" = ? WHERE "recipes"."id" = ?  [["deleted_at", "2020-05-26 04:36:57.646671"], ["updated_at", "2020-05-26 04:36:57.646732"], ["id", 2]]  
   (2.0ms)  commit transaction  
=> #<Recipe id: 2, name: "肉じゃが", deleted_at: "2020-05-26 04:36:57", created_at: "2020-05-26 04:28:27", updated_at: "2020-05-26 04:36:57">  
  
# `only_deleted`で論理削除中のデータを確認できる  
irb(main):005:0> Recipe.only_deleted  
  Recipe Load (0.4ms)  SELECT "recipes".* FROM "recipes" WHERE "recipes"."deleted_at" IS NOT NULL LIMIT ?  [["LIMIT", 11]]  
=> #<ActiveRecord::Relation [#<Recipe id: 2, name: "肉じゃが", deleted_at: "2020-05-26 04:36:57", created_at: "2020-05-26 04:28:27", updated_at: "2020-05-26 04:36:57">]>  
  
# `restore`で論理削除を解除  
irb(main):006:0> recipe.restore  
   (0.1ms)  begin transaction  
  Recipe Update (0.4ms)  UPDATE "recipes" SET "deleted_at" = ?, "updated_at" = ? WHERE "recipes"."id" = ?  [["deleted_at", nil], ["updated_at", "2020-05-26 04:38:00.042295"], ["id", 2]]  
   (1.8ms)  commit transaction  
=> #<Recipe id: 2, name: "肉じゃが", deleted_at: nil, created_at: "2020-05-26 04:28:27", updated_at: "2020-05-26 04:38:00">  
  
# 普通に一番目のデータを取得すると。。。取得できている!  
irb(main):007:0> Recipe.first  
  Recipe Load (0.4ms)  SELECT "recipes".* FROM "recipes" WHERE "recipes"."deleted_at" IS NULL ORDER BY "recipes"."id" ASC LIMIT ?  [["LIMIT", 1]]  
=> #<Recipe id: 2, name: "肉じゃが", deleted_at: nil, created_at: "2020-05-26 04:28:27", updated_at: "2020-05-26 04:38:00">