lukewendling / expressive_record

Add meaningful names for belongs_to associations to Rails 2.1 model object dirty changes to help with rolling your own history/audit logger.

This URL has Read+Write access

expressive_record / README.rdoc
3b809e54 » lukewendling 2008-11-17 init import 1 == Expressive Record
2
c3725657 » lukewendling 2008-11-18 updated README 3 Add meaningful names for belongs_to associations to Rails 2.1 model object dirty changes (http://dev.rubyonrails.org/changeset/9127) to help with rolling your own history/audit logger.
3b809e54 » lukewendling 2008-11-17 init import 4
5 == Install
6
8d5c9de4 » lukewendling 2008-11-17 history table name is confi... 7 script/plugin install git://github.com/lukewendling/expressive_record.git
8 or
9 sudo gem install lukewendling-expressive_record --source http://gems.github.com
10
c3725657 » lukewendling 2008-11-18 updated README 11 create a migration for the audit table (see USAGE)
3b809e54 » lukewendling 2008-11-17 init import 12
13 == Usage
14
15 ActiveRecord 2.1 introduces dirty changes; the ability to query a model object to track attribute changes before the record is saved using #changes, #changed, etc.
16
c3725657 » lukewendling 2008-11-18 updated README 17 However, belongs_to associations are cached simply as foreign key changes, so Ticket#changes yields something like {"status_id" => ["111", "222"]}, which isn't especially helpful when rolling your own audit logger.
3b809e54 » lukewendling 2008-11-17 init import 18
c3725657 » lukewendling 2008-11-18 updated README 19 Expressive Record turns association (foreign key) changes into meaningful terms when the changes are saved to your audit table.
3b809e54 » lukewendling 2008-11-17 init import 20
21 class Ticket < ActiveRecord::Base
8d5c9de4 » lukewendling 2008-11-17 history table name is confi... 22 include ExpressiveRecord
23
24 has_many :ticket_changes
3b809e54 » lukewendling 2008-11-17 init import 25
c3725657 » lukewendling 2008-11-18 updated README 26 # pass in the name of your audit table (optional)
8d5c9de4 » lukewendling 2008-11-17 history table name is confi... 27 express_changes :ticket_changes
3b809e54 » lukewendling 2008-11-17 init import 28
29 end
30
c3725657 » lukewendling 2008-11-18 updated README 31 express_changes adds a before_update callback to your model that inserts changes into an audit table with the following schema:
3b809e54 » lukewendling 2008-11-17 init import 32
33 class CreateTicketChanges < ActiveRecord::Migration
34 def self.up
35 create_table "ticket_changes", :force => true do |t|
36 t.integer "ticket_id", :null => false
37 t.string "attribute_type", :null => false
38 t.text "old_value"
39 t.text "new_value"
40 t.timestamps
41 end
42 end
8d5c9de4 » lukewendling 2008-11-17 history table name is confi... 43 end
44
906f577d » lukewendling 2008-11-24 before_update callback now ... 45 If using a before_update callback in subclasses, be sure to call 'super' as needed:
46
47 class A
48 # a before_update callback is auto-magically added
49 express_changes
50 end
51
52 class A < B
53 def before_update
54 self.status = 'New' # do this before auditing
55 super # now insert changes into audit log
56 end
57 end
58
c3725657 » lukewendling 2008-11-18 updated README 59 == Limitations
60 * the current implementation assumes that all belongs_to foreign keys use Rails conventional names, like user_id or status_id. if you are connecting to a legacy db with fk's like customerID or whatever, this won't work.
61
8d5c9de4 » lukewendling 2008-11-17 history table name is confi... 62 == TODO
c3725657 » lukewendling 2008-11-18 updated README 63 * add migration generator to create conventionally-named log table (i.e. ticket_changes) to schema