Adds thread-safe PaperTrail.whodunnit(value) { ... }

Allows to set whodunnit for the block, e.g.

PaperTrail.whodunnit("me") { Booking.past.not_charged.each(&:charge) }
This commit is contained in:
Dorian Marié 2017-02-28 18:12:20 -08:00 committed by Jared Beck
parent 65f62bc51d
commit dd1de6480c
4 changed files with 60 additions and 7 deletions

View File

@ -11,7 +11,8 @@ recommendations of [keepachangelog.com](http://keepachangelog.com/).
### Added
- None
- [#932](https://github.com/airblade/paper_trail/pull/932) -
`PaperTrail.whodunnit` now accepts a block.
### Fixed

View File

@ -708,6 +708,14 @@ widget.update_attributes :name => 'Wibble'
widget.versions.last.whodunnit # Andy Stewart
```
`whodunnit` also accepts a block, a convenient way to temporarily set the value.
```ruby
PaperTrail.whodunnit("Dorian Marié") do
widget.update_attributes :name => 'Wibble'
end
```
If your controller has a `current_user` method, PaperTrail provides a
`before_action` that will assign `current_user.id` to `PaperTrail.whodunnit`.
You can add this `before_action` to your `ApplicationController`.

View File

@ -87,10 +87,33 @@ module PaperTrail
paper_trail_store[:whodunnit] = value
end
# Returns who is reponsible for any changes that occur.
# If nothing passed, returns who is reponsible for any changes that occur.
#
# PaperTrail.whodunnit = "someone"
# PaperTrail.whodunnit # => "someone"
#
# If value and block passed, set this value as whodunnit for the duration of the block
#
# PaperTrail.whodunnit("me") do
# puts PaperTrail.whodunnit # => "me"
# end
#
# @api public
def whodunnit
paper_trail_store[:whodunnit]
def whodunnit(value = nil)
if value
raise ArgumentError, "no block given" unless block_given?
previous_whodunnit = paper_trail_store[:whodunnit]
paper_trail_store[:whodunnit] = value
begin
yield
ensure
paper_trail_store[:whodunnit] = previous_whodunnit
end
else
paper_trail_store[:whodunnit]
end
end
# Sets any information from the controller that you want PaperTrail to

View File

@ -75,10 +75,31 @@ RSpec.describe PaperTrail do
end
describe ".whodunnit" do
before(:all) { described_class.whodunnit = "foobar" }
context "when set globally" do
before(:all) { described_class.whodunnit = "foobar" }
it "is nil by default" do
expect(described_class.whodunnit).to be_nil
it "is set to `nil` by default" do
expect(described_class.whodunnit).to be_nil
end
end
context "with block passed" do
it "sets whodunnit only for the block passed" do
described_class.whodunnit("foo") do
expect(described_class.whodunnit).to eq("foo")
end
expect(described_class.whodunnit).to be_nil
end
it "sets whodunnit only for the current thread" do
described_class.whodunnit("foo") do
expect(described_class.whodunnit).to eq("foo")
Thread.new { expect(described_class.whodunnit).to be_nil }.join
end
expect(described_class.whodunnit).to be_nil
end
end
end