request_store 1.6.0 → 1.7.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: 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: