acts_as_audited_collection is a Rails plugin, which extends ActiveRecord to allow auditing of associations.
The basic feature set is:
- Tracking addition of child records to an association
- Tracking removal of child records
- Tracking a child record being reassociated with a new parent, as a remove followed by an add
- (Optionally) tracking any children which are modified
- (Optionally) tracking when a grandchild is modified by cascading through associations
This plugin is released under the MIT license, and was contributed to the Rails community by the good people at Software Projects.
Add this line to your application's Gemfile:
gem 'acts_as_audited_collection'
And then execute:
$ bundle
Or install it yourself as:
$ gem install acts_as_audited_collection
script/generate audited_collection_migration add_collection_audits_table
rake db:migrate
Specify the version you're upgrading from as a parameter.
rails generate audited_collect_migration upgrade_collection_audits_table 0.4.0
rake db:migrate
Declare an association that looks like:
class Employer < ActiveRecord::Base
has_many :people
acts_as_audited_collection_parent :for => :people
end
class Person < ActiveRecord::Base
belongs_to :employer
acts_as_audited_collection :parent => :employer
end
Person.create :name => 'Fred', :employer => nil # No audit record
e = Employer.create :name => 'Foo Inc.' # No audit record
Person.create :name => 'Mary', :employer => e # Audit record is created
e.people_audits.last.action # 'add'
e.people_audits.last.parent_record # Employer name: 'Foo Inc.'
e.people_audits.last.child_record # Person name: 'Mary'
e.people.create :name => 'Bob' # Audit record is created
e.people.last.destroy # Audit record is created
e.people_audits.last.action # 'remove'
e.people_audits.last.parent_record # Employer name: 'Foo Inc.'
e.people_audits.last.child_record # nil (record was destroyed)
e.people_audits.last.child_record_id # 3 (for example)
e.people_audits.last.child_record_type # 'Person'
p = Person.first # Person name: 'Fred'
p.update_attributes :employer => e # Audit record is created
e.people_audits.last.action # 'add'
e2 = Employer.create :name => 'Bar Ltd.' # No audit record
p.update_attributes :employer => e2 # Two audit records!
e.people_audits.last.action # 'remove'
e2.people_audits.last.action # 'add'
p.update_attributes :employer => e # Changing it back for the sake of my own sanity.
Consider the following alternative "Person" model.
class Person < ActiveRecord::Base
belongs_to :employer
acts_as_audited_collection :parent => :employer,
:track_modifications => true
end
With this, we can now see modifications from the parent (though we make no attempt to ascertain what the modifications were - if you need this, see acts_as_audited)
p = Person.first # Person name: 'Fred'
p.update_attributes :name => 'Freda' # Audit record is created
e.people_audits.last.action # 'modify'
e.people_audits.last.child_record # Person name: 'Freda'
Consider now that a Person might have any number of hobbies.
class Person < ActiveRecord::Base
belongs_to :employer
has_many :hobbies
acts_as_audited_collection :parent => :employer,
:track_modifications => true
acts_as_audited_collection_parent :for => :hobbies
end
class Hobby < ActiveRecord::Base
belongs_to :person
acts_as_audited_collection :parent => :person,
:cascade => true # Cascades audit events to the parent
end
The :cascade => true
option specifies that the audit event in the child record should cascade upward, marking the parent as modified, and therefore generating a 'modify'
audit record in any grandparent for which :track_modifications => true
has been specified..
p = Person.first # Person name: 'Freda'
p.hobbies.create :name => 'Model Trains' # Two audit records created.
p.hobbies_audits.last.action # 'add'
e.people_audits.last.action # 'modify'
e.people_audits.last.child_record # Person name: 'Freda'
e.people_audits.last.parent_record # Employer name: 'Foo Inc.'
Person.without_collection_audit do
p.update_attributes :name => 'Fred' # No audit record
end
Keep in mind that this disables collection auditing completely in the current thread, not just for the Person
model.
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Added some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request