request_store 1.1.0 → 1.5.1

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
- SHA1:
3
- metadata.gz: f85cc719e97b2fd7d14f66225abf332e8f6a1248
4
- data.tar.gz: 8b850f88cdaff14f6150e8799a931d85935402e6
2
+ SHA256:
3
+ metadata.gz: a8829219a616f7288e08e65fe5d39d491b1693cb31ca5632355a4a4216167a21
4
+ data.tar.gz: 1f151729fdffa5b98422b359ab3f145caf8a19943bb075f0b5d2b13999b318b3
5
5
  SHA512:
6
- metadata.gz: 6628a9dbf581592b306082f4782d44c0577b34eea89dbe3d231ece2b069a7b8b5b51dc9a6993df058dd989aeeda2a26e7dc35f5d7ca0f8353cbc1a918502322f
7
- data.tar.gz: d18615c3d9a6cd02bea10a119b549690d15cf87fbb0e9b3d62947ce7d004e55952124f5f7172a404b976bdaa7e2659ba135fca6ecc92563084d3edc3451d39df
6
+ metadata.gz: bc75042c21655c31f3392520e49a7bc816a157a5ac60ba783b73436d5293b88379ac08c0dc94ba352b7f4819c6d48cebccd60315a930a1d600c2a65148f14ae8
7
+ data.tar.gz: d70cb3dbb0868d4311cdb1ff6b710c9bab96c698acdd0d6d4c409ea133dafe119a43bd9d1eee41eea819350e5187aa4338fb4fda3d69613d6a128f9cbd86c7ea
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/.travis.yml CHANGED
@@ -1,17 +1,18 @@
1
- language: ruby
2
- rvm:
3
- - 1.8.7
4
- - 1.9.2
5
- - 1.9.3
6
- - 2.0.0
7
- - 2.1.0
8
- - jruby-18mode
9
- - jruby-19mode
10
- - rbx-2
11
- - ruby-head
12
- - jruby-head
13
- - ree
14
- matrix:
15
- allow_failures:
16
- - rvm: ruby-head
17
- - rvm: jruby-head
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - 2.1.0
6
+ - 2.2.3
7
+ - 2.4.9
8
+ - 2.5.7
9
+ - 2.6.5
10
+ - jruby-18mode
11
+ - jruby-19mode
12
+ - ruby-head
13
+ - jruby-head
14
+ - truffleruby-head
15
+ matrix:
16
+ allow_failures:
17
+ - rvm: ruby-head
18
+ - rvm: jruby-head
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in request_store.gemspec
4
- gemspec
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in request_store.gemspec
4
+ gemspec
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,92 +1,147 @@
1
- # RequestStore [![build status](https://travis-ci.org/steveklabnik/request_store.png?branch=master)](https://travis-ci.org/steveklabnik/request_store) [![Code Climate](https://codeclimate.com/github/steveklabnik/request_store.png)](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
- ### Rails 2 compatibility
62
-
63
- The gem includes a Railtie that will configure everything properly for Rails 3+
64
- apps, but if your app is tied to an older (2.x) version, you will have to
65
- manually add the middleware yourself. Typically this should just be a matter
66
- of adding:
67
-
68
- ```ruby
69
- config.middleware.use RequestStore::Middleware
70
- ```
71
-
72
- into your config/environment.rb.
73
-
74
- ### No Rails? No Problem!
75
-
76
- A Railtie is added that configures the Middleware for you, but if you're not
77
- using Rails, no biggie! Just use the Middleware yourself, however you need.
78
- You'll probably have to shove this somewhere:
79
-
80
- ```ruby
81
- use RequestStore::Middleware
82
- ```
83
-
84
- ## Contributing
85
-
86
- 1. Fork it
87
- 2. Create your feature branch (`git checkout -b my-new-feature`)
88
- 3. Commit your changes (`git commit -am 'Add some feature'`)
89
- 4. Push to the branch (`git push origin my-new-feature`)
90
- 5. Create new Pull Request
91
-
92
- Don't forget to run the tests with `rake`.
1
+ # RequestStore [![build status](https://travis-ci.org/steveklabnik/request_store.svg?branch=master)](https://travis-ci.org/steveklabnik/request_store) [![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,13 +1,36 @@
1
- module RequestStore
2
- class Middleware
3
- def initialize(app)
4
- @app = app
5
- end
6
-
7
- def call(env)
8
- @app.call(env)
9
- ensure
10
- RequestStore.clear!
11
- end
12
- end
13
- 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,11 +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
- end
10
- end
11
- 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.1.0"
3
- end
1
+ module RequestStore
2
+ VERSION = "1.5.1"
3
+ end
data/lib/request_store.rb CHANGED
@@ -1,42 +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
- def self.store
7
- Thread.current[:request_store] ||= {}
8
- end
9
-
10
- def self.clear!
11
- Thread.current[:request_store] = {}
12
- end
13
-
14
- def self.read(key)
15
- store[key]
16
- end
17
-
18
- def self.[](key)
19
- store[key]
20
- end
21
-
22
- def self.write(key, value)
23
- store[key] = value
24
- end
25
-
26
- def self.[]=(key, value)
27
- store[key] = value
28
- end
29
-
30
- def self.exist?(key)
31
- store.key?(key)
32
- end
33
-
34
- def self.fetch(key, &block)
35
- store[key] = yield unless exist?(key)
36
- store[key]
37
- end
38
-
39
- def self.delete(key, &block)
40
- store.delete(key, &block)
41
- end
42
- 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,22 +1,25 @@
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 = "http://github.com/steveklabnik/request_store"
14
-
15
- gem.files = `git ls-files`.split($/)
16
- gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
- gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
- gem.require_paths = ["lib"]
19
-
20
- gem.add_development_dependency "rake"
21
- gem.add_development_dependency 'minitest', '~> 3.0'
22
- 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.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
18
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
+ gem.require_paths = ["lib"]
20
+
21
+ gem.add_dependency "rack", ">= 1.4"
22
+
23
+ gem.add_development_dependency "rake", "~> 10.5"
24
+ gem.add_development_dependency "minitest", "~> 5.0"
25
+ end
@@ -1,29 +1,101 @@
1
- require 'minitest/autorun'
2
-
3
- require 'request_store'
4
-
5
- class MiddlewareTest < Minitest::Unit::TestCase
6
- def setup
7
- @app = RackApp.new
8
- @middleware = RequestStore::Middleware.new(@app)
9
- end
10
-
11
- def test_middleware_resets_store
12
- 2.times { @middleware.call({}) }
13
-
14
- assert_equal 1, @app.last_value
15
- assert_equal({}, RequestStore.store)
16
- end
17
-
18
- def test_middleware_resets_store_on_error
19
- errors = []
20
- begin
21
- @middleware.call({:error => true})
22
- rescue => e
23
- errors << e
24
- end
25
-
26
- assert_equal ['FAIL'], errors.map(&:message)
27
- assert_equal({}, RequestStore.store)
28
- end
29
- 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,63 +1,80 @@
1
- require 'minitest/autorun'
2
-
3
- require 'request_store'
4
-
5
- class RequestStoreTest < Minitest::Unit::TestCase
6
- def test_initial_state
7
- Thread.current[:request_store] = nil
8
- assert_equal RequestStore.store, Hash.new
9
- end
10
-
11
- def test_init_with_hash
12
- RequestStore.clear!
13
- assert_equal Hash.new, RequestStore.store
14
- end
15
-
16
- def test_clear
17
- RequestStore.clear!
18
- RequestStore.store[:foo] = 1
19
- RequestStore.clear!
20
- assert_equal Hash.new, RequestStore.store
21
- end
22
-
23
- def test_quacks_like_hash
24
- RequestStore.clear!
25
- RequestStore.store[:foo] = 1
26
- assert_equal 1, RequestStore.store[:foo]
27
- assert_equal 1, RequestStore.store.fetch(:foo)
28
- end
29
-
30
- def test_read
31
- RequestStore.clear!
32
- RequestStore.store[:foo] = 1
33
- assert_equal 1, RequestStore.read(:foo)
34
- assert_equal 1, RequestStore[:foo]
35
- end
36
-
37
- def test_write
38
- RequestStore.clear!
39
- RequestStore.write(:foo, 1)
40
- assert_equal 1, RequestStore.store[:foo]
41
- RequestStore[:foo] = 2
42
- assert_equal 2, RequestStore.store[:foo]
43
- end
44
-
45
- def test_fetch
46
- RequestStore.clear!
47
- assert_equal 2, RequestStore.fetch(:foo) { 1 + 1 }
48
- assert_equal 2, RequestStore.fetch(:foo) { 2 + 2 }
49
- end
50
-
51
- def test_delete
52
- RequestStore.clear!
53
- assert_equal 2, RequestStore.fetch(:foo) { 1 + 1 }
54
- assert_equal 2, RequestStore.delete(:foo) { 2 + 2 }
55
- assert_equal 4, RequestStore.delete(:foo) { 2 + 2 }
56
- end
57
-
58
- def test_delegates_to_thread
59
- RequestStore.clear!
60
- RequestStore.store[:foo] = 1
61
- assert_equal 1, Thread.current[:request_store][:foo]
62
- end
63
- 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,10 +1,29 @@
1
- class RackApp
2
- attr_reader :last_value
3
-
4
- def call(env)
5
- RequestStore.store[:foo] ||= 0
6
- RequestStore.store[:foo] += 1
7
- @last_value = RequestStore.store[:foo]
8
- raise 'FAIL' if env[:error]
9
- end
10
- 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,43 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: request_store
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.5.1
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: 2014-08-15 00:00:00.000000000 Z
11
+ date: 2022-01-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: rake
14
+ name: rack
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :development
19
+ version: '1.4'
20
+ type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: '1.4'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.5'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.5'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: minitest
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
45
  - - "~>"
