tablesalt 0.26.0.4 → 0.27.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d9734463d5faeecc30bc70bfa5e36078c7854bff1cadac30121eacfc74f6c588
4
- data.tar.gz: 964b8af5135b89ed291683fa9e1060edc63d2f1fa1e7208f65d43d14178abbc1
3
+ metadata.gz: 903ef715b92c22c371b74ed976cf05d459eb8cf5ccfc8c026958dd5551a22f45
4
+ data.tar.gz: 55db6947da0c3642ba8735d39255b60f2ae110f65ddd78bf7f3071ac47f2d328
5
5
  SHA512:
6
- metadata.gz: c3e259d04b5587176c3c5dd69274b0dfcd09b1ac6213a60d5cad67b9b1e5123a7a68e59ab3be0e26d54f34ae8427780c62f40c617400756d896a1b66bff71ae2
7
- data.tar.gz: 3d022dfc81459e6009c3fe9497337f33152e1002efedb1577ade4d160280bf2d331bb7dc746b14ad84c23fb61c805313bece1ec90d1d535bc68f3867699f15e6
6
+ metadata.gz: '08c265694d36c0a64a790a9a5796ed52fe5e2b4ad19aaf30fbc30782f79c87cca80773655cc2a39d72825afbfef2f55ce620f179d27146b0c9c2ee788f4c959a'
7
+ data.tar.gz: 19f07e26b872e1e2df3c38beb0c6851b106f4501da251a27f92fe397aeea49b3e8d0b865e4a04a2a639caaa160b32427b1edcec6da1b35b24cdfdd8229d48975
data/README.md CHANGED
@@ -31,7 +31,140 @@ Or install it yourself as:
31
31
 
32
32
  ## Usage
33
33
 
