Hatena::Diary

割と意味はない

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」を使ってみたよ( ̄▽ ̄)ノ


手順はこんな感じー。

  1. acts_as_paranoidのいんすとーる
  2. まいぐれーつ
  3. 実装ー。

んじゃやってみるよー( ̄▽ ̄)ノ


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使ってね。

<参考>

http://d.hatena.ne.jp/sumihiro/20080227/1204098653

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/zrsv/20090319/p1