前回からの続きです。
監査証跡を取るには、モデルに対して audited を呼び出してあげれば良いです。こんな感じです。
class Company < ActiveRecord::Base audited end
これでどのように監査証跡が取られるか、rails consoleの実行結果で見てみます。
tsubame.local{miyohide}% rails c Loading development environment (Rails 3.2.2) irb(main):001:0> Company.create(:name => "aaa") (0.1ms) begin transaction SQL (20.4ms) INSERT INTO "companies" ("created_at", "name", "updated_at") VALUES (?, ?, ?) [["created_at", Sun, 27 May 2012 10:18:10 UTC +00:00], ["name", "aaa"], ["updated_at", Sun, 27 May 2012 10:18:10 UTC +00:00]] (0.2ms) SELECT MAX("audits"."version") AS max_id FROM "audits" WHERE "audits"."auditable_id" = 2 AND "audits"."auditable_type" = 'Company' SQL (0.6ms) INSERT INTO "audits" ("action", "associated_id", "associated_type", "auditable_id", "auditable_type", "audited_changes", "comment", "created_at", "remote_address", "user_id", "user_type", "username", "version") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) [["action", "create"], ["associated_id", nil], ["associated_type", nil], ["auditable_id", 2], ["auditable_type", "Company"], ["audited_changes", "---\nname: aaa\n"], ["comment", nil], ["created_at", Sun, 27 May 2012 10:18:10 UTC +00:00], ["remote_address", nil], ["user_id", nil], ["user_type", nil], ["username", nil], ["version", 1]] (1.1ms) commit transaction => #<Company id: 2, name: "aaa", created_at: "2012-05-27 10:18:10", updated_at: "2012-05-27 10:18:10"> irb(main):002:0>
companiesテーブルに対するinsertを行った後、auditsテーブルに対してselect処理とinsert処理を行っています。
モデルに対して audited の一行を書くことで、関連も張られます。自身に関連する監査証跡を見るには、audits を呼び出してあげればOK。
irb(main):002:0> c = Company.find(2) # 先ほど作ったデータのidが2なので、find(2)で検索。 Company Load (3.6ms) SELECT "companies".* FROM "companies" WHERE "companies"."id" = ? LIMIT 1 [["id", 2]] => #<Company id: 2, name: "aaa", created_at: "2012-05-27 10:18:10", updated_at: "2012-05-27 10:18:10"> irb(main):003:0> c.audits Audited::Adapters::ActiveRecord::Audit Load (0.5ms) SELECT "audits".* FROM "audits" WHERE "audits"."auditable_id" = 2 AND "audits"."auditable_type" = 'Company' ORDER BY version => [#<Audited::Adapters::ActiveRecord::Audit id: 1, auditable_id: 2, auditable_type: "Company", associated_id: nil, associated_type: nil, user_id: nil, user_type: nil, username: nil, action: "create", audited_changes: {"name"=>"aaa"}, version: 1, comment: nil, remote_address: nil, created_at: "2012-05-27 10:18:10">] irb(main):004:0>
データの登録だけでなく、更新や削除もOK。
irb(main):005:0> c.update_attributes(:name => "bbb") (0.1ms) begin transaction (0.3ms) SELECT MAX("audits"."version") AS max_id FROM "audits" WHERE "audits"."auditable_id" = 2 AND "audits"."auditable_type" = 'Company' SQL (2.5ms) INSERT INTO "audits" ("action", "associated_id", "associated_type", "auditable_id", "auditable_type", "audited_changes", "comment", "created_at", "remote_address", "user_id", "user_type", "username", "version") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) [["action", "update"], ["associated_id", nil], ["associated_type", nil], ["auditable_id", 2], ["auditable_type", "Company"], ["audited_changes", "---\nname:\n- aaa\n- bbb\n"], ["comment", nil], ["created_at", Sun, 27 May 2012 10:41:57 UTC +00:00], ["remote_address", nil], ["user_id", nil], ["user_type", nil], ["username", nil], ["version", 2]] (0.2ms) UPDATE "companies" SET "name" = 'bbb', "updated_at" = '2012-05-27 10:41:57.805354' WHERE "companies"."id" = 2 (10.1ms) commit transaction => true irb(main):006:0> c.destroy (0.2ms) begin transaction (0.3ms) SELECT MAX("audits"."version") AS max_id FROM "audits" WHERE "audits"."auditable_id" = 2 AND "audits"."auditable_type" = 'Company' SQL (1.2ms) INSERT INTO "audits" ("action", "associated_id", "associated_type", "auditable_id", "auditable_type", "audited_changes", "comment", "created_at", "remote_address", "user_id", "user_type", "username", "version") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) [["action", "destroy"], ["associated_id", nil], ["associated_type", nil], ["auditable_id", 2], ["auditable_type", "Company"], ["audited_changes", "---\nname: bbb\n"], ["comment", nil], ["created_at", Sun, 27 May 2012 10:42:17 UTC +00:00], ["remote_address", nil], ["user_id", nil], ["user_type", nil], ["username", nil], ["version", 3]] SQL (0.3ms) DELETE FROM "companies" WHERE "companies"."id" = ? [["id", 2]] (3.7ms) commit transaction => #<Company id: 2, name: "bbb", created_at: "2012-05-27 10:18:10", updated_at: "2012-05-27 10:41:57"> irb(main):007:0>
ちょっとした注意点として1点。削除の時にdeleteを呼んだときは、auditsテーブルに対するinsertは行われません。
irb(main):007:0> c = Company.create(:name => "test1") (0.1ms) begin transaction SQL (0.6ms) INSERT INTO "companies" ("created_at", "name", "updated_at") VALUES (?, ?, ?) [["created_at", Sun, 27 May 2012 10:45:49 UTC +00:00], ["name", "test1"], ["updated_at", Sun, 27 May 2012 10:45:49 UTC +00:00]] (0.2ms) SELECT MAX("audits"."version") AS max_id FROM "audits" WHERE "audits"."auditable_id" = 3 AND "audits"."auditable_type" = 'Company' SQL (0.4ms) INSERT INTO "audits" ("action", "associated_id", "associated_type", "auditable_id", "auditable_type", "audited_changes", "comment", "created_at", "remote_address", "user_id", "user_type", "username", "version") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) [["action", "create"], ["associated_id", nil], ["associated_type", nil], ["auditable_id", 3], ["auditable_type", "Company"], ["audited_changes", "---\nname: test1\n"], ["comment", nil], ["created_at", Sun, 27 May 2012 10:45:49 UTC +00:00], ["remote_address", nil], ["user_id", nil], ["user_type", nil], ["username", nil], ["version", 1]] (3.0ms) commit transaction => #<Company id: 3, name: "test1", created_at: "2012-05-27 10:45:49", updated_at: "2012-05-27 10:45:49"> irb(main):008:0> c.delete SQL (3.6ms) DELETE FROM "companies" WHERE "companies"."id" = 3 => #<Company id: 3, name: "test1", created_at: "2012-05-27 10:45:49", updated_at: "2012-05-27 10:45:49"> irb(main):009:0>
これは、ActiveRecordがdeleteのときにはcallbackを呼ばないからです。
詳細は「Ruby on Rails Guides: Active Record Validations and Callbacks」を読んでおくと良いかと思います。
長くなってきたので、今日はここまで。