34
- TODO: Write usage instructions here
34
+ ### ClassPass
35
+
36
+ TODO: write usage instructions
37
+
38
+ ### DSLAccessor
39
+
40
+ TODO: write usage instructions
41
+
42
+ ### Isolation
43
+
44
+ TODO: write usage instructions
45
+
46
+ ### StringableObject
47
+
48
+ TODO: write usage instructions
49
+
50
+ ### ThreadAccessor
51
+
52
+ In the simplest use case, a ThreadAccessor can be used to set a value on the current working thread to be used later on. The `thread_accessor` method creates a singleton and instance method for reading and writing a given variable stored on the thread.
53
+
54
+ #### Defined methods
55
+ * `thread_reader(method_name, thread_key = method_name, private: true)`
56
+ Defines singleton method and instance method to read from the given thread key.
57
+ * `thread_writer(method_name, thread_key = method_name, private: true)`
58
+ Defines singleton method and instance method to write to the given thread key.
59
+ * `thread_accessor(method_name, thread_key = method_name, private: true)`
60
+ Calls `thread_reader` and `thread_writer` with the given arguments.
61
+
62
+ #### Example
63
+
64
+ ```ruby
65
+ class CurrentUser
66
+ include TableSalt::ThreadAccessor
67
+
68
+ thread_accessor :current_user
69
+
70
+ def self.set(user)
71
+ self.current_user = user
72
+ end
73
+ end
74
+
75
+ CurrentUser.set(User.first)
76
+
77
+ # then, sometime later within the same request:
78
+ CurrentUser.current_user
79
+ # => #<User id: 1>
80
+ ```
81
+
82
+ #### Thread Safety
83
+ Yep, when you mess with thread variables, you need to think about thread safety. For Rack applications, `ThreadAccessor` ships with a Rack middleware component:
84
+ ```ruby
85
+ # in config/initializers/rack.rb, or config/initializers/tablesalt.rb, or anywhere else in your boot path:
86
+ config.middleware.use TableSalt::ThreadAccessor::RackMiddleware
87
+ ```
88
+
89
+ If your application isn't on Rack, you'll need to add a little more code manually to take care of this:
90
+ ```ruby
91
+ # Somewhere in your request path:
92
+ class YourMiddleware
93
+ def call
94
+ ThreadAccessor.clean_thread_context { yield }
95
+ end
96
+ end
97
+ ```
98
+
99
+ #### Namespaces
100
+
101
+ Maybe you wrote a gem that, say, sets a current user value on the thread to enable some other cool behavior. Since you don't want your gem's behavior to interfere with other behavior of the application, you can use a namespaced thread store instead:
102
+ ```ruby
103
+ module MyGem
104
+ class CurrentUser
105
+ # This isolates the module's thread store for your gem.
106
+ include Tablesalt::ThreadAccessor[MyGem]
107
+
108
+ thread_accessor :current_user
109
+
110
+ def self.set(user)
111
+ self.current_user = user
112
+ end
113
+ end
114
+
115
+ class DoAThing
116
+ include Tablesalt::ThreadAccessor[MyGem]
117
+
118
+ thread_accessor :current_user
119
+ end
120
+ end
121
+
122
+ MyGem::CurrentUser.set(User.first)
123
+
124
+ # then, sometime later within the same request:
125
+ MyGem::DoAThing.current_user
126
+ # => #<User id: 1>
127
+
128
+ # From class defined above:
129
+ CurrentUser.current_user
130
+ # => nil
131
+ ```
132
+
133
+ Note that this will require you to clear your gem's thread store manually. It is recommended you provide your own middleware with your gem to keep the application's thread stores clean:
134
+
135
+ ```ruby
136
+ module MyGem
137
+ class MyMiddleware
138
+ def initialize(app)
139
+ @app = app
140
+ end
141
+
142
+ def call(req)
143
+ ThreadAccessor.clean_thread_context(namespace: MyGem) { @app.call(req) }
144
+ end
145
+ end
146
+ end
147
+ ```
148
+
149
+ #### Test Helpers
150
+
151
+ Tablesalt's spec helper provides custom RSpec matchers for thread accessor methods:
152
+ * `defines_thread_accessor(name, thread_key, private: true, namespace: nil)`
153
+ * `defines_thread_reader(name, thread_key, private: true, namespace: nil)`
154
+ * `defines_thread_writer(name, thread_key, private: true, namespace: nil)`
155
+
156
+ If your application uses ThreadAccessor, you'll need to clear the thread stores between test runs.
157
+ * **RSpec**
158
+ If you're using RSpec, you're in luck! Just `require tablesalt/spec_helper` in `spec_helper.rb` or `rails_helper.rb`.
159
+ * **Minitest & others**
160
+ If you're using Minitest or some other testing framework, you'll need to clear things out manually. This is pretty simple, just run the following after each test run:
161
+ ```ruby
162
+ Thread.current[Tablesalt::ThreadAccessor::THREAD_ACCESSOR_STORE_THREAD_KEY] = nil
163
+ ```
164
+
165
+ ### UsesHashForEquality
166
+
167
+ TODO: write usage instructions
35
168
 
36
169
  ## Development
37
170
 
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.configure do |config|
4
+ config.after(:each) do
5
+ Thread.current[Tablesalt::ThreadAccessor::THREAD_ACCESSOR_STORE_THREAD_KEY] = nil
6
+ end
7
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ # RSpec matcher to assert the definition of a thread accessor
4
+ #
5
+ # class MyClass
6
+ # include Tablesalt::ThreadAccessor
7
+ #
8
+ # thread_accessor :foo, :a_foo_key
9
+ # end
10
+ #
11
+ # RSpec.describe MyClass do
12
+ # subject { described_class }
13
+ #
14
+ # it { is_expected.to define_thread_accessor :foo, :a_foo_key, private: false }
15
+ # end
16
+ RSpec::Matchers.define :define_thread_accessor do |accessor_name, thread_key, **options|
17
+ match do |subject|
18
+ expect(subject).to define_thread_reader accessor_name, thread_key, **options
19
+ expect(subject).to define_thread_writer accessor_name, thread_key, **options
20
+ end
21
+ end
@@ -5,7 +5,7 @@ require "active_support/core_ext/hash/keys"
5
5
  # RSpec matcher to assert the definition of a thread accessor
