Skip to content

Commit 1f76b9f

Browse files
committed
Drop RequestStore in favour of ActiveSupport::CurrentAttributes
1 parent 47dbc22 commit 1f76b9f

File tree

5 files changed

+56
-32
lines changed

5 files changed

+56
-32
lines changed

lib/paper_trail/frameworks/rails/railtie.rb

+7
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,12 @@ class Railtie < ::Rails::Railtie
2626
require "paper_trail/frameworks/active_record"
2727
end
2828
end
29+
30+
# ActiveSupport::CurrentAttributes resets all attributes before and after each request.
31+
# Resetting after a request breaks backwards compatibility with the previous RequestStore
32+
# implementation. This initializer ensures this reset is skipped.
33+
initializer "active_support.reset_all_current_attributes_instances" do |app|
34+
app.executor.to_run { PaperTrail::Request::CurrentAttributes.skip_reset = true }
35+
end
2936
end
3037
end

lib/paper_trail/request.rb

+25-27
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# frozen_string_literal: true
22

3-
require "request_store"
3+
require "paper_trail/request/current_attributes"
44

55
module PaperTrail
66
# Manages variables that affect the current HTTP request, such as `whodunnit`.
@@ -20,9 +20,7 @@ class << self
2020
# PaperTrail.request.controller_info # => { ip: '127.0.0.1' }
2121
#
2222
# @api public
23-
def controller_info=(value)
24-
store[:controller_info] = value
25-
end
23+
delegate :controller_info=, to: :current_attributes
2624

2725
# Returns the data from the controller that you want PaperTrail to store.
2826
# See also `PaperTrail::Rails::Controller#info_for_paper_trail`.
@@ -31,9 +29,7 @@ def controller_info=(value)
3129
# PaperTrail.request.controller_info # => { ip: '127.0.0.1' }
3230
#
3331
# @api public
34-
def controller_info
35-
store[:controller_info]
36-
end
32+
delegate :controller_info, to: :current_attributes
3733

3834
# Switches PaperTrail off for the given model.
3935
# @api public
@@ -49,30 +45,29 @@ def enable_model(model_class)
4945

5046
# Sets whether PaperTrail is enabled or disabled for the current request.
5147
# @api public
52-
def enabled=(value)
53-
store[:enabled] = value
54-
end
48+
delegate :enabled=, to: :current_attributes
5549

5650
# Returns `true` if PaperTrail is enabled for the request, `false` otherwise.
5751
# See `PaperTrail::Rails::Controller#paper_trail_enabled_for_controller`.
5852
# @api public
5953
def enabled?
60-
!!store[:enabled]
54+
!!current_attributes.enabled
6155
end
6256

6357
# Sets whether PaperTrail is enabled or disabled for this model in the
6458
# current request.
6559
# @api public
6660
def enabled_for_model(model, value)
67-
store[:"enabled_for_#{model}"] = value
61+
current_attributes.enabled_for[model] = value
6862
end
6963

7064
# Returns `true` if PaperTrail is enabled for this model in the current
7165
# request, `false` otherwise.
7266
# @api public
7367
def enabled_for_model?(model)
7468
model.include?(::PaperTrail::Model::InstanceMethods) &&
75-
!!store.fetch(:"enabled_for_#{model}", true)
69+
!!(current_attributes.enabled_for[model] ||
70+
current_attributes.enabled_for[model].nil?)
7671
end
7772

7873
# Temporarily set `options` and execute a block.
@@ -97,15 +92,13 @@ def with(options)
9792
# inserting a `Version` record.
9893
#
9994
# @api public
100-
def whodunnit=(value)
101-
store[:whodunnit] = value
102-
end
95+
delegate :whodunnit=, to: :current_attributes
10396

104-
# Returns who is reponsible for any changes that occur during request.
97+
# Returns who is responsible for any changes that occur during request.
10598
#
10699
# @api public
107100
def whodunnit
108-
who = store[:whodunnit]
101+
who = current_attributes.whodunnit
109102
who.respond_to?(:call) ? who.call : who
110103
end
111104

@@ -114,31 +107,36 @@ def whodunnit
114107
# @api private
115108
def merge(options)
116109
options.to_h.each do |k, v|
117-
store[k] = v
110+
if k.start_with?("enabled_for_")
111+
model_klass = k.to_s.sub("enabled_for_", "").constantize
112+
current_attributes.enabled_for[model_klass] = v
113+
else
114+
current_attributes.public_send("#{k}=", v)
115+
end
118116
end
119117
end
120118

121119
# @api private
122120
def set(options)
123-
store.clear
121+
current_attributes.reset
124122
merge(options)
125123
end
126124

127-
# Returns a Hash, initializing with default values if necessary.
125+
# Returns the current request attributes with default values initialized if necessary.
128126
# @api private
129-
def store
130-
RequestStore.store[:paper_trail] ||= {
131-
enabled: true
132-
}
127+
def current_attributes
128+
CurrentAttributes.tap do |attrs|
129+
attrs.enabled = true if attrs.enabled.nil?
130+
end
133131
end
134132

135-
# Returns a deep copy of the internal hash from our RequestStore. Keys are
133+
# Returns a deep copy of the current attributes. Keys are
136134
# all symbols. Values are mostly primitives, but whodunnit can be a Proc.
137135
# We cannot use Marshal.dump here because it doesn't support Proc. It is
138136
# unclear exactly how `deep_dup` handles a Proc, but it doesn't complain.
139137
# @api private
140138
def to_h
141-
store.deep_dup
139+
current_attributes.attributes.deep_dup
142140
end
143141

144142
# Provide a helpful error message if someone has a typo in one of their
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# frozen_string_literal: true
2+
3+
module PaperTrail
4+
module Request
5+
# Thread-isolated attributes for managing the current request.
6+
class CurrentAttributes < ActiveSupport::CurrentAttributes
7+
attribute :enabled
8+
attribute :enabled_for
9+
attribute :controller_info
10+
attribute :whodunnit
11+
attribute :skip_reset
12+
13+
def enabled_for
14+
super || self.enabled_for = {}
15+
end
16+
17+
# Overrides ActiveSupport::CurrentAttributes#reset to support skipping.
18+
def reset
19+
return if skip_reset
20+
super
21+
end
22+
end
23+
end
24+
end

paper_trail.gemspec

-3
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,6 @@ has been destroyed.
4949
# See discussion in paper_trail/compatibility.rb
5050
s.add_dependency "activerecord", ::PaperTrail::Compatibility::ACTIVERECORD_GTE
5151

52-
# PT supports request_store versions for 3 years.
53-
s.add_dependency "request_store", "~> 1.4"
54-
5552
s.add_development_dependency "appraisal", "~> 2.4.1"
5653
s.add_development_dependency "byebug", "~> 11.1"
5754
s.add_development_dependency "ffaker", "~> 2.20"

spec/controllers/widgets_controller_spec.rb

-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
RSpec.describe WidgetsController, type: :controller, versioning: true do
66
before { request.env["REMOTE_ADDR"] = "127.0.0.1" }
77

8-
after { RequestStore.store[:paper_trail] = nil }
9-
108
describe "#create" do
119
context "with PT enabled" do
1210
it "stores information like IP address in version" do

0 commit comments

Comments
 (0)