request_store-1.3.0/0000755000004100000410000000000012654142213014447 5ustar www-datawww-datarequest_store-1.3.0/Rakefile0000644000004100000410000000035112654142213016113 0ustar www-datawww-datarequire "bundler/gem_tasks" require 'rake/testtask' Rake::TestTask.new do |t| t.libs << "lib" t.test_files = FileList['test/*_test.rb'] t.ruby_opts = ['-r./test/test_helper.rb'] t.verbose = true end task :default => :test request_store-1.3.0/Gemfile0000644000004100000410000000014212654142213015737 0ustar www-datawww-datasource 'https://rubygems.org' # Specify your gem's dependencies in request_store.gemspec gemspec request_store-1.3.0/LICENSE.txt0000644000004100000410000000205512654142213016274 0ustar www-datawww-dataCopyright (c) 2012 Steve Klabnik MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.request_store-1.3.0/.travis.yml0000644000004100000410000000036212654142213016561 0ustar www-datawww-datalanguage: ruby sudo: false rvm: - 1.8.7 - 1.9.2 - 1.9.3 - 2.0.0 - 2.1.0 - 2.2.3 - jruby-18mode - jruby-19mode - rbx-2 - ruby-head - jruby-head - ree matrix: allow_failures: - rvm: ruby-head - rvm: jruby-head request_store-1.3.0/lib/0000755000004100000410000000000012654142213015215 5ustar www-datawww-datarequest_store-1.3.0/lib/request_store/0000755000004100000410000000000012654142213020121 5ustar www-datawww-datarequest_store-1.3.0/lib/request_store/version.rb0000644000004100000410000000005412654142213022132 0ustar www-datawww-datamodule RequestStore VERSION = "1.3.0" end request_store-1.3.0/lib/request_store/middleware.rb0000644000004100000410000000035112654142213022562 0ustar www-datawww-datamodule RequestStore class Middleware def initialize(app) @app = app end def call(env) RequestStore.begin! @app.call(env) ensure RequestStore.end! RequestStore.clear! end end end request_store-1.3.0/lib/request_store/railtie.rb0000644000004100000410000000111712654142213022077 0ustar www-datawww-datamodule RequestStore class Railtie < ::Rails::Railtie initializer "request_store.insert_middleware" do |app| if ActionDispatch.const_defined? :RequestId app.config.middleware.insert_after ActionDispatch::RequestId, RequestStore::Middleware else app.config.middleware.insert_after Rack::MethodOverride, RequestStore::Middleware end if ActionDispatch.const_defined?(:Reloader) && ActionDispatch::Reloader.respond_to?(:to_cleanup) ActionDispatch::Reloader.to_cleanup do RequestStore.clear! end end end end end request_store-1.3.0/lib/request_store.rb0000644000004100000410000000162612654142213020453 0ustar www-datawww-datarequire "request_store/version" require "request_store/middleware" require "request_store/railtie" if defined?(Rails::Railtie) module RequestStore def self.store Thread.current[:request_store] ||= {} end def self.clear! Thread.current[:request_store] = {} end def self.begin! Thread.current[:request_store_active] = true end def self.end! Thread.current[:request_store_active] = false end def self.active? Thread.current[:request_store_active] || false end def self.read(key) store[key] end def self.[](key) store[key] end def self.write(key, value) store[key] = value end def self.[]=(key, value) store[key] = value end def self.exist?(key) store.key?(key) end def self.fetch(key, &block) store[key] = yield unless exist?(key) store[key] end def self.delete(key, &block) store.delete(key, &block) end end request_store-1.3.0/metadata.yml0000644000004100000410000000402512654142213016753 0ustar www-datawww-data--- !ruby/object:Gem::Specification name: request_store version: !ruby/object:Gem::Version version: 1.3.0 platform: ruby authors: - Steve Klabnik autorequire: bindir: bin cert_chain: [] date: 2016-01-08 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency name: rake requirement: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: minitest requirement: !ruby/object:Gem::Requirement requirements: - - ~> - !ruby/object:Gem::Version version: '5.0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - ~> - !ruby/object:Gem::Version version: '5.0' description: RequestStore gives you per-request global storage. email: - steve@steveklabnik.com executables: [] extensions: [] extra_rdoc_files: [] files: - .gitignore - .travis.yml - Gemfile - LICENSE.txt - README.md - Rakefile - lib/request_store.rb - lib/request_store/middleware.rb - lib/request_store/railtie.rb - lib/request_store/version.rb - request_store.gemspec - test/middleware_test.rb - test/request_store_test.rb - test/test_helper.rb homepage: http://github.com/steveklabnik/request_store licenses: - MIT metadata: {} post_install_message: rdoc_options: [] require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' required_rubygems_version: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' requirements: [] rubyforge_project: rubygems_version: 2.0.14.1 signing_key: specification_version: 4 summary: RequestStore gives you per-request global storage. test_files: - test/middleware_test.rb - test/request_store_test.rb - test/test_helper.rb request_store-1.3.0/test/0000755000004100000410000000000012654142213015426 5ustar www-datawww-datarequest_store-1.3.0/test/request_store_test.rb0000644000004100000410000000310712654142213021717 0ustar www-datawww-datarequire 'minitest/autorun' require 'request_store' class RequestStoreTest < Minitest::Test def setup RequestStore.clear! end def test_initial_state Thread.current[:request_store] = nil assert_equal RequestStore.store, Hash.new end def test_init_with_hash assert_equal Hash.new, RequestStore.store end def test_clear RequestStore.store[:foo] = 1 RequestStore.clear! assert_equal Hash.new, RequestStore.store end def test_quacks_like_hash RequestStore.store[:foo] = 1 assert_equal 1, RequestStore.store[:foo] assert_equal 1, RequestStore.store.fetch(:foo) end def test_read RequestStore.store[:foo] = 1 assert_equal 1, RequestStore.read(:foo) assert_equal 1, RequestStore[:foo] end def test_write RequestStore.write(:foo, 1) assert_equal 1, RequestStore.store[:foo] RequestStore[:foo] = 2 assert_equal 2, RequestStore.store[:foo] end def test_fetch assert_equal 2, RequestStore.fetch(:foo) { 1 + 1 } assert_equal 2, RequestStore.fetch(:foo) { 2 + 2 } end def test_delete assert_equal 2, RequestStore.fetch(:foo) { 1 + 1 } assert_equal 2, RequestStore.delete(:foo) { 2 + 2 } assert_equal 4, RequestStore.delete(:foo) { 2 + 2 } end def test_delegates_to_thread RequestStore.store[:foo] = 1 assert_equal 1, Thread.current[:request_store][:foo] end def test_active_state assert_equal false, RequestStore.active? RequestStore.begin! assert_equal true, RequestStore.active? RequestStore.end! assert_equal false, RequestStore.active? end end request_store-1.3.0/test/middleware_test.rb0000644000004100000410000000172512654142213021134 0ustar www-datawww-datarequire 'minitest/test' require 'minitest/autorun' require 'request_store' class MiddlewareTest < Minitest::Test def setup @app = RackApp.new @middleware = RequestStore::Middleware.new(@app) end def test_middleware_resets_store 2.times { @middleware.call({}) } assert_equal 1, @app.last_value assert_equal({}, RequestStore.store) end def test_middleware_resets_store_on_error e = assert_raises RuntimeError do @middleware.call({:error => true}) end assert_equal 'FAIL', e.message assert_equal({}, RequestStore.store) end def test_middleware_begins_store @middleware.call({}) assert_equal true, @app.store_active end def test_middleware_ends_store @middleware.call({}) assert_equal false, RequestStore.active? end def test_middleware_ends_store_on_error assert_raises RuntimeError do @middleware.call({:error => true}) end assert_equal false, RequestStore.active? end end request_store-1.3.0/test/test_helper.rb0000644000004100000410000000041312654142213020267 0ustar www-datawww-dataclass RackApp attr_reader :last_value, :store_active def call(env) RequestStore.store[:foo] ||= 0 RequestStore.store[:foo] += 1 @last_value = RequestStore.store[:foo] @store_active = RequestStore.active? raise 'FAIL' if env[:error] end end request_store-1.3.0/.gitignore0000644000004100000410000000023212654142213016434 0ustar www-datawww-data*.gem *.rbc .bundle .config .yardoc Gemfile.lock InstalledFiles _yardoc coverage doc/ lib/bundler/man pkg rdoc spec/reports test/tmp test/version_tmp tmp request_store-1.3.0/request_store.gemspec0000644000004100000410000000164412654142213020725 0ustar www-datawww-data# -*- encoding: utf-8 -*- lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'request_store/version' Gem::Specification.new do |gem| gem.name = "request_store" gem.version = RequestStore::VERSION gem.authors = ["Steve Klabnik"] gem.email = ["steve@steveklabnik.com"] gem.description = %q{RequestStore gives you per-request global storage.} gem.summary = %q{RequestStore gives you per-request global storage.} gem.homepage = "http://github.com/steveklabnik/request_store" gem.licenses = ["MIT"] gem.files = `git ls-files`.split($/) gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) } gem.test_files = gem.files.grep(%r{^(test|spec|features)/}) gem.require_paths = ["lib"] gem.add_development_dependency "rake" gem.add_development_dependency "minitest", "~> 5.0" end request_store-1.3.0/README.md0000644000004100000410000000643212654142213015733 0ustar www-datawww-data# 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) Ever needed to use a global variable in Rails? Ugh, that's the worst. If you need global state, you've probably reached for `Thread.current`. Like this: ```ruby def self.foo Thread.current[:foo] ||= 0 end def self.foo=(value) Thread.current[:foo] = value end ``` Ugh! I hate it. But you gotta do what you gotta do... ### The problem Everyone's worrying about concurrency these days. So people are using those fancy threaded web servers, like Thin or Puma. But if you use `Thread.current`, and you use one of those servers, watch out! Values can stick around longer than you'd expect, and this can cause bugs. For example, if we had this in our controller: ```ruby def index Thread.current[:counter] ||= 0 Thread.current[:counter] += 1 render :text => Thread.current[:counter] end ``` If we ran this on MRI with Webrick, you'd get `1` as output, every time. But if you run it with Thin, you get `1`, then `2`, then `3`... ### The solution Add this line to your application's Gemfile: ```ruby gem 'request_store' ``` And change the code to this: ```ruby def index RequestStore.store[:foo] ||= 0 RequestStore.store[:foo] += 1 render :text => RequestStore.store[:foo] end ``` Yep, everywhere you used `Thread.current` just change it to `RequestStore.store`. Now no matter what server you use, you'll get `1` every time: the storage is local to that request. ### Rails 2 compatibility The gem includes a Railtie that will configure everything properly for Rails 3+ apps, but if your app is tied to an older (2.x) version, you will have to manually add the middleware yourself. Typically this should just be a matter of adding: ```ruby config.middleware.use RequestStore::Middleware ``` into your config/environment.rb. ### No Rails? No Problem! A Railtie is added that configures the Middleware for you, but if you're not using Rails, no biggie! Just use the Middleware yourself, however you need. You'll probably have to shove this somewhere: ```ruby use RequestStore::Middleware ``` #### No Rails + Rack::Test In order to have `RequestStore` storage cleared between requests, add it to the `app`: ```ruby # spec_helper.rb def app Rack::Builder.new do use RequestStore::Middleware run MyApp end end ``` ## Semantic Versioning This project conforms to [semver](http://semver.org/). As a result of this policy, you can (and should) specify a dependency on this gem using the [Pessimistic Version Constraint](http://guides.rubygems.org/patterns/) with two digits of precision. For example: ```ruby spec.add_dependency 'request_store', '~> 1.0' ``` This means your project is compatible with request_store 1.0 up until 2.0. You can also set a higher minimum version: ```ruby spec.add_dependency 'request_store', '~> 1.1' ``` ## Contributing 1. Fork it 2. Create your feature branch (`git checkout -b my-new-feature`) 3. Commit your changes (`git commit -am 'Add some feature'`) 4. Push to the branch (`git push origin my-new-feature`) 5. Create new Pull Request Don't forget to run the tests with `rake`.