6
6
  #
7
7
  # class MyClass
8
- # include Tablesalt::ConfigDelegation
8
+ # include Tablesalt::ThreadAccessor
9
9
  #
10
10
  # thread_reader :a_thread_key
11
11
  # end
@@ -16,20 +16,21 @@ require "active_support/core_ext/hash/keys"
16
16
  # it { is_expected.to define_thread_reader :a_thread_key, private: false }
17
17
  # end
18
18
  RSpec::Matchers.define :define_thread_reader do |method_name, thread_key, **options|
19
- attr_reader :subject, :method_name, :thread_key, :private_opt
19
+ attr_reader :subject, :method_name, :thread_key, :private_opt, :namespace
20
20
 
21
- description { "defines#{a_private} thread reader #{method_name.inspect} with thread key #{thread_key.inspect}" }
21
+ description { "define#{a_private} thread reader #{method_name.inspect} with thread key #{thread_key.inspect}#{namespace_failure_message}" }
22
22
 
23
- failure_message { "expected #{subject_module} to define#{a_private} thread reader #{method_name.inspect} with thread key #{thread_key.inspect}" }
24
- failure_message_when_negated { "expected #{subject_module} not to define#{a_private} thread reader #{method_name.inspect} with thread key #{thread_key.inspect}" }
23
+ failure_message { "expected #{subject_module} to define#{a_private} thread reader #{method_name.inspect} with thread key #{thread_key.inspect}#{namespace_failure_message}" }
24
+ failure_message_when_negated { "expected #{subject_module} not to define#{a_private} thread reader #{method_name.inspect} with thread key #{thread_key.inspect}#{namespace_failure_message}" }
25
25
 
26
- match_unless_raises do |subject|
27
- options.assert_valid_keys(:private)
26
+ match do |subject|
27
+ options.assert_valid_keys(:private, :namespace)
28
28
 
29
29
  @subject = subject
30
30
  @method_name = method_name
31
31
  @thread_key = thread_key.to_sym
32
32
  @private_opt = options.fetch(:private, true)
33
+ @namespace = options.fetch(:namespace, nil)
33
34
 
34
35
  with_value_on_thread do
35
36
  expect(instance).to be_respond_to(method_name, true)
@@ -50,11 +51,12 @@ RSpec::Matchers.define :define_thread_reader do |method_name, thread_key, **opti
50
51
  private
51
52
 
52
53
  def with_value_on_thread
53
- Thread.current[thread_key] = stubbed_value
54
+ value_before = Tablesalt::ThreadAccessor.store(namespace)[thread_key]
55
+ Tablesalt::ThreadAccessor.store(namespace)[thread_key] = stubbed_value
54
56
 
55
57
  yield
56
58
 
57
- Thread.current[thread_key] = nil
59
+ Tablesalt::ThreadAccessor.store(namespace)[thread_key] = value_before
58
60
  end
59
61
 
60
62
  def subject_module
@@ -62,19 +64,12 @@ RSpec::Matchers.define :define_thread_reader do |method_name, thread_key, **opti
62
64
  end
63
65
 
64
66
  def klass
65
- @klass ||=
66
- case subject
67
- when Class
68
- subject
69
- when Module
70
- Class.new(subject)
71
- else
72
- subject.class
73
- end
67
+ @klass ||= subject.is_a?(Module) ? subject : subject.class
74
68
  end
75
69
 
76
70
  def instance
77
71
  return subject unless subject.is_a?(Module)
72
+ return subject unless subject.respond_to?(:new)
78
73
 
79
74
  @instance ||= begin
80
75
  allow(klass).to receive(:initialize).with(any_args)
@@ -91,4 +86,10 @@ RSpec::Matchers.define :define_thread_reader do |method_name, thread_key, **opti
91
86
 
92
87
  " a private"
93
88
  end
89
+
90
+ def namespace_failure_message
91
+ return if namespace.blank?
92
+
93
+ " in #{namespace.inspect} namespace"
94
+ end
94
95
  end
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/hash/keys"
4
+
5
+ # RSpec matcher to assert the definition of a thread accessor
6
+ #
7
+ # class MyClass
8
+ # include Tablesalt::ThreadAccessor
9
+ #
10
+ # thread_writer :foo, :a_foo_key
11
+ # end
12
+ #
13
+ # RSpec.describe MyClass do
14
+ # subject { described_class }
15
+ #
16
+ # it { is_expected.to define_thread_writer :foo, :a_foo_key, private: false }
17
+ # end
18
+ RSpec::Matchers.define :define_thread_writer do |writer_name, thread_key, **options|
19
+ attr_reader :subject, :writer_name, :method_name, :thread_key, :private_opt, :namespace
20
+
21
+ description { "define#{a_private} thread writer #{writer_name.inspect} with thread key #{thread_key.inspect}#{namespace_failure_message}" }
22
+
23
+ failure_message { "expected #{subject_module} to define#{a_private} thread writer #{writer_name.inspect} with thread key #{thread_key.inspect}#{namespace_failure_message}" }
24
+ failure_message_when_negated { "expected #{subject_module} not to define#{a_private} thread writer #{writer_name.inspect} with thread key #{thread_key.inspect}#{namespace_failure_message}" }
25
+
26
+ match do |subject|
27
+ options.assert_valid_keys(:private, :namespace)
28
+
29
+ @subject = subject
30
+ @writer_name = writer_name
31
+ @method_name = "#{writer_name}="
32
+ @thread_key = thread_key.to_sym
33
+ @private_opt = options.fetch(:private, true)
34
+ @namespace = options.fetch(:namespace, nil)
35
+
36
+ expect(instance).to be_respond_to(method_name, true)
37
+ expect(klass).to be_respond_to(method_name, true)
38
+
39
+ klass.__send__(method_name, class_stubbed_value)
40
+ expect(Tablesalt::ThreadAccessor.store(namespace)[thread_key]).to eq class_stubbed_value
41
+
42
+ instance.__send__(method_name, instance_stubbed_value)
43
+ expect(Tablesalt::ThreadAccessor.store(namespace)[thread_key]).to eq instance_stubbed_value
44
+
45
+ if private_opt
46
+ expect(klass).to be_private_method_defined method_name
47
+ expect(klass.singleton_class).to be_private_method_defined method_name
48
+ end
49
+
50
+ true
51
+ end
52
+
53
+ private
54
+
55
+ def subject_module
56
+ subject.is_a?(Module) ? subject : subject.class
57
+ end
58
+
59
+ def klass
60
+ @klass ||= subject.is_a?(Module) ? subject : subject.class
61
+ end
62
+
63
+ def instance
64
+ return subject unless subject.is_a?(Module)
65
+ return subject unless subject.respond_to?(:new)
66
+
67
+ @instance ||= begin
68
+ allow(klass).to receive(:initialize).with(any_args)
69
+ subject.new
70
+ end
71
+ end
72
+
73
+ def class_stubbed_value
74
+ @class_stubbed_value ||= double("class thread value")
75
+ end
76
+
77
+ def instance_stubbed_value
78
+ @instance_stubbed_value ||= double("instance thread value")
79
+ end
80
+
81
+ def a_private
82
+ return unless private_opt
83
+
84
+ " a private"
85
+ end
86
+
87
+ def namespace_failure_message
88
+ return if namespace.blank?
89
+
90
+ " in #{namespace.inspect} namespace"
91
+ end
92
+ end
@@ -1,4 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "custom_matchers/define_thread_accessor"
3
4
  require_relative "custom_matchers/define_thread_reader"
