読者です 読者をやめる 読者になる 読者になる

波打際のブログさん

主に、プログラミング備忘録など。

Rails4と3で論理削除を行うためのGem Kakurenbo の紹介と今更論理削除Gemを実装した理由。

Ruby Rails

様々なわけがあってkakurenboは非推奨です。新規のプロジェクトではkakurenbo-putiの使用をおすすめします。

Kakurenboとは

 Rails4及びRails3で論理削除を行うためのGemです。paranoia及びacts_as_paranoidと互換性があるので、gemを置き換えるだけでそのまま動きます。(動かなかったらissue投げてくだしあ><)

なんで今更論理削除のGemを実装したのか

 今更開発しなくても論理削除のGemは山ほど出てきますが、なぜ開発しなくてはならなくなってしまったのか経緯に触れておきます。

acts_as_paranoid

 論理削除の本家と言ってもいいレベルの知名度です、だがしかしいつまで立ってもRails4に対応しない。

rails4_acts_as_paranoid

 既存のバグほったらかしで使えない。(メモリ関連のバグがありSQLクエリが永遠に結合されていきます。やばみ。プルリク送ったのに放置されてます。)

paranoia

 今Rails4で論理削除と言ったらコレ!ってくらい定番です。私もつい最近まではコレを利用していました。コールバック関連のバグを修正するプルリク送ったりして結構便利に使っていました。
 しかし、とある作業中にアソシエーションに深刻な問題があることに気付き、プルリクを送りましたが、仕様なのでマージする気はないとプルリク蹴られてしまいました。

 具体的にはリレーショナルで1対多の関係を設定している場合、親を論理削除して復元を行った場合、親が論理削除される以前に論理削除されている子まで復元されてしまうのです。例えば掲示板で、掲示板を本体を論理削除した後、何かの手違いだとわかり復元する時に、問題があって削除してた書き込みも全て復元されてしまうのです。

 「そもそも間違えて削除しなければいい話だろ」なんて運用でカバーするスタイルはRailsRubyらしくありません。だからこれは深刻な問題です。大切なことなのでもう一度言います。これは深刻な問題です。

結論

 paranoiaをフォークして作ろうと思ったものの、paranoiaのテストフォルダにはTest::Unitで書かれた、生SQLクエリでテーブル生成したり、実行順番依存で書かれた闇のテストコードが・・・ → Rspecで綺麗にテスト書きながら最初から作ろう。

 かくして、新しくKakurenbo*1を開発することになるのであった。。。。

インストール方法

 いつものようにGemfileに追加するとか、インストールするとか。

gem "kakurenbo"

使い方

 論理削除で管理したいモデルに deleted_at カラムを datetime 型で追加するだけで使えます。

rails generate migration add_deleted_at_to_models deleted_at:datetime

クラスの初期化時にカラムを読み取って、deleted_atがあれば論理削除と判別するので論理削除のモデルでいちいちacts_as_paranoidメソッドを呼び出す必要はありません。
(deleted_at以外のカラムを利用する際には、acts_as_paranoidをcolumnオプション付きで呼び出して設定してください。)

基本的な使い方

 paranoiaやacts_as_paranoidと互換性があるので説明はいらないかもしれませんが基本的な使い方です。

この記事は古くなっています、最新バージョン 0.2.x の使い方はこちらを参照してください。

論理削除Gem、 Kakurenbo をアップデートしました。 - 波打際のブログさん

論理削除

 普通にdestroyメソッドを呼び出すと論理削除されます。

model.destroy
復元

 論理削除したモデルはrestoreで復活できます。

model.restore!

# 次の方法も使えます。id指定、もしくはidの配列で一括で復元できます。
Model.restore(id)

before_restore, after_restoreコールバック使えます。

物理削除

 destroy!で物理削除できます。

model.destroy!
スコープ
# 削除されたモデルも取得
Model.with_deleted

# 削除されたモデルのみ取得
Model.only_deleted

# 削除されていないモデルのみ取得(デフォルトスコープです。)
Model.without_deleted

関連リンク

修正履歴

  • 2014年01月29日 誤字脱字を修正しました。

*1:RailsとかRubyのGemって、流行ってるのってみんな変な名前だよね!じゃぁ俺も変な名前のGem作ろう・・・論理削除・・・かくれみの・・・かくれんぼ!! → Kakurenbo