request_store 1.6.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e791505be9e9e0f6f8bf0b3229cb7840f473f71fdb6a4bb7f4d7375a06d11cdf
4
- data.tar.gz: b8866d3e58f810f96e3ea1b4ef7b4491b69cdf0bc6df06e5610c6d8f3312e8dd
3
+ metadata.gz: c9883603b6fb82a3e39d90b6e7509911f3813160d2fe267ad892536305c5d741
4
+ data.tar.gz: 437805cfcdfc5bc8c3c59bafe9d12bf4ae3ba1685e5261ca40dfce79f7cee845
5
5
  SHA512:
6
- metadata.gz: c76ab30766f74dda033ce70567b47df54128775dca712737a946a0c5263a7c668f3e039941efda725749070bc93745f7654f62cdccd695004f4dd84852fcb930
7
- data.tar.gz: 771cc8e824566de385f8d266fe233ea43313dac648bc4d9fbbf8b7e2fe0e1cdabfc5c0633dc09c386a2966e4cccd978dc3e37d38f135574832919641861f29af
6
+ metadata.gz: bb19a5818c773c1e27ee3b1c215d1422bdabecf7929eaf235db48364c0a0f05467203c4c3b651ce9470c6d51f412d1f7d54e0c5043d44f0c2744d22a0e28d727
7
+ data.tar.gz: b0a56bde2842cecf4b291622e332130bed3c175d649f0659024594e4d38a49309a6e1ad40171afc6ee368045e98a93e6c8aa1c56f1235ed50d38d3197298e570
@@ -1,33 +1,33 @@
1
- name: CI
2
-
3
- on:
4
- pull_request:
5
-
6
- push:
7
- branches: [master]
8
-
9
- jobs:
10
- build:
11
- runs-on: ubuntu-latest
12
- strategy:
13
- matrix:
14
- ruby:
15
- - 3.0
16
- - 3.1
17
- - 3.2
18
- - 3.3
19
- - ruby-head
20
- - jruby-9.1
21
- - jruby-9.2
22
- - jruby-9.3
23
- - jruby-head
24
- - truffleruby-head
25
-
26
- steps:
27
- - uses: actions/checkout@v1
28
- - uses: ruby/setup-ruby@v1
29
- with:
30
- ruby-version: ${{ matrix.ruby }}
31
- bundler-cache: true # 'bundle install' and cache
32
- - name: Test
33
- run: bundle exec rake
1
+ name: CI
2
+
3
+ on:
4
+ pull_request:
5
+
6
+ push:
7
+ branches: [master]
8
+
9
+ jobs:
10
+ build:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ ruby:
15
+ - '3.0'
16
+ - 3.1
17
+ - 3.2
18
+ - 3.3
19
+ - ruby-head
20
+ - jruby-9.1
21
+ - jruby-9.2
22
+ - jruby-9.3
23
+ - jruby-head
24
+ - truffleruby-head
25
+
26
+ steps:
27
+ - uses: actions/checkout@v4
28
+ - uses: ruby/setup-ruby@v1
29
+ with:
30
+ ruby-version: ${{ matrix.ruby }}
31
+ bundler-cache: true # 'bundle install' and cache
32
+ - name: Test
33
+ run: bundle exec rake
data/.gitignore CHANGED
@@ -1,17 +1,17 @@
1
- *.gem
2
- *.rbc
3
- .bundle
4
- .config
5
- .yardoc
6
- Gemfile.lock
7
- InstalledFiles
8
- _yardoc
9
- coverage
10
- doc/
11
- lib/bundler/man
12
- pkg
13
- rdoc
14
- spec/reports
15
- test/tmp
16
- test/version_tmp
17
- tmp
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile CHANGED
@@ -1,13 +1,13 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in request_store.gemspec
4
- gemspec
5
-
6
- case Gem::Version.new(RUBY_VERSION.dup)
7
- when ->(ruby_version) { ruby_version >= Gem::Version.new('2.2.0') }
8
- gem 'rake', '~> 13'
9
- when ->(ruby_version) { ruby_version >= Gem::Version.new('2.0.0') }
10
- gem 'rake', '~> 12.3.3'
11
- else
12
- gem 'rake', '~> 11'
13
- end
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in request_store.gemspec
4
+ gemspec
5
+
6
+ case Gem::Version.new(RUBY_VERSION.dup)
7
+ when ->(ruby_version) { ruby_version >= Gem::Version.new('2.2.0') }
8
+ gem 'rake', '~> 13'
9
+ when ->(ruby_version) { ruby_version >= Gem::Version.new('2.0.0') }
10
+ gem 'rake', '~> 12.3.3'
11
+ else
12
+ gem 'rake', '~> 11'
13
+ end
data/LICENSE.txt CHANGED
@@ -1,22 +1,22 @@
1
- Copyright (c) 2012 Steve Klabnik
2
-
3
- MIT License
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining
6
- a copy of this software and associated documentation files (the
7
- "Software"), to deal in the Software without restriction, including
8
- without limitation the rights to use, copy, modify, merge, publish,
9
- distribute, sublicense, and/or sell copies of the Software, and to
10
- permit persons to whom the Software is furnished to do so, subject to
11
- the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be
14
- included in all copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
1
+ Copyright (c) 2012 Steve Klabnik
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
22
  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,147 +1,147 @@