5
+ require_relative "custom_matchers/define_thread_writer"
4
6
  require_relative "custom_matchers/isolate"
@@ -1,3 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "rspec/custom_matchers"
4
+ require_relative "rspec/config"
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tablesalt
4
+ module ThreadAccessor
5
+ module Management
6
+ def store(namespace = nil)
7
+ raise ArgumentError, "cannot request a namespaced store from a namespaced accessor" if namespace.present? && self::THREAD_ACCESSOR_STORE_NAMESPACE.present?
8
+
9
+ namespace = self::THREAD_ACCESSOR_STORE_NAMESPACE if namespace.nil?
10
+
11
+ stores = Thread.current[Tablesalt::ThreadAccessor::THREAD_ACCESSOR_STORE_THREAD_KEY] ||= {}
12
+ stores[namespace] ||= ThreadStore.new
13
+ end
14
+
15
+ # Cleans up ThreadAccessor state after given block executes
16
+ #
17
+ # @param :logger [Logger] Optional; A logger instance that implements the method :warn to send warning messages to
18
+ # @yield Required; Yields no variables to the given block
19
+ def clean_thread_context(logger: nil, namespace: nil)
20
+ if store(namespace).present?
21
+ if logger.nil?
22
+ puts "WARNING: ThreadAccessor variables set outside ThreadAccessor context: #{store(namespace).keys.join(", ")}"
23
+ else
24
+ logger.warn("ThreadAccessor variables set outside ThreadAccessor context: #{store(namespace).keys.join(", ")}")
25
+ end
26
+ end
27
+
28
+ yield
29
+ ensure
30
+ store(namespace).clear
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tablesalt
4
+ module ThreadAccessor
5
+ class RackMiddleware
6
+ def initialize(app)
7
+ @app = app
8
+ end
9
+
10
+ # Clears thread variables after request is finished processing.
11
+ # Make sure this middleware appears +before+ anything that may set
12
+ # thread variables using ThreadAccessor
13
+ def call(req)
14
+ ThreadAccessor.clean_thread_context(logger: logger) { @app.call(req) }
15
+ end
16
+
17
+ def logger
18
+ return unless @app.respond_to? :logger
19
+
20
+ @app.logger
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tablesalt
4
+ module ThreadAccessor
5
+ class ScopedAccessor < Module
6
+ attr_reader :scope
7
+
8
+ def initialize(scope)
9
+ @scope = scope
10
+
11
+ extend ActiveSupport::Concern
12
+ extend Management
13
+ include ThreadAccessor
14
+
15
+ const_set :THREAD_ACCESSOR_STORE_NAMESPACE, scope
16
+ end
17
+
18
+ def name
19
+ "#{self.class}:#{scope}"
20
+ end
21
+
22
+ def inspect
23
+ "#<#{name}>"
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tablesalt
4
+ module ThreadAccessor
5
+ module StoreInstance
6
+ private
7
+
8
+ def __thread_accessor_store_instance__
9
+ ThreadAccessor.store(respond_to?(:const_get) ? self::THREAD_ACCESSOR_STORE_NAMESPACE : self.class::THREAD_ACCESSOR_STORE_NAMESPACE)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/hash_with_indifferent_access"
4
+
5
+ module Tablesalt
6
+ module ThreadAccessor
7
+ class ThreadStore
8
+ delegate :==, to: :hash
9
+ delegate_missing_to :hash
10
+
11
+ def hash
12
+ @hash ||= HashWithIndifferentAccess.new
13
+ end
14
+ end
15
+ end
16
+ end
@@ -1,12 +1,49 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/concern"
4
+ require "active_support/core_ext/module/delegation"
4
5
 
