Optionally ignore attributes.

This commit is contained in:
Andy Stewart 2009-10-28 13:12:36 +00:00
parent 53e1eb4194
commit 52981bfca3
5 changed files with 56 additions and 3 deletions

View File

@ -6,7 +6,7 @@ PaperTrail lets you track changes to your models' data. It's good for auditing
## Features
* Stores every create, update and destroy.
* Does not store updates which don't change anything.
* Does not store updates which don't change anything (or which only change attributes you are ignoring).
* Allows you to get at every version, including the original, even once destroyed.
* Allows you to get at every version even if the schema has since changed.
* Automatically records who was responsible if your controller has a `current_user` method.
@ -87,6 +87,25 @@ Here's a helpful table showing what PaperTrail stores:
PaperTrail stores the values in the Model Before column. Most other auditing/versioning plugins store the After column.
## Ignoring changes to certain attributes
You can ignore changes to certain attributes like this:
class Article < ActiveRecord::Base
has_paper_trail :ignore => [:title, :rating]
end
This means that changes to just the `title` or `rating` will not store another version of the article. It does not mean that the `title` and `rating` attributes will be ignored if some other change causes a new `Version` to be crated. For example:
>> a = Article.create
>> a.versions.length # 1
>> a.update_attributes :title => 'My Title', :rating => 3
>> a.versions.length # 1
>> a.update_attributes :content => 'Hello'
>> a.versions.length # 2
>> a.versions.last.reify.title # 'My Title'
## Reverting And Undeleting A Model
PaperTrail makes reverting to a previous version easy:

View File

@ -6,8 +6,13 @@ module PaperTrail
module ClassMethods
def has_paper_trail
# Options:
# :ignore an array of attributes for which a new +Version+ will not be created if only they change.
def has_paper_trail(options = {})
send :include, InstanceMethods
cattr_accessor :ignore
self.ignore = (options[:ignore] || []).map &:to_s
cattr_accessor :paper_trail_active
self.paper_trail_active = true
@ -36,7 +41,7 @@ module PaperTrail
end
def record_update
if changed? and self.class.paper_trail_active
if changed_and_we_care? and self.class.paper_trail_active
versions.build :event => 'update',
:object => object_to_string(previous_version),
:whodunnit => PaperTrail.whodunnit
@ -63,6 +68,10 @@ module PaperTrail
def object_to_string(object)
object.attributes.to_yaml
end
def changed_and_we_care?
changed? and !(changed - self.class.ignore).empty?
end
end
end

View File

@ -17,10 +17,29 @@ class Fluxor < ActiveRecord::Base
belongs_to :widget
end
class Article < ActiveRecord::Base
has_paper_trail :ignore => [:title]
end
class HasPaperTrailModelTest < Test::Unit::TestCase
load_schema
context 'A record' do
setup { @article = Article.create }
context 'which updates an ignored column' do
setup { @article.update_attributes :title => 'My first title' }
should_not_change('the number of versions') { Version.count }
end
context 'which updates an ignored column and a non-ignored column' do
setup { @article.update_attributes :title => 'My first title', :content => 'Some text here.' }
should_change('the number of versions', :by => 1) { Version.count }
end
end
context 'A new record' do
setup { @widget = Widget.new }

View File

@ -10,5 +10,6 @@ class PaperTrailSchemaTest < ActiveSupport::TestCase
assert_equal [], Version.all
assert_equal [], Wotsit.all
assert_equal [], Fluxor.all
assert_equal [], Article.all
end
end

View File

@ -35,4 +35,9 @@ ActiveRecord::Schema.define(:version => 0) do
t.string :name
end
create_table :articles, :force => true do |t|
t.integer :title
t.string :content
end
end