Red > Green > Refactor > Red

cycle is based on desire

テーブル論理削除 gem acts_as_paranoid

rails 4 に対応している


  • gem の目的

テーブルデータを物理削除ではなく論理削除する。

データ自体が完全に消えては困るが、表向きには消去されていてほしいときに使う。

  • Gemfileの記述
gem 'rails4_acts_as_paranoid'
  • 論理削除確認までの手順 (books テーブルを使用)(物理削除の方法等は参考元ページまで)

本を表すテーブルを作る。

rails g model book name:string page:integer
  • (モデルの味付け。それ以外に意味が無いので気にされなくてよい)1ページ以上1000ページ以下を validation にかける
class Book < ActiveRecord::Base]
  validates_numericality_of :page, only_integer: true, greater_than_or_equal_to: 1, less_than_or_equal_to: 1000
end
  • acts_as_paranoid の論理削除用 フィールドを追加する
rails g migration AddDeleteFlagToBook deleted_at:datetime

rake db:migrate
  • acts_as_paranoid の利用を宣言する
class Book < ActiveRecord::Base
  acts_as_paranoid
  validates_numericality_of :page, only_integer: true, greater_than_or_equal_to: 1, less_than_or_equal_to: 1000
end

  • 動作確認

3つのレコードを save し、論理削除し、本当にそうなったのかどうか確認する。

3 つのレコードを save

2.0.0-p353 :002 > Book.new(name: 'foo', page: 90).save
   (0.3ms)  begin transaction
   中略
   (133.0ms)  commit transaction
 => true 
2.0.0-p353 :003 > Book.new(name: 'bar', page: 70).save
   (0.1ms)  begin transaction
    中略
   (121.4ms)  commit transaction
 => true 
2.0.0-p353 :004 > Book.new(name: 'qux', page: 800).save
   (0.2ms)  begin transaction
    中略
   (380.6ms)  commit transaction
 => true 

save された3レコードの確認

2.0.0-p353 :005 > Book.all
  Book Load (0.6ms)  SELECT "books".* FROM "books" WHERE (books.deleted_at IS NULL)
 => #<ActiveRecord::Relation
[#<Book id: 1, name: "foo", page: 90, created_at: "2014-01-07 14:53:40", updated_at: "2014-01-07 14:53:40", deleted_at: nil>,
#<Book id: 2, name: "bar", page: 70, created_at: "2014-01-07 14:53:53", updated_at: "2014-01-07 14:53:53", deleted_at: nil>,
#<Book id: 3, name: "qux", page: 800, created_at: "2014-01-07 14:54:12", updated_at: "2014-01-07 14:54:12", deleted_at: nil>]>

論理削除 --- acts_as_paranoid が引っかかっているので物理ではなく論理

2.0.0-p353 :006 > Book.delete_all
  SQL (118.6ms)  UPDATE "books" SET deleted_at = '2014-01-07 14:56:05.280569' WHERE (books.deleted_at IS NULL)
 => 3 

レコードの追加

2.0.0-p353 :008 > Book.new(name: 'xor', page: 8).save
   (0.2ms)  begin transaction
 中略( id=4 のレコードが追加された)
   (392.6ms)  commit transaction
 => true 

論理削除されたレコードだけを確認

2.0.0-p353 :009 > Book.only_deleted
  Book Load (0.2ms)  SELECT "books".* FROM "books" WHERE (books.deleted_at IS NOT NULL)
 => #<ActiveRecord::Relation
[#<Book id: 1, name: "foo", page: 90, created_at: "2014-01-07 14:53:40", updated_at: "2014-01-07 14:53:40", deleted_at: "2014-01-07 14:56:05">,
#<Book id: 2, name: "bar", page: 70, created_at: "2014-01-07 14:53:53", updated_at: "2014-01-07 14:53:53", deleted_at: "2014-01-07 14:56:05">,
#<Book id: 3, name: "qux", page: 800, created_at: "2014-01-07 14:54:12", updated_at: "2014-01-07 14:54:12", deleted_at: "2014-01-07 14:56:05">]> 

削除されていない + 論理削除されたレコードを find する

2.0.0-p353 :010 > Book.with_deleted
  Book Load (0.3ms)  SELECT "books".* FROM "books"
 => #<ActiveRecord::Relation
[#<Book id: 1, name: "foo", page: 90, created_at: "2014-01-07 14:53:40", updated_at: "2014-01-07 14:53:40", deleted_at: "2014-01-07 14:56:05">,
#<Book id: 2, name: "bar", page: 70, created_at: "2014-01-07 14:53:53", updated_at: "2014-01-07 14:53:53", deleted_at: "2014-01-07 14:56:05">,
#<Book id: 3, name: "qux", page: 800, created_at: "2014-01-07 14:54:12", updated_at: "2014-01-07 14:54:12", deleted_at: "2014-01-07 14:56:05">,
#<Book id: 4, name: "xor", page: 8, created_at: "2014-01-07 15:01:24", updated_at: "2014-01-07 15:01:24", deleted_at: nil>]>

参考元 # 勉強になりました

TECHSCORE BLOG

富士山は世界遺産