6
+ require_relative "thread_accessor/management"
7
+ require_relative "thread_accessor/rack_middleware"
8
+ require_relative "thread_accessor/scoped_accessor"
9
+ require_relative "thread_accessor/store_instance"
10
+ require_relative "thread_accessor/thread_store"
11
+
12
+ # WARNING: This module is still in beta mode and will likely change significantly soon. Tread carefully...
5
13
  module Tablesalt
6
14
  module ThreadAccessor
7
15
  extend ActiveSupport::Concern
16
+ extend Management
17
+
18
+ THREAD_ACCESSOR_STORE_THREAD_KEY = :__tablesalt_thread_accessor_store__
19
+
20
+ # nil by default, gets overridden by ScopedAccessor
21
+ THREAD_ACCESSOR_STORE_NAMESPACE = nil
22
+
23
+ include StoreInstance
24
+
25
+ class << self
26
+ # @example
27
+ # module MyGem
28
+ # class MyClass
29
+ # include Tablesalt::ThreadAccessor[:my_gem]
30
+ #
31
+ # # Stored in a separate thread store for :my_gem, safe from mischievous app developers
32
+ # thread_accessor :foo, :my_foo
33
+ # end
34
+ # end
35
+ #
36
+ # @param scope [String, Symbol] A namespace for the thread variables
37
+ # @return [Module] A ThreadAccessor module to be included into your class
38
+ def [](scope)
39
+ @scoped_accessors ||= {}
40
+ @scoped_accessors[scope] ||= ScopedAccessor.new(scope)
41
+ end
42
+ end
8
43
 
9
44
  module ClassMethods
45
+ include StoreInstance
46
+
10
47
  private
11
48
 
12
49
  # Defines an instance method and a singleton method to read from a given key in Thread.current
@@ -29,8 +66,8 @@ module Tablesalt
29
66
  # @param thread_key [String, Symbol] The key to read from Thread.current
30
67
  # @option :private [Boolean] If true, both defined methods will be private. Default: true
31
68
  def thread_reader(method, thread_key, **options)
32
- define_method(method) { Thread.current[thread_key] }
33
- define_singleton_method(method) { Thread.current[thread_key] }
69
+ define_method(method) { __thread_accessor_store_instance__[thread_key] }
70
+ define_singleton_method(method) { __thread_accessor_store_instance__[thread_key] }
34
71
 
35
72
  return unless options.fetch(:private, true)
36
73
 
@@ -52,14 +89,25 @@ module Tablesalt
52
89
  # Thread.current[:foo]
53
90
  # => "bar"
54
91
  #
92
+ # Note::
93
+ # All written thread variables are tracked on-thread, but will not be automatically cleared when
94
+ # the thread is done processing a request/unit of work. Make sure to either use the provided
95
+ # {ThreadAccessor::RackMiddleware} or run {ThreadAccessor.clean_thread_context} manually once
96
+ # the thread is finished to avoid pollluting other requests.
97
+ #
98
+ # Gem Authors::
99
+ # Thread variables should ideally be kept in a namespaced store instead of the global one. This means
100
+ # you are responsible for clearing your own store - either add your own middleware or advise users how
101
+ # to clear the thread store themselves.
102
+ #
55
103
  # @param method [String, Symbol] The name of the writer method
56
104
  # @param thread_key [String, Symbol] The key to write to on Thread.current
57
105
  # @option :private [Boolean] If true, both defined methods will be private. Default: true
58
106
  def thread_writer(method, thread_key, **options)
59
107
  method_name = "#{method}="
60
108
 
61
- define_method(method_name) { |value| Thread.current[thread_key] = value }
62
- define_singleton_method(method_name) { |value| Thread.current[thread_key] = value }
109
+ define_method(method_name) { |value| __thread_accessor_store_instance__[thread_key] = value }
110
+ define_singleton_method(method_name) { |value| __thread_accessor_store_instance__[thread_key] = value }
63
111
 