1
- # RequestStore [![CI](https://github.com/steveklabnik/request_store/actions/workflows/ci.yml/badge.svg)](https://github.com/steveklabnik/request_store/actions/workflows/ci.yml) [![Code Climate](https://codeclimate.com/github/steveklabnik/request_store.svg)](https://codeclimate.com/github/steveklabnik/request_store)
2
-
3
- Ever needed to use a global variable in Rails? Ugh, that's the worst. If you
4
- need global state, you've probably reached for `Thread.current`. Like this:
5
-
6
- ```ruby
7
- def self.foo
8
- Thread.current[:foo] ||= 0
9
- end
10
-
11
- def self.foo=(value)
12
- Thread.current[:foo] = value
13
- end
14
- ```
15
-
16
- Ugh! I hate it. But you gotta do what you gotta do...
17
-
18
- ### The problem
19
-
20
- Everyone's worrying about concurrency these days. So people are using those
21
- fancy threaded web servers, like Thin or Puma. But if you use `Thread.current`,
22
- and you use one of those servers, watch out! Values can stick around longer
23
- than you'd expect, and this can cause bugs. For example, if we had this in
24
- our controller:
25
-
26
- ```ruby
27
- def index
28
- Thread.current[:counter] ||= 0
29
- Thread.current[:counter] += 1
30
-
31
- render :text => Thread.current[:counter]
32
- end
33
- ```
34
-
35
- If we ran this on MRI with Webrick, you'd get `1` as output, every time. But if
36
- you run it with Thin, you get `1`, then `2`, then `3`...
37
-
38
- ### The solution
39
-
40
- Add this line to your application's Gemfile:
41
-
42
- ```ruby
43
- gem 'request_store'
44
- ```
45
-
46
- And change the code to this:
47
-
48
- ```ruby
49
- def index
50
- RequestStore.store[:foo] ||= 0
51
- RequestStore.store[:foo] += 1
52
-
53
- render :text => RequestStore.store[:foo]
54
- end
55
- ```
56
-
57
- Yep, everywhere you used `Thread.current` just change it to
58
- `RequestStore.store`. Now no matter what server you use, you'll get `1` every
59
- time: the storage is local to that request.
60
-
61
- ### API
62
-
63
- The `fetch` method returns the stored value if it already exists. If no stored value exists, it uses the provided block to add a new stored value.
64
-
65
- ```ruby
66
- top_posts = RequestStore.fetch(:top_posts) do
67
- # code to obtain the top posts
68
- end
69
- ```
70
-
71
- ### Rails 2 compatibility
72
-
73
- The gem includes a Railtie that will configure everything properly for Rails 3+
74
- apps, but if your app is tied to an older (2.x) version, you will have to
75
- manually add the middleware yourself. Typically this should just be a matter
76
- of adding:
77
-
78
- ```ruby
79
- config.middleware.use RequestStore::Middleware
80
- ```
81
-
82
- into your config/environment.rb.
83
-
84
- ### No Rails? No Problem!
85
-
86
- A Railtie is added that configures the Middleware for you, but if you're not
87
- using Rails, no biggie! Just use the Middleware yourself, however you need.
88
- You'll probably have to shove this somewhere:
89
-
90
- ```ruby
91
- use RequestStore::Middleware
92
- ```
93
-
94
- #### No Rails + Rack::Test
95
-
96
- In order to have `RequestStore` storage cleared between requests, add it to the
97
- `app`:
98
-
99
- ```ruby
100
- # spec_helper.rb
101
-
102
- def app
103
- Rack::Builder.new do
104
- use RequestStore::Middleware
105
- run MyApp
106
- end
107
- end
108
- ```
109
-
110
- ## Using with Sidekiq
111
-
112
- This gem uses a Rack middleware to clear the store object after every request,
113
- but that doesn't translate well to background processing with
114
- [Sidekiq](https://github.com/mperham/sidekiq).
115
-
116
- A companion library,
117
- [request_store-sidekiq](https://rubygems.org/gems/request_store-sidekiq)
118
- creates a Sidekiq middleware that will ensure the store is cleared after each
119
- job is processed, for security and consistency with how this is done in Rack.
120
-
121
- ## Semantic Versioning
122
-
123
- This project conforms to [semver](http://semver.org/). As a result of this
124
- policy, you can (and should) specify a dependency on this gem using the
125
- [Pessimistic Version Constraint](http://guides.rubygems.org/patterns/) with
126
- two digits of precision. For example:
127
-
128
- ```ruby
129
- spec.add_dependency 'request_store', '~> 1.0'
130
- ```
131
-
132
- This means your project is compatible with request_store 1.0 up until 2.0.
133
- You can also set a higher minimum version:
134
-
135
- ```ruby
136
- spec.add_dependency 'request_store', '~> 1.1'
137
- ```
138
-
139
- ## Contributing
140
-
141
- 1. Fork it
142
- 2. Create your feature branch (`git checkout -b my-new-feature`)
143
- 3. Commit your changes (`git commit -am 'Add some feature'`)
144
- 4. Push to the branch (`git push origin my-new-feature`)
145
- 5. Create new Pull Request
146
-
147
- Don't forget to run the tests with `rake`.
1
+ # RequestStore [![CI](https://github.com/steveklabnik/request_store/actions/workflows/ci.yml/badge.svg)](https://github.com/steveklabnik/request_store/actions/workflows/ci.yml) [![Code Climate](https://codeclimate.com/github/steveklabnik/request_store.svg)](https://codeclimate.com/github/steveklabnik/request_store)
2
+
3
+ Ever needed to use a global variable in Rails? Ugh, that's the worst. If you
4
+ need global state, you've probably reached for `Thread.current`. Like this:
5
+
6
+ ```ruby
7
+ def self.foo
8
+ Thread.current[:foo] ||= 0
9
+ end
10
+
11
+ def self.foo=(value)
12
+ Thread.current[:foo] = value
13
+ end
14
+ ```
15
+
16
+ Ugh! I hate it. But you gotta do what you gotta do...
17
+
18
+ ### The problem
19
+
20
+ Everyone's worrying about concurrency these days. So people are using those
21
+ fancy threaded web servers, like Thin or Puma. But if you use `Thread.current`,
22
+ and you use one of those servers, watch out! Values can stick around longer
23
+ than you'd expect, and this can cause bugs. For example, if we had this in
24
+ our controller:
25
+
26
+ ```ruby
27
+ def index
28
+ Thread.current[:counter] ||= 0
29
+ Thread.current[:counter] += 1
30
+
31
+ render :text => Thread.current[:counter]
32
+ end
33
+ ```
34
+
35
+ If we ran this on MRI with Webrick, you'd get `1` as output, every time. But if
36
+ you run it with Thin, you get `1`, then `2`, then `3`...
37
+
38
+ ### The solution
39
+
40
+ Add this line to your application's Gemfile:
41
+
42
+ ```ruby
43
+ gem 'request_store'
44
+ ```
45
+
46
+ And change the code to this:
47
+
48
+ ```ruby
49
+ def index
50
+ RequestStore.store[:foo] ||= 0
51
+ RequestStore.store[:foo] += 1
52
+
53
+ render :text => RequestStore.store[:foo]
54
+ end
55
+ ```
56
+
57
+ Yep, everywhere you used `Thread.current` just change it to
58
+ `RequestStore.store`. Now no matter what server you use, you'll get `1` every
59
+ time: the storage is local to that request.
60
+
61
+ ### API
62
+
63
+ The `fetch` method returns the stored value if it already exists. If no stored value exists, it uses the provided block to add a new stored value.
64
+
65
+ ```ruby
66
+ top_posts = RequestStore.fetch(:top_posts) do
67
+ # code to obtain the top posts
68
+ end
69
+ ```
70
+
71
+ ### Rails 2 compatibility
72
+
73
+ The gem includes a Railtie that will configure everything properly for Rails 3+
74
+ apps, but if your app is tied to an older (2.x) version, you will have to
75
+ manually add the middleware yourself. Typically this should just be a matter
76
+ of adding:
77
+
78
+ ```ruby
79
+ config.middleware.use RequestStore::Middleware
80
+ ```
81
+
82
+ into your config/environment.rb.
83
+
84
+ ### No Rails? No Problem!
85
+
86
+ A Railtie is added that configures the Middleware for you, but if you're not
87
+ using Rails, no biggie! Just use the Middleware yourself, however you need.
88
+ You'll probably have to shove this somewhere:
89
+
90
+ ```ruby
91
+ use RequestStore::Middleware
92
+ ```
93
+
94
+ #### No Rails + Rack::Test
95
+
96
+ In order to have `RequestStore` storage cleared between requests, add it to the
97
+ `app`:
98
+
99
+ ```ruby
100
+ # spec_helper.rb
101
+
102
+ def app
103
+ Rack::Builder.new do
104
+ use RequestStore::Middleware
105
+ run MyApp
106
+ end
107
+ end
108
+ ```
109
+
110
+ ## Using with Sidekiq
111
+
112
+ This gem uses a Rack middleware to clear the store object after every request,
113
+ but that doesn't translate well to background processing with
114
+ [Sidekiq](https://github.com/mperham/sidekiq).
115
+
116
+ A companion library,
117
+ [request_store-sidekiq](https://rubygems.org/gems/request_store-sidekiq)
118
+ creates a Sidekiq middleware that will ensure the store is cleared after each
119
+ job is processed, for security and consistency with how this is done in Rack.
120
+
121
+ ## Semantic Versioning
122
+
123
+ This project conforms to [semver](http://semver.org/). As a result of this
124
+ policy, you can (and should) specify a dependency on this gem using the
125
+ [Pessimistic Version Constraint](http://guides.rubygems.org/patterns/) with
126
+ two digits of precision. For example:
127
+
128
+ ```ruby
129
+ spec.add_dependency 'request_store', '~> 1.0'
130
+ ```
131
+
132
+ This means your project is compatible with request_store 1.0 up until 2.0.
133
+ You can also set a higher minimum version:
134
+
135
+ ```ruby
136
+ spec.add_dependency 'request_store', '~> 1.1'
137
+ ```
138
+
139
+ ## Contributing
140
+
141
+ 1. Fork it
142
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
143
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
144
+ 4. Push to the branch (`git push origin my-new-feature`)
145
+ 5. Create new Pull Request
146
+
147
+ Don't forget to run the tests with `rake`.
data/Rakefile CHANGED
@@ -1,12 +1,12 @@
1
- require "bundler/gem_tasks"
2
-
3
- require 'rake/testtask'
4
-
5
- Rake::TestTask.new do |t|
6
- t.libs << "lib"
7
- t.test_files = FileList['test/*_test.rb']
8
- t.ruby_opts = ['-r./test/test_helper.rb']
9
- t.verbose = true
10
- end
11
-
12
- task :default => :test
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rake/testtask'
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.libs << "lib"
7
+ t.test_files = FileList['test/*_test.rb']
8
+ t.ruby_opts = ['-r./test/test_helper.rb']
9
+ t.verbose = true
10
+ end
11
+
12
+ task :default => :test
@@ -1,36 +1,36 @@
1
- require 'rack/body_proxy'
2
-
3
- # A middleware that ensures the RequestStore stays around until
4
- # the last part of the body is rendered. This is useful when
5
- # using streaming.
6
- #
7
- # Uses Rack::BodyProxy, adapted from Rack::Lock's usage of the
8
- # same pattern.
9
-
10
- module RequestStore
11
- class Middleware
12
- def initialize(app)
13
- @app = app
14
- end
15
-
16
- def call(env)
17
- RequestStore.begin!
18
-
19
- status, headers, body = @app.call(env)
20
-
21
- body = Rack::BodyProxy.new(body) do
22
- RequestStore.end!
23
- RequestStore.clear!
24
- end
25
-
26
- returned = true
27
-
28
- [status, headers, body]
29
- ensure
30
- unless returned
31
- RequestStore.end!
32
- RequestStore.clear!
33
- end
34
- end
35
- end
36
- end
1
+ require 'rack/body_proxy'
2
+
3
+ # A middleware that ensures the RequestStore stays around until
4
+ # the last part of the body is rendered. This is useful when
5
+ # using streaming.
6
+ #
7
+ # Uses Rack::BodyProxy, adapted from Rack::Lock's usage of the
8
+ # same pattern.
9
+
10
+ module RequestStore
11
+ class Middleware
12
+ def initialize(app)
13
+ @app = app
14
+ end
15
+
16
+ def call(env)
17
+ RequestStore.begin!
18
+
19
+ status, headers, body = @app.call(env)
20
+
21
+ body = Rack::BodyProxy.new(body) do
22
+ RequestStore.end!
23
+ RequestStore.clear!
24
+ end
25
+
26
+ returned = true
27
+
28
+ [status, headers, body]
29
+ ensure
30
+ unless returned
31
+ RequestStore.end!
32
+ RequestStore.clear!
33
+ end
34
+ end
35
+ end
36
+ end
@@ -1,21 +1,21 @@
1
- module RequestStore
2
- class Railtie < ::Rails::Railtie
3
- initializer "request_store.insert_middleware" do |app|
4
- if ActionDispatch.const_defined? :RequestId
5
- app.config.middleware.insert_after ActionDispatch::RequestId, RequestStore::Middleware
6
- else
7
- app.config.middleware.insert_after Rack::MethodOverride, RequestStore::Middleware
8
- end
9
-
10
- if ActiveSupport.const_defined?(:Reloader) && ActiveSupport::Reloader.respond_to?(:to_complete)
11
- ActiveSupport::Reloader.to_complete do
12
- RequestStore.clear!
13
- end
14
- elsif ActionDispatch.const_defined?(:Reloader) && ActionDispatch::Reloader.respond_to?(:to_cleanup)
15
- ActionDispatch::Reloader.to_cleanup do
16
- RequestStore.clear!
17
- end
18
- end
19
- end
20
- end
21
- end
1
+ module RequestStore
2
+ class Railtie < ::Rails::Railtie
3
+ initializer "request_store.insert_middleware" do |app|
4
+ if ActionDispatch.const_defined? :RequestId
5
+ app.config.middleware.insert_after ActionDispatch::RequestId, RequestStore::Middleware
6
+ else
7
+ app.config.middleware.insert_after Rack::MethodOverride, RequestStore::Middleware
8
+ end
9
+
10
+ if ActiveSupport.const_defined?(:Reloader) && ActiveSupport::Reloader.respond_to?(:to_complete)
11
+ ActiveSupport::Reloader.to_complete do
12
+ RequestStore.clear!
13
+ end
14
+ elsif ActionDispatch.const_defined?(:Reloader) && ActionDispatch::Reloader.respond_to?(:to_cleanup)
15
+ ActionDispatch::Reloader.to_cleanup do
16
+ RequestStore.clear!
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,3 +1,3 @@
1
- module RequestStore
2
- VERSION = "1.6.0"
3
- end
1
+ module RequestStore
2
+ VERSION = "1.7.0"
3
+ end
data/lib/request_store.rb CHANGED
@@ -1,68 +1,58 @@
1
- require "request_store/version"
2
- require "request_store/middleware"
3
- require "request_store/railtie" if defined?(Rails::Railtie)
4
-
5
- module RequestStore
6
- if Fiber.respond_to?(:[])
7
- def self.scope
8
- Fiber
9
- end
10
- else
11
- def self.scope
12
- Thread.current
13
- end
14
- end
15
-
16
- def self.store
17
- scope[:request_store] ||= {}
18
- end
19
-
20
- def self.store=(store)
21
- scope[:request_store] = store
22
- end
23
-
24
- def self.clear!
25
- scope[:request_store] = {}
26
- end
27
-
28
- def self.begin!
29
- scope[:request_store_active] = true
30
- end
31
-
32
- def self.end!
33
- scope[:request_store_active] = false
34
- end
35
-
36
- def self.active?
37
- scope[:request_store_active] || false
38
- end
39
-
40
- def self.read(key)
41
- store[key]
42
- end
43
-
44
- def self.[](key)
45
- store[key]
46
- end
47
-
48
- def self.write(key, value)
49
- store[key] = value
50
- end
51
-
52
- def self.[]=(key, value)
53
- store[key] = value
54
- end
55
-
56
- def self.exist?(key)
57
- store.key?(key)
58
- end
59
-
60
- def self.fetch(key)
61
- store[key] = yield unless exist?(key)
62
- store[key]
63
- end
64
-
65
- def self.delete(key, &block)
66
- store.delete(key, &block)
67
- end
68
- end
1
+ require "request_store/version"
2
+ require "request_store/middleware"
3
+ require "request_store/railtie" if defined?(Rails::Railtie)
4
+
5
+ module RequestStore
6
+ def self.store
7
+ Thread.current[:request_store] ||= {}
8
+ end
9
+
10
+ def self.store=(store)
11
+ Thread.current[:request_store] = store
12
+ end
13
+
14
+ def self.clear!
15
+ Thread.current[:request_store] = {}
16
+ end
17
+
18
+ def self.begin!
19
+ Thread.current[:request_store_active] = true
20
+ end
21
+
22
+ def self.end!
23
+ Thread.current[:request_store_active] = false
24
+ end
25
+
26
+ def self.active?
27
+ Thread.current[:request_store_active] || false
28
+ end
29
+
30
+ def self.read(key)
31
+ store[key]
32
+ end
33
+
34
+ def self.[](key)
35
+ store[key]
36
+ end
37
+
38
+ def self.write(key, value)
39
+ store[key] = value
40
+ end
41
+
42
+ def self.[]=(key, value)
43
+ store[key] = value
44
+ end
45
+
46
+ def self.exist?(key)
47
+ store.key?(key)
48
+ end
49
+
50
+ def self.fetch(key)
51
+ store[key] = yield unless exist?(key)
52
+ store[key]
53
+ end
54
+
55
+ def self.delete(key, &block)
56
+ store.delete(key, &block)
57
+ end
58
+ end
@@ -1,24 +1,24 @@
1
- # -*- encoding: utf-8 -*-
2
- lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'request_store/version'
5
-
6
- Gem::Specification.new do |gem|
7
- gem.name = "request_store"
8
- gem.version = RequestStore::VERSION
9
- gem.authors = ["Steve Klabnik"]
10
- gem.email = ["steve@steveklabnik.com"]
11
- gem.description = %q{RequestStore gives you per-request global storage.}
12
- gem.summary = %q{RequestStore gives you per-request global storage.}
13
- gem.homepage = "https://github.com/steveklabnik/request_store"
14
- gem.licenses = ["MIT"]
15
-
16
- gem.files = `git ls-files`.split($/)
17
- gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
- gem.require_paths = ["lib"]
19
-
20
- gem.add_dependency "rack", ">= 1.4"
21
-
22
- gem.add_development_dependency "rake"
23
- gem.add_development_dependency "minitest", "~> 5.0"
24
- end
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'request_store/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "request_store"
8
+ gem.version = RequestStore::VERSION
9
+ gem.authors = ["Steve Klabnik"]
10
+ gem.email = ["steve@steveklabnik.com"]
11
+ gem.description = %q{RequestStore gives you per-request global storage.}
12
+ gem.summary = %q{RequestStore gives you per-request global storage.}
13
+ gem.homepage = "https://github.com/steveklabnik/request_store"
14
+ gem.licenses = ["MIT"]
15
+
16
+ gem.files = `git ls-files`.split($/)
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_dependency "rack", ">= 1.4"
21
+
22
+ gem.add_development_dependency "rake"
23
+ gem.add_development_dependency "minitest", "~> 5.0"
24
+ end
@@ -1,101 +1,101 @@
1
- require 'minitest/test'
2
- require 'minitest/autorun'
3
-
4
- require 'request_store'
5
-
6
- class MiddlewareTest < Minitest::Test
7
- def setup
8
- @app = RackApp.new
9
- @middleware = RequestStore::Middleware.new(@app)
10
- end
11
-
12
- def call_middleware(opts = {})
13
- _, _, proxy = @middleware.call(opts)
14
- proxy.close
15
- proxy
16
- end
17
-
18
- def test_middleware_resets_store
19
- 2.times do
20
- call_middleware
21
- end
22
-
23
- assert_equal 1, @app.last_value
24
- assert_equal({}, RequestStore.store)
25
- end
26
-
27
- def test_middleware_does_not_mutate_response_and_does_not_overflow_stack
28
- 10000.times do
29
- call_middleware
30
- end
31
-
32
- resp = call_middleware
33
- assert resp.is_a?(::Rack::BodyProxy)
34
- assert_equal ["response"], resp.to_a
35
- assert_equal ["response"], resp.instance_variable_get(:@body)
36
- end
37
-
38
- def test_middleware_resets_store_on_error
39
- e = assert_raises RuntimeError do
40
- call_middleware({:error => true})
41
- end
42
-
43
- assert_equal 'FAIL', e.message
44
- assert_equal({}, RequestStore.store)
45
- end
46
-
47
- def test_middleware_begins_store
48
- call_middleware
49
- assert_equal true, @app.store_active
50
- end
51
-
52
- def test_middleware_ends_store
53
- call_middleware
54
-
55
- assert_equal false, RequestStore.active?
56
- end
57
-
58
- def test_middleware_ends_store_on_error
59
- assert_raises RuntimeError do
60
- call_middleware({:error => true})
61
- end
62
-
63
- assert_equal false, RequestStore.active?
64
- end
65
-
66
- def test_middleware_stores_until_proxy_closes
67
- _, _, proxy = @middleware.call({})
68
-
69
- assert_equal 1, @app.last_value
70
- assert RequestStore.active?
71
-
72
- proxy.close
73
-
74
- refute RequestStore.active?
75
- refute RequestStore.store[:foo]
76
- end
77
- end
78
-
79
- class MiddlewareWithConstResponseTest < Minitest::Test
80
- def setup
81
- @app = RackAppWithConstResponse.new
82
- @middleware = RequestStore::Middleware.new(@app)
83
- end
84
-
85
- def call_middleware(opts = {})
86
- _, _, proxy = @middleware.call(opts)
87
- proxy.close
88
- proxy
89
- end
90
-
91
- def test_middleware_does_not_mutate_response_and_does_not_overflow_stack
92
- 10000.times do
93
- call_middleware
94
- end
95
-
96
- resp = call_middleware
97
- assert resp.is_a?(::Rack::BodyProxy)
98
- assert_equal ["response"], resp.to_a
99
- assert_equal ["response"], resp.instance_variable_get(:@body)
100
- end
101
- end
1
+ require 'minitest/test'
2
+ require 'minitest/autorun'
3
+
4
+ require 'request_store'
5
+
6
+ class MiddlewareTest < Minitest::Test
7
+ def setup
8
+ @app = RackApp.new
9
+ @middleware = RequestStore::Middleware.new(@app)
10
+ end
11
+
12
+ def call_middleware(opts = {})
13
+ _, _, proxy = @middleware.call(opts)
14
+ proxy.close
15
+ proxy
16
+ end
17
+
18
+ def test_middleware_resets_store
19
+ 2.times do
20
+ call_middleware
21
+ end
22
+
23
+ assert_equal 1, @app.last_value
24
+ assert_equal({}, RequestStore.store)
25
+ end
26
+
27
+ def test_middleware_does_not_mutate_response_and_does_not_overflow_stack
28
+ 10000.times do
29
+ call_middleware
30
+ end
31
+
32
+ resp = call_middleware
33
+ assert resp.is_a?(::Rack::BodyProxy)
34
+ assert_equal ["response"], resp.to_a
35
+ assert_equal ["response"], resp.instance_variable_get(:@body)
36
+ end
37
+
38
+ def test_middleware_resets_store_on_error
39
+ e = assert_raises RuntimeError do
40
+ call_middleware({:error => true})
41
+ end
42
+
43
+ assert_equal 'FAIL', e.message
44
+ assert_equal({}, RequestStore.store)
45
+ end
46
+
47
+ def test_middleware_begins_store
48
+ call_middleware
49
+ assert_equal true, @app.store_active
50
+ end
51
+
52
+ def test_middleware_ends_store
53
+ call_middleware
54
+
55
+ assert_equal false, RequestStore.active?
56
+ end
57
+
58
+ def test_middleware_ends_store_on_error
59
+ assert_raises RuntimeError do
60
+ call_middleware({:error => true})
61
+ end
62
+
63
+ assert_equal false, RequestStore.active?
64
+ end
65
+
66
+ def test_middleware_stores_until_proxy_closes
67
+ _, _, proxy = @middleware.call({})
68
+
69
+ assert_equal 1, @app.last_value
70
+ assert RequestStore.active?
71
+
72
+ proxy.close
73
+
74
+ refute RequestStore.active?
75
+ refute RequestStore.store[:foo]
76
+ end
77
+ end
78
+
79
+ class MiddlewareWithConstResponseTest < Minitest::Test
80
+ def setup
81
+ @app = RackAppWithConstResponse.new
82
+ @middleware = RequestStore::Middleware.new(@app)
83
+ end
84
+
85
+ def call_middleware(opts = {})
86
+ _, _, proxy = @middleware.call(opts)
87
+ proxy.close
88
+ proxy
89
+ end
90
+
91
+ def test_middleware_does_not_mutate_response_and_does_not_overflow_stack
92
+ 10000.times do
93
+ call_middleware
94
+ end
95
+
96
+ resp = call_middleware
97
+ assert resp.is_a?(::Rack::BodyProxy)
98
+ assert_equal ["response"], resp.to_a
99
+ assert_equal ["response"], resp.instance_variable_get(:@body)
100
+ end
101
+ end
@@ -1,80 +1,80 @@
1
- require 'minitest/autorun'
2
-
3
- require 'request_store'
4
-
5
- class RequestStoreTest < Minitest::Test
6
- def setup
7
- RequestStore.clear!
8
- end
9
-
10
- def teardown
11
- RequestStore.clear!
12
- end
13
-
14
- def test_initial_state
15
- Thread.current[:request_store] = nil
16
- assert_equal RequestStore.store, Hash.new
17
- end
18
-
19
- def test_init_with_hash
20
- assert_equal Hash.new, RequestStore.store
21
- end
22
-
23
- def test_assign_store
24
- store_obj = { test_key: 'test' }
25
- RequestStore.store = store_obj
26
- assert_equal 'test', RequestStore.store[:test_key]
27
- assert_equal store_obj, RequestStore.store
28
- end
29
-
30
- def test_clear
31
- RequestStore.store[:foo] = 1
32
- RequestStore.clear!
33
- assert_equal Hash.new, RequestStore.store
34
- end
35
-
36
- def test_quacks_like_hash
37
- RequestStore.store[:foo] = 1
38
- assert_equal 1, RequestStore.store[:foo]
39
- assert_equal 1, RequestStore.store.fetch(:foo)
40
- end
41
-
42
- def test_read
43
- RequestStore.store[:foo] = 1
44
- assert_equal 1, RequestStore.read(:foo)
45
- assert_equal 1, RequestStore[:foo]
46
- end
47
-
48
- def test_write
49
- RequestStore.write(:foo, 1)
50
- assert_equal 1, RequestStore.store[:foo]
51
- RequestStore[:foo] = 2
52
- assert_equal 2, RequestStore.store[:foo]
53
- end
54
-
55
- def test_fetch
56
- assert_equal 2, RequestStore.fetch(:foo) { 1 + 1 }
57
- assert_equal 2, RequestStore.fetch(:foo) { 2 + 2 }
58
- end
59
-
60
- def test_delete
61
- assert_equal 2, RequestStore.fetch(:foo) { 1 + 1 }
62
- assert_equal 2, RequestStore.delete(:foo) { 2 + 2 }
63
- assert_equal 4, RequestStore.delete(:foo) { 2 + 2 }
64
- end
65
-
66
- def test_delegates_to_scope
67
- RequestStore.store[:foo] = 1
68
- assert_equal 1, RequestStore.scope[:request_store][:foo]
69
- end
70
-
71
- def test_active_state
72
- assert_equal false, RequestStore.active?
73
-
74
- RequestStore.begin!
75
- assert_equal true, RequestStore.active?
76
-
77
- RequestStore.end!
78
- assert_equal false, RequestStore.active?
79
- end
80
- end
1
+ require 'minitest/autorun'
2
+
3
+ require 'request_store'
4
+
5
+ class RequestStoreTest < Minitest::Test
6
+ def setup
7
+ RequestStore.clear!
8
+ end
9
+
10
+ def teardown
11
+ RequestStore.clear!
12
+ end
13
+
14
+ def test_initial_state
15
+ Thread.current[:request_store] = nil
16
+ assert_equal RequestStore.store, Hash.new
17
+ end
18
+
19
+ def test_init_with_hash
20
+ assert_equal Hash.new, RequestStore.store
21
+ end
22
+
23
+ def test_assign_store
24
+ store_obj = { test_key: 'test' }
25
+ RequestStore.store = store_obj
26
+ assert_equal 'test', RequestStore.store[:test_key]
27
+ assert_equal store_obj, RequestStore.store
28
+ end
29
+
30
+ def test_clear
31
+ RequestStore.store[:foo] = 1
32
+ RequestStore.clear!
33
+ assert_equal Hash.new, RequestStore.store
34
+ end
35
+
36
+ def test_quacks_like_hash
37
+ RequestStore.store[:foo] = 1
38
+ assert_equal 1, RequestStore.store[:foo]
39
+ assert_equal 1, RequestStore.store.fetch(:foo)
40
+ end
41
+
42
+ def test_read
43
+ RequestStore.store[:foo] = 1
44
+ assert_equal 1, RequestStore.read(:foo)
45
+ assert_equal 1, RequestStore[:foo]
46
+ end
47
+
48
+ def test_write
49
+ RequestStore.write(:foo, 1)
50
+ assert_equal 1, RequestStore.store[:foo]
51
+ RequestStore[:foo] = 2
52
+ assert_equal 2, RequestStore.store[:foo]
53
+ end
54
+
55
+ def test_fetch
56
+ assert_equal 2, RequestStore.fetch(:foo) { 1 + 1 }
57
+ assert_equal 2, RequestStore.fetch(:foo) { 2 + 2 }
58
+ end
59
+
60
+ def test_delete
61
+ assert_equal 2, RequestStore.fetch(:foo) { 1 + 1 }
62
+ assert_equal 2, RequestStore.delete(:foo) { 2 + 2 }
63
+ assert_equal 4, RequestStore.delete(:foo) { 2 + 2 }
64
+ end
65
+
66
+ def test_delegates_to_thread
67
+ RequestStore.store[:foo] = 1
68
+ assert_equal 1, Thread.current[:request_store][:foo]
69
+ end
70
+
71
+ def test_active_state
72
+ assert_equal false, RequestStore.active?
73
+
74
+ RequestStore.begin!
75
+ assert_equal true, RequestStore.active?
76
+
77
+ RequestStore.end!
78
+ assert_equal false, RequestStore.active?
79
+ end
80
+ end
data/test/test_helper.rb CHANGED
@@ -1,29 +1,29 @@
1
- class RackApp
2
- attr_reader :last_value, :store_active
3
-
4
- def call(env)
5
- RequestStore.store[:foo] ||= 0
6
- RequestStore.store[:foo] += 1
7
- @last_value = RequestStore.store[:foo]
8
- @store_active = RequestStore.active?
9
- raise 'FAIL' if env[:error]
10
-
11
- [200, {}, ["response"]]
12
- end
13
- end
14
-
15
- class RackAppWithConstResponse
16
- RESPONSE = [200, {}, ["response"]]
17
-
18
- attr_reader :last_value, :store_active
19
-
20
- def call(env)
21
- RequestStore.store[:foo] ||= 0
22
- RequestStore.store[:foo] += 1
23
- @last_value = RequestStore.store[:foo]
24
- @store_active = RequestStore.active?
25
- raise 'FAIL' if env[:error]
26
-
27
- RESPONSE
28
- end
29
- end
1
+ class RackApp
2
+ attr_reader :last_value, :store_active
3
+
4
+ def call(env)
5
+ RequestStore.store[:foo] ||= 0
6
+ RequestStore.store[:foo] += 1
7
+ @last_value = RequestStore.store[:foo]
8
+ @store_active = RequestStore.active?
9
+ raise 'FAIL' if env[:error]
10
+
11
+ [200, {}, ["response"]]
12
+ end
13
+ end
14
+
15
+ class RackAppWithConstResponse
16
+ RESPONSE = [200, {}, ["response"]]
17
+
18
+ attr_reader :last_value, :store_active
19
+
20
+ def call(env)
21
+ RequestStore.store[:foo] ||= 0
22
+ RequestStore.store[:foo] += 1
23
+ @last_value = RequestStore.store[:foo]
24
+ @store_active = RequestStore.active?
25
+ raise 'FAIL' if env[:error]
26
+
27
+ RESPONSE
28
+ end
29
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: request_store
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.0
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steve Klabnik
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-02-08 00:00:00.000000000 Z
11
+ date: 2024-05-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -77,7 +77,7 @@ homepage: https://github.com/steveklabnik/request_store
77
77
  licenses:
78
78
  - MIT
79
79
  metadata: {}
80
- post_install_message:
80
+ post_install_message:
81
81
  rdoc_options: []
82
82
  require_paths:
83
83
  - lib
@@ -92,8 +92,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
92
92
  - !ruby/object:Gem::Version
93
93
  version: '0'
94
94
  requirements: []
95
- rubygems_version: 3.2.15
96
- signing_key:
95
+ rubygems_version: 3.3.5
96
+ signing_key:
97
97
  specification_version: 4
98
98
  summary: RequestStore gives you per-request global storage.
99
99
  test_files: