2009-03-19 railsで変なの作るよ #10 〜acts_as_paranoid編〜
acts_as_paranoidで論理削除してみるよ( ̄▽ ̄)
結構前のこと。
室長「zrsv、ちょい退会機能作っといて。」
zrsv「はぁい( ̄▽ ̄)ノ」我ながら良い返事。
室長「あ。もち論理削除ね」
zrsv「!!( ̄A ̄;;)」
…論理削除ねぇー。
テーブルに削除フラグ持たせるのは別にいんだけどさー。
結構アレなのよねぇ、、指定間違えると退会した人が表に出てきたりとかさー。
関連テーブルが増えたときに、そっちもちゃんと論理削除処理書かないといけないとかさー。
必要なのは重々承知なんだけどさー。
色々面倒だからあんま好きじゃないんだよねー。論理削除ー。( ̄A ̄;)
…とかぶつぶつボヤきながら調べてたらこんなの見つけた。
<acts_as_paranoid>
どうもこれは、
・destroy(_all)をすると勝手に論理削除してくれる。 ・↑のときに関連モデルについても論理削除してくれる(要宣言) ・findとかで検索する時に、論理削除されたレコードは引っ張り出さない。
というスグレモノらしい。をぉ便利☆
っていうことで、早速やってみたよー。
#他にも「acts_as_deletable」ってのもあったんだけど、
#これは別テーブルに削除するレコードを退避させるってものらしい。
#……今回のやつでは、そこまでするのは無駄じゃね?ってことで
#ココでは「acts_as_paranoid」を使ってみたよ( ̄▽ ̄)ノ
手順はこんな感じー。
- acts_as_paranoidのいんすとーる
- まいぐれーつ
- 実装ー。
んじゃやってみるよー( ̄▽ ̄)ノ
1.acts_as_paranoidのインストール
まずは、acts_as_paranoidさんを入れさせていただきますよー。
> ruby script/plugin install acts_as_paranoid + ./acts_as_paranoid/CHANGELOG + ./acts_as_paranoid/MIT-LICENSE + ./acts_as_paranoid/README + ./acts_as_paranoid/RUNNING_UNIT_TESTS + ./acts_as_paranoid/Rakefile + ./acts_as_paranoid/init.rb + ./acts_as_paranoid/lib/caboose/acts/belongs_to_with_deleted_association.rb + ./acts_as_paranoid/lib/caboose/acts/has_many_through_without_deleted_association.rb + ./acts_as_paranoid/lib/caboose/acts/paranoid.rb + ./acts_as_paranoid/test/database.yml + ./acts_as_paranoid/test/fixtures/categories.yml + ./acts_as_paranoid/test/fixtures/categories_widgets.yml + ./acts_as_paranoid/test/fixtures/taggings.yml + ./acts_as_paranoid/test/fixtures/tags.yml + ./acts_as_paranoid/test/fixtures/widgets.yml + ./acts_as_paranoid/test/paranoid_test.rb + ./acts_as_paranoid/test/schema.rb + ./acts_as_paranoid/test/test_helper.rb
2.まいぐれーつ
次に、論理削除したいテーブルに削除フラグ用のカラムを追加しちゃうよ。
今回は、User : Hennano = 1 : 多
っていうところに論理削除をしかけまーす。
↓のまいぐれーつファイルを用意して、れっつmigrate☆
<db/migrate/xxx_acts_as_paranoid_for_user.rb>
1 class ActsAsParanoidForUser < ActiveRecord::Migration 2 def self.up 3 add_column :users, :deleted_at, :datetime, :comment => "削除日時" 4 add_column :hennanos, :deleted_at, :datetime, :comment => "削除日時" 5 end 6 7 def self.down 8 remove_column :users, :deleted_at 9 remove_column :hennanos, :deleted_at 10 end 11 end
3.実装
実装はちょー楽。
モデルにacts_as_paranoidを使うぜっっって言う宣言を書くだけ。
あと、関連モデルも一緒に論理削除するんで、UserとHennano両方に宣言するのです。
<app/models/user.rb>
1 class User < ActiveRecord::Base 2 acts_as_paranoid # acts_as_paranoidを使わせていただく宣言。 3 4 has_many :hennanos, :dependent => :destroy 5 6 end # end class[User]
ポイントは2行目。
「acts_as_paranoid」って書くだけ。うわーチョー楽(>▽<)ノ
あと4行目の関連定義のとこで、dependentですとろいって書いておくとアレだ。
Userを削除するときに、一緒に関連するHennanoも削除してくれるんだけど
そっちも論理削除にしたいから……
ってことで。こうだ。同じく2行目を書いておくのだ。
<app/models/hennano.rb>
1 class Hennano < ActiveRecord::Base 2 acts_as_paranoid # acts_as_paranoidを使わせていただく宣言。 3 4 belongs_to :user 5 6 end # end class[Hennano]
さて。早速destroyメソッド使って削除してみる
→find使っても出てこない。
→DBを直接見てみてると、データ自体はあって、deleted_atに削除日時が入ってる
→関連モデルのHennanoも一緒に論理削除されてる
すばらし♪
→物理削除したい時は、破壊的メソッドを使うと良いらしい。 →論理削除したデータも引っ張りだしたい時は「find_with_deleted」メソッドを使うと良いみたい。 →論理削除したデータを復活させたい時は、「deleted_at」をNULLで更新すると良いらしい。 ※一意制約かけるときは要注意。deleted_atなscope使ってね。
<参考>
- 39 http://www.google.co.jp/search?q=acts_as_paranoid&lr=lang_ja&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:ja:official&client=firefox-a
- 36 http://www.google.co.jp/search?q=acts_as_paranoid&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:en-US:official&client=firefox-a
- 30 http://www.google.co.jp/search?hl=ja&client=firefox-a&rls=org.mozilla:ja:official&hs=InY&q=rails+xml+cdata&btnG=検索&lr=lang_ja
- 18 http://www.google.co.jp/search?hl=ja&source=hp&q=acts_as_paranoid&btnG=Google+検索&lr=&aq=f&oq=
- 17 http://www.google.co.jp/search?hl=ja&q=論理削除&lr=&aq=0r&oq=ろんりさくじょ
- 17 http://www.google.co.jp/search?q=Rails+論理削除&lr=lang_ja&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:ja:official&client=firefox-a
- 17 http://www.google.co.jp/search?sourceid=navclient&hl=ja&ie=UTF-8&rlz=1T4SPDA_jaJP203JP204&q=<+xml+(<![CDATA[
- 16 http://tobysoft.net/wiki/index.php?Ruby/Ruby on Rails/acts_as_paranoid
- 13 http://d.hatena.ne.jp/sumihiro/20080227/1204098653
- 13 http://www.google.co.jp/search?hl=ja&q=acts_as_paranoid&sourceid=navclient-ff&rlz=1B3GGGL_jaJP272JP273&ie=UTF-8