Modelのバージョン管理を行う(acts_as_versioned)

やりたいのはあるモデルを更新した際に更新前の状態を自動的にバックアップしてくれる機能。
いろいろあると思うけど、acts_as_versioned プラグインを使ってみた。

環境:Rails3.0系

インストール

インストールはいつもの感じで以下

$ gem install acts_as_versioned

Gemfile に gem 'acts_as_versioned' を追加

$ bundle install

バージョン管理したい Model に以下を追加。

class Account < ActiveRecord::Base 
  acts_as_versioned   # 追加
end 

バージョン管理用のマイグレーションを作成する

$ rails g migration add_version

作成したマイグレーションに以下を記述。

# db/migrate/20110912133220_add_version.rb

class AddVersion < ActiveRecord::Migration
  def self.up
    Account.create_versioned_table
  end

  def self.down
    Account.drop_versioned_table
  end
end
$ rake db:migrate

使いっぷり

  • バックアップ数を取得は version メンバにアクセス。
  • バックアップの配列取得は versions メンバにアクセス。
>> ac = Account.new
>> ac.name = "baggio"
>> ac.save
>> ac = Account.first
>> ac.version 
=> 1
>> ac.versions
=> [#<Account::Version id: 1, account_id: 1, version: 1, name: "baggio", created_at: "2011-09-12 13:42:09", updated_at: "2011-09-12 13:42:09">]
>> ac.name = "zola"
>> ac.save
>> ac = Account.first
>> ac.version
=> 2
>> ac.versions
=> [#<Account::Version id: 1, account_id: 1, version: 1, name: "baggio", created_at: "2011-09-12 13:42:09", updated_at: "2011-09-12 13:42:09">, #<Account::Version id: 2, account_id: 1, version: 2, name: "zola", created_at: "2011-09-12 13:42:09", updated_at: "2011-09-12 13:42:43">]
  • 全履歴を取得する例(更新時間でソート)
@histories = Account.all.map{|ac| ac.versions}.flatten.sort{|a,b| b.updated_at <=> a.updated_at}

いや、もっと簡単に Account::Version.all で良いみたい。

@histories = Account::Version.order('updated_at DESC')

履歴が追加か変更かについては、 h.account.version == 1 で判定可能。

true : 新規
false : 変更(2つ以上の履歴があるので)

でも上記だけだと削除した履歴は取得できない。
自前で削除のフックを使って記録するしかないのか。

参考