Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Thread safety for #without_versioning #328

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions lib/paper_trail.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,16 @@ def self.enabled_for_controller?
!!paper_trail_store[:request_enabled_for_controller]
end

# Sets whether PaperTrail is enabled or disabled for this model in the current request.
def self.enabled_for_model(model, value)
paper_trail_store[:"request_enabled_for_#{model}"] = value
end

# Returns `true` if PaperTrail is enabled for this model in the current request, `false` otherwise.
def self.enabled_for_model?(model)
!!(paper_trail_store.fetch(:"request_enabled_for_#{model}", model.paper_trail_enabled_for_model))
end

# Set the field which records when a version was created.
def self.timestamp_field=(field_name)
PaperTrail.config.timestamp_field = field_name
Expand Down
16 changes: 10 additions & 6 deletions lib/paper_trail/has_paper_trail.rb
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,16 @@ def has_paper_trail(options = {})

# Switches PaperTrail off for this class.
def paper_trail_off
self.paper_trail_enabled_for_model = false
PaperTrail.enabled_for_model(self, false)
end

# Switches PaperTrail on for this class.
def paper_trail_on
self.paper_trail_enabled_for_model = true
PaperTrail.enabled_for_model(self, true)
end

def paper_trail_enabled_for_model?
PaperTrail.enabled_for_model?(self)
end

def paper_trail_version_class
Expand Down Expand Up @@ -194,11 +198,11 @@ def next_version

# Executes the given method or block without creating a new version.
def without_versioning(method = nil)
paper_trail_was_enabled = self.paper_trail_enabled_for_model
self.class.paper_trail_off
paper_trail_was_enabled = PaperTrail.enabled_for_model?(self.class)
PaperTrail.enabled_for_model(self.class, false)
method ? method.to_proc.call(self) : yield
ensure
self.class.paper_trail_on if paper_trail_was_enabled
PaperTrail.enabled_for_model(self.class, paper_trail_was_enabled)
end

private
Expand Down Expand Up @@ -323,7 +327,7 @@ def changed_and_not_ignored
end

def paper_trail_switched_on?
PaperTrail.enabled? && PaperTrail.enabled_for_controller? && self.paper_trail_enabled_for_model
PaperTrail.enabled? && PaperTrail.enabled_for_controller? && PaperTrail.enabled_for_model?(self.class)
end

def save_version?
Expand Down
4 changes: 2 additions & 2 deletions test/dummy/app/controllers/test_controller.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
class TestController < ActionController::Base
def user_for_paper_trail
Thread.current.object_id
def current_user
@current_user ||= OpenStruct.new(:id => Thread.current.object_id)
end
end
26 changes: 25 additions & 1 deletion test/functional/thread_safety_test.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
require 'test_helper'

class ThreadSafetyTest < ActionController::TestCase
test "be thread safe" do
test "be thread safe when using #set_paper_trail_whodunnit" do
blocked = true

slow_thread = Thread.new do
Expand All @@ -23,4 +23,28 @@ class ThreadSafetyTest < ActionController::TestCase

assert_not_equal slow_thread.value, fast_thread.value
end

test "be thread safe when using #without_versioning" do
enabled = nil

slow_thread = Thread.new do
Widget.new.without_versioning do
sleep(0.01)
enabled = PaperTrail.enabled_for_model?(Widget)
sleep(0.01)
end

enabled
end

fast_thread = Thread.new do
sleep(0.005)
enabled = PaperTrail.enabled_for_model?(Widget)
enabled
end

assert_not_equal slow_thread.value, fast_thread.value
assert Widget.paper_trail_enabled_for_model
assert PaperTrail.enabled_for_model?(Widget)
end
end
2 changes: 1 addition & 1 deletion test/unit/model_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@ def without(&block)
context 'when destroyed "without versioning"' do
should 'leave paper trail off after call' do
@widget.without_versioning :destroy
assert !Widget.paper_trail_enabled_for_model
assert !PaperTrail.enabled_for_model?(Widget)
end
end

Expand Down