64
112
  return unless options.fetch(:private, true)
65
113
 
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Tablesalt
4
4
  # This constant is managed by spicerack
5
- VERSION = "0.26.0.4"
5
+ VERSION = "0.27.0"
6
6
  end
data/lib/tablesalt.rb CHANGED
@@ -3,13 +3,13 @@
3
3
  require "active_support"
4
4
  require "short_circu_it"
5
5
 
6
- require "tablesalt/version"
7
-
8
- require "tablesalt/class_pass"
9
- require "tablesalt/dsl_accessor"
10
- require "tablesalt/isolation"
11
- require "tablesalt/stringable_object"
12
- require "tablesalt/thread_accessor"
13
- require "tablesalt/uses_hash_for_equality"
6
+ require_relative "tablesalt/version"
7
+
8
+ require_relative "tablesalt/class_pass"
9
+ require_relative "tablesalt/dsl_accessor"
10
+ require_relative "tablesalt/isolation"
11
+ require_relative "tablesalt/stringable_object"
12
+ require_relative "tablesalt/thread_accessor"
13
+ require_relative "tablesalt/uses_hash_for_equality"
14
14
 
15
15
  module Tablesalt; end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tablesalt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.26.0.4
4
+ version: 0.27.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jordan Minneti
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-05-17 00:00:00.000000000 Z
11
+ date: 2021-08-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -53,12 +53,20 @@ files:
53
53
  - lib/tablesalt/class_pass.rb
54
54
  - lib/tablesalt/dsl_accessor.rb
55
55
  - lib/tablesalt/isolation.rb
56
+ - lib/tablesalt/rspec/config.rb
56
57
  - lib/tablesalt/rspec/custom_matchers.rb
58
+ - lib/tablesalt/rspec/custom_matchers/define_thread_accessor.rb
57
59
  - lib/tablesalt/rspec/custom_matchers/define_thread_reader.rb
60
+ - lib/tablesalt/rspec/custom_matchers/define_thread_writer.rb
58
61
  - lib/tablesalt/rspec/custom_matchers/isolate.rb
59
62
  - lib/tablesalt/spec_helper.rb
60
63
  - lib/tablesalt/stringable_object.rb
61
64
  - lib/tablesalt/thread_accessor.rb
65
+ - lib/tablesalt/thread_accessor/management.rb
66
+ - lib/tablesalt/thread_accessor/rack_middleware.rb
67
+ - lib/tablesalt/thread_accessor/scoped_accessor.rb
68
+ - lib/tablesalt/thread_accessor/store_instance.rb
69
+ - lib/tablesalt/thread_accessor/thread_store.rb
62
70
  - lib/tablesalt/uses_hash_for_equality.rb
63
71
  - lib/tablesalt/version.rb
64
72
  homepage: https://github.com/Freshly/spicerack/tree/main/tablesalt
@@ -68,7 +76,7 @@ metadata:
68
76
  homepage_uri: https://github.com/Freshly/spicerack/tree/main/tablesalt
69
77
  source_code_uri: https://github.com/Freshly/spicerack/tree/main/tablesalt
70
78
  changelog_uri: https://github.com/Freshly/spicerack/blob/main/tablesalt/CHANGELOG.md
71
- documentation_uri: https://www.rubydoc.info/gems/tablesalt/0.26.0.4
79
+ documentation_uri: https://www.rubydoc.info/gems/tablesalt/0.27.0
72
80
  post_install_message:
73
81
  rdoc_options: []
74
82
  require_paths:
@@ -84,7 +92,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
84
92
  - !ruby/object:Gem::Version
85
93
  version: '0'
86
94
  requirements: []
87
- rubygems_version: 3.2.17
95
+ rubygems_version: 3.2.25
88
96
  signing_key:
89
97
  specification_version: 4
90
98
  summary: Miscellaneous helper modules, POROs, and more, that standardize common behavior