Skip to content

Commit

Permalink
Clarify who was responsible for changes.
Browse files Browse the repository at this point in the history
N.B. This commit adds an `originator` method to the Active::Record
mixin so be careful if your AR object already has a method of the same
name.
  • Loading branch information
airblade committed Jun 28, 2010
1 parent 424724d commit f27763b
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 8 deletions.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,25 @@ In a migration or in `script/console` you can set who is responsible like this:
>> widget.update_attributes :name => 'Wibble'
>> widget.versions.last.whodunnit # Andy Stewart

N.B. A `version`'s `whodunnit` records who changed the object causing the `version` to be stored. Because a `version` stores the object as it looked before the change (see the table above), `whodunnit` returns who stopped the object looking like this -- not who made it look like this. Hence `whodunnit` is aliased as `terminator`.

To find out who made a `version`'s object look that way, use `version.originator`. And to find out who made a "live" object look like it does, use `originator` on the object.

>> widget = Widget.find 153 # assume widget has 0 versions
>> PaperTrail.whodunnit = 'Alice'
>> widget.update_attributes :name => 'Yankee'
>> widget.originator # 'Alice'
>> PaperTrail.whodunnit = 'Bob'
>> widget.update_attributes :name => 'Zulu'
>> widget.originator # 'Bob'
>> first_version, last_version = widget.versions.first, widget.versions.last
>> first_version.whodunnit # 'Alice'
>> first_version.originator # nil
>> first_version.terminator # 'Alice'
>> last_version.whodunnit # 'Bob'
>> last_version.originator # 'Alice'
>> last_version.terminator # 'Bob'


## Storing metadata

Expand Down
5 changes: 5 additions & 0 deletions lib/paper_trail/has_paper_trail.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ def record_destroy
end
end

# Returns who put the object into its current state.
def originator
versions.last.try :whodunnit
end

# Returns the object (not a Version) as it was at the given timestamp.
def version_at(timestamp)
# Short-circuit if the current state is applicable.
Expand Down
13 changes: 12 additions & 1 deletion lib/paper_trail/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,17 @@ def reify
end
end

# Returns who put the item into the state stored in this version.
def originator
previous.try :whodunnit
end

# Returns who changed the item from the state it had in this version.
# This is an alias for `whodunnit`.
def terminator
whodunnit
end

def next
Version.first :conditions => ["id > ? AND item_type = ? AND item_id = ?", id, item_type, item_id],
:order => 'id ASC'
Expand All @@ -54,5 +65,5 @@ def index
Version.all(:conditions => ["item_type = ? AND item_id = ?", item_type, item_id],
:order => 'id ASC').index(self)
end

end
34 changes: 27 additions & 7 deletions test/paper_trail_model_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -310,29 +310,49 @@ class HasPaperTrailModelTest < Test::Unit::TestCase

context 'A papertrail with somebody making changes' do
setup do
PaperTrail.whodunnit = 'Colonel Mustard'
@widget = Widget.new :name => 'Fidget'
end

context 'when a record is created' do
setup { @widget.save }
setup do
PaperTrail.whodunnit = 'Alice'
@widget.save
@version = @widget.versions.last # only 1 version
end

should 'track who made the change' do
assert_equal 'Colonel Mustard', @widget.versions.last.whodunnit
assert_equal 'Alice', @version.whodunnit
assert_nil @version.originator
assert_equal 'Alice', @version.terminator
assert_equal 'Alice', @widget.originator
end

context 'when a record is updated' do
setup { @widget.update_attributes :name => 'Rivet' }
setup do
PaperTrail.whodunnit = 'Bob'
@widget.update_attributes :name => 'Rivet'
@version = @widget.versions.last
end

should 'track who made the change' do
assert_equal 'Colonel Mustard', @widget.versions.last.whodunnit
assert_equal 'Bob', @version.whodunnit
assert_equal 'Alice', @version.originator
assert_equal 'Bob', @version.terminator
assert_equal 'Bob', @widget.originator
end

context 'when a record is destroyed' do
setup { @widget.destroy }
setup do
PaperTrail.whodunnit = 'Charlie'
@widget.destroy
@version = @widget.versions.last
end

should 'track who made the change' do
assert_equal 'Colonel Mustard', @widget.versions.last.whodunnit
assert_equal 'Charlie', @version.whodunnit
assert_equal 'Bob', @version.originator
assert_equal 'Charlie', @version.terminator
assert_equal 'Charlie', @widget.originator
end
end
end
Expand Down

0 comments on commit f27763b

Please sign in to comment.