Make PaperTrail threadsafe.

This commit is contained in:
Andy Stewart 2010-03-19 14:19:01 +00:00
parent aac0f945c9
commit 9332ff25c2
3 changed files with 28 additions and 24 deletions

View File

@ -18,6 +18,7 @@ PaperTrail lets you track changes to your models' data. It's good for auditing
* No configuration necessary.
* Stores everything in a single database table (generates migration for you).
* Thoroughly tested.
* Threadsafe.
## Rails Version
@ -206,7 +207,7 @@ And on again like this:
## Testing
PaperTrail has a thorough suite of tests. Thanks to [Zachery Hostens](http://github.com/zacheryph) for making them able to run standalone, i.e. without needing PaperTrail to be sitting in a Rails app.
PaperTrail has a thorough suite of tests.
## Articles
@ -225,6 +226,8 @@ Many thanks to:
* [Zachery Hostens](http://github.com/zacheryph)
* [Jeremy Weiskotten](http://github.com/jeremyw)
* [Phan Le](http://github.com/revo)
* [jdrucza](http://github.com/jdrucza)
## Inspirations

View File

@ -3,26 +3,29 @@ require 'paper_trail/has_paper_trail'
require 'paper_trail/version'
module PaperTrail
@@whodunnit = nil
def self.included(base)
base.before_filter :set_whodunnit
end
def self.whodunnit
@@whodunnit.respond_to?(:call) ? @@whodunnit.call : @@whodunnit
Thread.current[:whodunnit]
end
# Sets who is responsible for any changes that occur.
# You would normally use this in a migration or on the console,
# when working with models directly. In a controller it is set
# automatically to the `current_user`.
def self.whodunnit=(value)
@@whodunnit = value
Thread.current[:whodunnit] = value
end
private
protected
# Sets who is responsible for any changes that occur: the controller's
# `current_user`.
def set_whodunnit
@@whodunnit = lambda {
self.send :current_user rescue nil
}
Thread.current[:whodunnit] = self.send :current_user rescue nil
end
end

View File

@ -1,34 +1,32 @@
require File.dirname(__FILE__) + '/test_helper.rb'
require 'test_helper'
class TestController < ActionController::Base
def current_user
@current_user ||= ActiveSupport::SecureRandom.hex(32)
Thread.current.object_id
end
end
class ThreadSafeTest < Test::Unit::TestCase
should "is thread safe when dealing with audit logging" do
should "be thread safe" do
blocked = true
blocked_thread = Thread.new do
slow_thread = Thread.new do
controller = TestController.new
controller.send(:set_whodunnit)
controller.send :set_whodunnit
begin
puts "sleep for .001 sec"
sleep(0.001)
sleep 0.001
end while blocked
PaperTrail.whodunnit
end
fast_running_thread = Thread.new do
fast_thread = Thread.new do
controller = TestController.new
controller.send(:set_whodunnit)
controller.send :set_whodunnit
who = PaperTrail.whodunnit
blocked = false
PaperTrail.whodunnit
who
end
assert_not_equal blocked_thread.value, fast_running_thread.value
assert_not_equal slow_thread.value, fast_thread.value
end
end
end