close #334; Add small-scope 'whodunnit' method to PaperTrail::Model::InstanceMethods

This commit is contained in:
Ben Atkins 2014-03-11 17:55:44 -04:00
parent 52823d2fb2
commit 44a632eea6
5 changed files with 76 additions and 13 deletions

View File

@ -2,6 +2,7 @@
- [#340](https://github.com/airblade/paper_trail/issues/340) - Prevent potential error encountered when using the `InstallGenerator`
with Rails `4.1.0.rc1`.
- [#334](https://github.com/airblade/paper_trail/pull/334) - Add small-scope `whodunnit` method to `PaperTrail::Model::InstanceMethods`.
- [#329](https://github.com/airblade/paper_trail/issues/329) - Add `touch_with_version` method to `PaperTrail::Model::InstanceMethods`,
to allow for generating a version `touch`ing a model.
- [#328](https://github.com/airblade/paper_trail/pull/328) / [#326](https://github.com/airblade/paper_trail/issues/326) /

View File

@ -480,13 +480,30 @@ In a console session you can manually set who is responsible like this:
You can avoid having to do this manually by setting your initializer to pick up the username of the current user from the OS, like this:
```ruby
class PaperTrail::Version < ActiveRecord::Base
# config/initializers/paper_trail.rb
module PaperTrail
class Version < ActiveRecord::Base
if defined?(Rails::Console)
PaperTrail.whodunnit = "#{`whoami`.strip}: console"
elsif File.basename($0) == "rake"
PaperTrail.whodunnit = "#{`whoami`.strip}: rake #{ARGV.join ' '}"
end
end
end
```
Sometimes you want to define who is responsible for a change in a small scope without overwriting value of `PaperTrail.whodunnit`. It is possible to define the `whodunnit` value for an operation inside a block like this:
```ruby
>> PaperTrail.whodunnit = 'Andy Stewart'
>> widget.whodunnit('Lucas Souza') do
>> widget.update_attributes :name => 'Wibble'
>> end
>> widget.versions.last.whodunnit # Lucas Souza
>> widget.update_attributes :name => 'Clair'
>> widget.versions.last.whodunnit # Andy Stewart
>> widget.whodunnit('Ben Atkins') { |w| w.update_attributes :name => 'Beth' } # this syntax also works
>> widget.versions.last.whodunnit # Ben Atkins
```
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`.
@ -1062,6 +1079,7 @@ Many thanks to:
* [Vlad Bokov](https://github.com/razum2um)
* [Sean Marcia](https://github.com/SeanMarcia)
* [Chulki Lee](https://github.com/chulkilee)
* [Lucas Souza](https://github.com/lucasas)
## Inspirations

View File

@ -216,6 +216,18 @@ module PaperTrail
self.class.paper_trail_on! if paper_trail_was_enabled
end
# Temporarily overwrites the value of whodunnit and then executes the provided block.
def whodunnit(value)
raise ArgumentError, 'expected to receive a block' unless block_given?
current_whodunnit = PaperTrail.whodunnit
PaperTrail.whodunnit = value
begin
yield self
ensure
PaperTrail.whodunnit = current_whodunnit
end
end
# Mimicks behavior of `touch` method from `ActiveRecord::Persistence`, but generates a version
#
# TODO: lookinto leveraging the `after_touch` callback from `ActiveRecord` to allow the

View File

@ -23,6 +23,39 @@ describe Widget do
describe "Methods" do
describe "Instance", :versioning => true do
describe :whodunnit do
it { should respond_to(:whodunnit) }
context "no block given" do
it "should raise an error" do
expect { widget.whodunnit('Ben') }.to raise_error(ArgumentError, 'expected to receive a block')
end
end
context "block given" do
let(:orig_name) { Faker::Name.name }
let(:new_name) { Faker::Name.name }
before do
PaperTrail.whodunnit = orig_name
widget.versions.last.whodunnit.should == orig_name # persist `widget`
end
it "should modify value of `PaperTrail.whodunnit` while executing the block" do
widget.whodunnit(new_name) do
PaperTrail.whodunnit.should == new_name
widget.update_attributes(:name => 'Elizabeth')
end
widget.versions.last.whodunnit.should == new_name
end
it "should revert the value of `PaperTrail.whodunnit` to it's previous value after executing the block" do
widget.whodunnit(new_name) { |w| w.update_attributes(:name => 'Elizabeth') }
PaperTrail.whodunnit.should == orig_name
end
end
end
describe :touch_with_version do
it { should respond_to(:touch_with_version) }

View File

@ -837,7 +837,6 @@ class HasPaperTrailModelTest < ActiveSupport::TestCase
should 'return its previous self' do
assert_equal @widget.versions[-2].reify, @widget.previous_version
end
end