32
46
  - !ruby/object:Gem::Version
33
- version: '3.0'
47
+ version: '5.0'
34
48
  type: :development
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
52
  - - "~>"
39
53
  - !ruby/object:Gem::Version
40
- version: '3.0'
54
+ version: '5.0'
41
55
  description: RequestStore gives you per-request global storage.
42
56
  email:
43
57
  - steve@steveklabnik.com
@@ -59,10 +73,11 @@ files:
59
73
  - test/middleware_test.rb
60
74
  - test/request_store_test.rb
61
75
  - test/test_helper.rb
62
- homepage: http://github.com/steveklabnik/request_store
63
- licenses: []
76
+ homepage: https://github.com/steveklabnik/request_store
77
+ licenses:
78
+ - MIT
64
79
  metadata: {}
65
- post_install_message:
80
+ post_install_message:
66
81
  rdoc_options: []
67
82
  require_paths:
68
83
  - lib
@@ -77,9 +92,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
77
92
  - !ruby/object:Gem::Version
78
93
  version: '0'
79
94
  requirements: []
80
- rubyforge_project:
81
- rubygems_version: 2.2.2
82
- signing_key:
95
+ rubygems_version: 3.2.15
96
+ signing_key:
83
97
  specification_version: 4
84
98
  summary: RequestStore gives you per-request global storage.
85
99
  test_files: