### Test Setup and Teardown with RequestStore Source: https://context7.com/steveklabnik/request_store/llms.txt Demonstrates clearing the RequestStore before and after each test to ensure isolation. This prevents data from leaking between tests. ```ruby class MyTest < Minitest::Test def setup RequestStore.clear! end def teardown RequestStore.clear! end def test_isolation RequestStore.store[:counter] = 5 RequestStore.clear! assert_equal({}, RequestStore.store) end end ``` -------------------------------- ### Thread-Local Storage Example (Before RequestStore) Source: https://github.com/steveklabnik/request_store/blob/master/README.md Demonstrates the use of Thread.current for global state, which can lead to issues in threaded environments. This pattern is discouraged. ```ruby def self.foo Thread.current[:foo] ||= 0 end def self.foo=(value) Thread.current[:foo] = value end ``` -------------------------------- ### Manually Add RequestStore Middleware (Non-Rails) Source: https://github.com/steveklabnik/request_store/blob/master/README.md If not using Rails, you can manually include the RequestStore::Middleware in your Rack application setup. ```ruby use RequestStore::Middleware ``` -------------------------------- ### Using RequestStore.fetch with a Block Source: https://github.com/steveklabnik/request_store/blob/master/README.md Demonstrates how to use the `fetch` method to retrieve a value from the store, or compute and store it if it doesn't exist. This is useful for lazy initialization. ```ruby top_posts = RequestStore.fetch(:top_posts) do # code to obtain the top posts end ``` -------------------------------- ### RequestStore Lifecycle Controls: begin!, end!, active? Source: https://context7.com/steveklabnik/request_store/llms.txt Illustrates how to manually control the RequestStore's active state. `begin!` and `end!` are typically handled by middleware, while `active?` is useful for conditional logic. ```ruby # Middleware lifecycle (handled automatically; shown here for illustration) RequestStore.active? # => false RequestStore.begin! RequestStore.active? # => true # ... request is processed ... RequestStore.end! RequestStore.active? # => false # Guard background-job code that should not run outside a request def cache_result(value) RequestStore.store[:result] = value if RequestStore.active? end ``` -------------------------------- ### RequestStore::Middleware for Rack Applications Source: https://context7.com/steveklabnik/request_store/llms.txt Shows how to integrate RequestStore::Middleware into a Rack application. This middleware manages the store's lifecycle automatically. ```ruby # Plain Rack app (config.ru) require 'request_store' use RequestStore::Middleware run MyRackApp ``` ```ruby # Rack::Test integration (spec_helper.rb / test_helper.rb) require 'rack/test' require 'request_store' def app Rack::Builder.new do use RequestStore::Middleware run MyApp end end ``` ```ruby # Rails 2 / manual insertion (config/environment.rb) config.middleware.use RequestStore::Middleware ``` -------------------------------- ### Write a Single Value with RequestStore.write or RequestStore[]= Source: https://context7.com/steveklabnik/request_store/llms.txt Assign a value to a key using RequestStore.write or the bracket assignment syntax RequestStore[]=. These operations are equivalent to directly setting a key on RequestStore.store. ```ruby # Two equivalent write forms RequestStore.write(:tenant_id, 99) RequestStore[:tenant_id] = 99 ``` ```ruby RequestStore.read(:tenant_id) # => 99 ``` -------------------------------- ### Fetch Data with Lazy Initialization using RequestStore.fetch Source: https://context7.com/steveklabnik/request_store/llms.txt RequestStore.fetch retrieves a value by key or, if absent, evaluates a block to initialize and store the value. This ensures expensive operations are performed at most once per request, improving performance. ```ruby class ProductService def self.featured_products RequestStore.fetch(:featured_products) do Product.where(featured: true).includes(:category).limit(10).to_a end end end ``` ```ruby # First call within a request — hits the database products = ProductService.featured_products # => [#, ...] # Subsequent calls within the same request — returns cached value same = ProductService.featured_products # same object, no DB query # After the request ends, RequestStore is cleared automatically, # so the next request fetches fresh data. ``` -------------------------------- ### RequestStore.write / RequestStore[]= Source: https://context7.com/steveklabnik/request_store/llms.txt Write a single value to the store. Both forms are equivalent to directly setting a key on `RequestStore.store`. ```APIDOC ## RequestStore.write / RequestStore[]= ### Description Writes a value to the store. Both forms are equivalent to directly setting a key on `RequestStore.store`. ### Usage Examples ```ruby # Two equivalent write forms RequestStore.write(:tenant_id, 99) RequestStore[:tenant_id] = 99 RequestStore.read(:tenant_id) # => 99 ``` ``` -------------------------------- ### RequestStore.exist? Source: https://context7.com/steveklabnik/request_store/llms.txt Check key presence. Returns `true` if the key is present in the store (including when the value is `nil` or `false`), `false` otherwise. ```APIDOC ## RequestStore.exist? — Check key presence ### Description Returns `true` if the key is present in the store (including when the value is `nil` or `false`), `false` otherwise. ### Usage Examples ```ruby RequestStore.store[:initialized] = false RequestStore.exist?(:initialized) # => true (key present, value is false) RequestStore.exist?(:missing_key) # => false ``` ``` -------------------------------- ### Controller Action Using RequestStore Source: https://github.com/steveklabnik/request_store/blob/master/README.md Shows the refactored controller action using RequestStore.store, ensuring that storage is local to the current request and thread-safe. ```ruby def index RequestStore.store[:foo] ||= 0 RequestStore.store[:foo] += 1 render :text => RequestStore.store[:foo] end ``` -------------------------------- ### Check Key Presence with RequestStore.exist? Source: https://context7.com/steveklabnik/request_store/llms.txt The RequestStore.exist? method checks if a key is present in the store. It returns true even if the stored value is nil or false, differentiating between a missing key and a key with a falsy value. ```ruby RequestStore.store[:initialized] = false ``` ```ruby RequestStore.exist?(:initialized) # => true (key present, value is false) RequestStore.exist?(:missing_key) # => false ``` -------------------------------- ### Read a Single Value with RequestStore.read or RequestStore[] Source: https://context7.com/steveklabnik/request_store/llms.txt Use RequestStore.read or the bracket syntax RequestStore[] to retrieve a value by its key. These methods safely return nil if the key does not exist, avoiding KeyErrors. ```ruby RequestStore.store[:locale] = :fr ``` ```ruby # Two equivalent read forms RequestStore.read(:locale) # => :fr RequestStore[:locale] # => :fr ``` ```ruby # Safe to read a missing key — returns nil, no KeyError RequestStore.read(:missing) # => nil ``` -------------------------------- ### RequestStore.fetch Source: https://context7.com/steveklabnik/request_store/llms.txt Read with lazy initialization. Returns the stored value for `key` if it exists. If not, evaluates the block, stores the result, and returns it. The block is evaluated at most once per request. ```APIDOC ## RequestStore.fetch — Read with lazy initialization ### Description Returns the stored value for `key` if it already exists. If no value is stored under that key, evaluates the block, stores the result, and returns it. Subsequent calls with the same key skip the block entirely — it is called at most once per request. ### Usage Examples ```ruby class ProductService def self.featured_products # Expensive DB query runs at most once per request, regardless of # how many times this method is called during the same request. RequestStore.fetch(:featured_products) do Product.where(featured: true).includes(:category).limit(10).to_a end end end # First call within a request — hits the database products = ProductService.featured_products # => [#, ...] # Subsequent calls within the same request — returns cached value same = ProductService.featured_products # same object, no DB query # After the request ends, RequestStore is cleared automatically, # so the next request fetches fresh data. ``` ``` -------------------------------- ### RequestStore.store Source: https://context7.com/steveklabnik/request_store/llms.txt Access the per-request hash. Initializes it to an empty hash if it hasn't been set yet. This is the primary interface and a drop-in replacement for Thread.current[...] patterns. ```APIDOC ## RequestStore.store — Access the per-request hash ### Description Returns the current thread's request-scoped hash, initializing it to `{}` if it hasn't been set yet. This is the primary interface and a drop-in replacement for `Thread.current[...]` patterns. ### Usage Examples ```ruby # Before (unsafe with threaded servers — values leak between requests) # Thread.current[:current_user_id] = 42 # After (safe — cleared after every request) RequestStore.store[:current_user_id] = 42 # Typical usage in a Rails controller/model class ApplicationController < ActionController::Base before_action :set_current_user_store private def set_current_user_store RequestStore.store[:current_user] = current_user RequestStore.store[:request_id] = request.uuid end end # Accessed anywhere downstream (model, service object, etc.) class AuditLogger def self.log(action) user = RequestStore.store[:current_user] req = RequestStore.store[:request_id] Rails.logger.info "[#{req}] User #{user&.id} performed #{action}" end end ``` ``` -------------------------------- ### Add RequestStore to Gemfile Source: https://github.com/steveklabnik/request_store/blob/master/README.md The initial step to integrate RequestStore into your Rails application by adding it to your Gemfile. ```ruby gem 'request_store' ``` -------------------------------- ### RequestStore Lifecycle Controls Source: https://context7.com/steveklabnik/request_store/llms.txt Manages the active state of the RequestStore and provides access to the store itself. `begin!` and `end!` are typically called by middleware, while `active?` can be used for conditional logic. ```APIDOC ## RequestStore.begin! / RequestStore.end! / RequestStore.active? ### Description Manages the lifecycle of the request store. `begin!` activates the store, `end!` deactivates it, and `active?` checks the current state. ### Methods - `RequestStore.begin!` - `RequestStore.end!` - `RequestStore.active?` ### Usage Example ```ruby # Middleware lifecycle (handled automatically; shown here for illustration) RequestStore.active? # => false RequestStore.begin! RequestStore.active? # => true # ... request is processed ... RequestStore.end! RequestStore.active? # => false # Guard background-job code that should not run outside a request def cache_result(value) RequestStore.store[:result] = value if RequestStore.active? end ``` ### Accessing the Store `RequestStore.store` provides access to the key-value store. ### Example ```ruby RequestStore.store[:user_id] = 123 puts RequestStore.store[:user_id] # => 123 ``` ``` -------------------------------- ### RequestStore.read / RequestStore[] Source: https://context7.com/steveklabnik/request_store/llms.txt Read a single value from the store by key. Both forms are equivalent. Returns `nil` if the key does not exist. ```APIDOC ## RequestStore.read / RequestStore[] — Read a single value ### Description Reads a value from the store by key. Both forms are equivalent. Returns `nil` if the key does not exist. ### Usage Examples ```ruby RequestStore.store[:locale] = :fr # Two equivalent read forms RequestStore.read(:locale) # => :fr RequestStore[:locale] # => :fr # Safe to read a missing key — returns nil, no KeyError RequestStore.read(:missing) # => nil ``` ``` -------------------------------- ### Problematic Controller Action with Thread.current Source: https://github.com/steveklabnik/request_store/blob/master/README.md Illustrates how using Thread.current in a controller action can lead to unexpected behavior and bugs when running on threaded web servers like Thin or Puma. ```ruby def index Thread.current[:counter] ||= 0 Thread.current[:counter] += 1 render :text => Thread.current[:counter] end ``` -------------------------------- ### Sidekiq Integration with Companion Gem Source: https://context7.com/steveklabnik/request_store/llms.txt Uses the `request_store-sidekiq` gem to automatically add a Sidekiq server middleware. This middleware clears the store after each job, similar to the Rack middleware. ```ruby # Gemfile gem 'request_store' gem 'request_store-sidekiq' # No additional configuration needed — the companion gem registers # its middleware automatically. # Your Sidekiq worker can safely use RequestStore within a job, # knowing it will be cleared before the next job runs on the same thread. class ReportJob include Sidekiq::Job def perform(user_id) RequestStore.store[:job_user_id] = user_id ReportBuilder.build # safely reads RequestStore.store[:job_user_id] # store is cleared automatically after this job completes end end ``` -------------------------------- ### Manually Add RequestStore Middleware (Rails 2) Source: https://github.com/steveklabnik/request_store/blob/master/README.md For older Rails 2.x applications, the RequestStore middleware needs to be manually added to the environment configuration. ```ruby config.middleware.use RequestStore::Middleware ``` -------------------------------- ### Sidekiq Integration Source: https://context7.com/steveklabnik/request_store/llms.txt Utilizes the `request_store-sidekiq` companion gem to add a Sidekiq server middleware that clears the store after each job, ensuring isolation between jobs processed on the same thread. ```APIDOC ## Sidekiq integration ### Description Use the companion gem `request_store-sidekiq` to add a Sidekiq server middleware that clears the store after each job, matching the Rack behavior. This ensures isolation between jobs processed on the same thread. ### Gemfile ```ruby gem 'request_store' gem 'request_store-sidekiq' ``` ### Configuration No additional configuration is needed, as the companion gem registers its middleware automatically. ### Usage within Sidekiq Worker Your Sidekiq worker can safely use `RequestStore` within a job, knowing it will be cleared before the next job runs on the same thread. ```ruby class ReportJob include Sidekiq::Job def perform(user_id) RequestStore.store[:job_user_id] = user_id ReportBuilder.build # safely reads RequestStore.store[:job_user_id] # store is cleared automatically after this job completes end end ``` ``` -------------------------------- ### RequestStore Middleware with Rack::Test Source: https://github.com/steveklabnik/request_store/blob/master/README.md Configures the RequestStore middleware within a Rack::Builder for use with Rack::Test, ensuring the store is cleared between test requests. ```ruby # spec_helper.rb def app Rack::Builder.new do use RequestStore::Middleware run MyApp end end ``` -------------------------------- ### RequestStore::Middleware Source: https://context7.com/steveklabnik/request_store/llms.txt A Rack middleware that automatically manages the RequestStore lifecycle for incoming HTTP requests. It ensures the store is active during request processing and cleared afterward. ```APIDOC ## RequestStore::Middleware ### Description A Rack middleware that calls `RequestStore.begin!` before the app, wraps the response body to keep the store active during streaming, and calls `RequestStore.end!` and `RequestStore.clear!` after the body is consumed or on error. ### Usage #### Plain Rack app (config.ru) ```ruby require 'request_store' use RequestStore::Middleware run MyRackApp ``` #### Rack::Test integration (spec_helper.rb / test_helper.rb) ```ruby require 'rack/test' require 'request_store' def app Rack::Builder.new do use RequestStore::Middleware run MyApp end end ``` #### Rails 2 / manual insertion (config/environment.rb) ```ruby config.middleware.use RequestStore::Middleware ``` ``` -------------------------------- ### DelayedJob Integration Source: https://context7.com/steveklabnik/request_store/llms.txt Integrates RequestStore with DelayedJob by adding a plugin that clears the store after each job completes, preventing data leakage between jobs processed by the same worker thread. ```APIDOC ## DelayedJob integration ### Description Background jobs run outside a Rack request, so the middleware doesn't fire. This integration adds a DelayedJob plugin to call `RequestStore.clear!` after each job, preventing store data from leaking across jobs processed by the same worker thread. ### Configuration (config/initializers/request_store_delayed_job.rb) ```ruby module Delayed module Plugins class RequestStore < Plugin module Cache def after(job) ::RequestStore.clear! super if defined?(super) end end callbacks do |lifecycle| lifecycle.before(:invoke_job) do |job| payload = job.payload_object payload = payload.object if payload.is_a?(Delayed::PerformableMethod) payload.extend Cache end end end end end Delayed::Worker.plugins << Delayed::Plugins::RequestStore ``` ``` -------------------------------- ### Rails 3+ Integration with Railtie Source: https://context7.com/steveklabnik/request_store/llms.txt For Rails 3+ applications, the request_store gem automatically inserts its middleware. No manual configuration is needed in `config/environment.rb`. ```ruby # Gemfile — that's all you need for Rails 3+ gem 'request_store', '~> 1.7' # Verify the middleware is present $ rails middleware # ... # use RequestStore::Middleware # ... # No other configuration required. The store is available # everywhere within a request: class OrdersController < ApplicationController def create RequestStore.store[:order_context] = { channel: 'web', ip: request.remote_ip } OrderCreationService.call(order_params) end end class OrderCreationService def self.call(params) ctx = RequestStore.store[:order_context] # ctx => { channel: "web", ip: "1.2.3.4" } end end ``` -------------------------------- ### Rails Integration (Rails 3+) Source: https://context7.com/steveklabnik/request_store/llms.txt For Rails 3+ applications, the `request_store` gem automatically inserts `RequestStore::Middleware` into the Rack stack and sets up a reloader hook to clear the store between development code reloads. ```APIDOC ## Rails integration via Railtie ### Description For Rails 3+ apps, the gem automatically inserts `RequestStore::Middleware` and registers a reloader hook to clear the store between code-reload cycles in development. No manual configuration is needed beyond adding the gem to your Gemfile. ### Gemfile ```ruby gem 'request_store', '~> 1.7' ``` ### Verification Verify the middleware is present by running: ```bash $ rails middleware # ... # use RequestStore::Middleware # ... ``` ### Usage within Rails The store is available everywhere within a request: ```ruby class OrdersController < ApplicationController def create RequestStore.store[:order_context] = { channel: 'web', ip: request.remote_ip } OrderCreationService.call(order_params) end end class OrderCreationService def self.call(params) ctx = RequestStore.store[:order_context] # ctx => { channel: "web", ip: "1.2.3.4" } end end ``` ``` -------------------------------- ### RequestStore.clear! Source: https://context7.com/steveklabnik/request_store/llms.txt Reset the store. Replaces the current store with a fresh empty hash. Called automatically by `RequestStore::Middleware` at the end of every request; useful in tests or background jobs to reset state manually. ```APIDOC ## RequestStore.clear! — Reset the store ### Description Replaces the current store with a fresh empty hash. Called automatically by `RequestStore::Middleware` at the end of every request; useful in tests or background jobs to reset state manually. ### Usage Examples ```ruby # Example usage in a test scenario RequestStore.store[:user_id] = 123 RequestStore.clear! RequestStore.read(:user_id) # => nil ``` ``` -------------------------------- ### DelayedJob Integration with Custom Plugin Source: https://context7.com/steveklabnik/request_store/llms.txt Integrates RequestStore with DelayedJob by adding a plugin that clears the store after each job. This prevents data leakage between jobs on the same worker thread. ```ruby # config/initializers/request_store_delayed_job.rb module Delayed module Plugins class RequestStore < Plugin module Cache def after(job) ::RequestStore.clear! super if defined?(super) end end callbacks do |lifecycle| lifecycle.before(:invoke_job) do |job| payload = job.payload_object payload = payload.object if payload.is_a?(Delayed::PerformableMethod) payload.extend Cache end end end end end Delayed::Worker.plugins << Delayed::Plugins::RequestStore ``` -------------------------------- ### RequestStore.delete Source: https://context7.com/steveklabnik/request_store/llms.txt Remove a key from the store. Accepts an optional block that is called with the key if it is not found, mirroring `Hash#delete` semantics. ```APIDOC ## RequestStore.delete — Remove a key ### Description Removes a key from the store. Accepts an optional block that is called with the key if it is not found, mirroring `Hash#delete` semantics. ### Usage Examples ```ruby RequestStore.store[:temp_flag] = true RequestStore.delete(:temp_flag) # => true (removed value) RequestStore.delete(:temp_flag) # => nil (already gone) RequestStore.delete(:temp_flag) { |k| "#{k} not found" } # => "temp_flag not found" ``` ``` -------------------------------- ### Access Per-Request Hash with RequestStore.store Source: https://context7.com/steveklabnik/request_store/llms.txt Use RequestStore.store to access the current thread's request-scoped hash. This is a safe replacement for Thread.current, ensuring data is isolated per request. Values are automatically cleared at the end of each request. ```ruby Thread.current[:current_user_id] = 42 ``` ```ruby RequestStore.store[:current_user_id] = 42 ``` ```ruby class ApplicationController < ActionController::Base before_action :set_current_user_store private def set_current_user_store RequestStore.store[:current_user] = current_user RequestStore.store[:request_id] = request.uuid end end ``` ```ruby class AuditLogger def self.log(action) user = RequestStore.store[:current_user] req = RequestStore.store[:request_id] Rails.logger.info "[#{req}] User #{user&.id} performed #{action}" end end ``` -------------------------------- ### Add RequestStore Dependency in Gemspec Source: https://github.com/steveklabnik/request_store/blob/master/README.md Specifies the RequestStore gem dependency in a gemspec file using pessimistic version constraints for compatibility. ```ruby spec.add_dependency 'request_store', '~> 1.0' ``` ```ruby spec.add_dependency 'request_store', '~> 1.1' ``` -------------------------------- ### DelayedJob RequestStore Plugin Source: https://github.com/steveklabnik/request_store/wiki/Integration-with-DelayedJob This plugin extends DelayedJob to clear the RequestStore cache after each job. It hooks into the job lifecycle to ensure proper cache management. ```ruby module Delayed module Plugins class RequestStore < Plugin module Cache def after(job) ::RequestStore.clear! super if defined?(super) end end callbacks do |lifecycle| lifecycle.before(:invoke_job) do |job| payload = job.payload_object payload = payload.object if payload.is_a? Delayed::PerformableMethod payload.extend Cache end end end end end Delayed::Worker.plugins << Delayed::Plugins::RequestStore ``` -------------------------------- ### Remove a Key with RequestStore.delete Source: https://context7.com/steveklabnik/request_store/llms.txt Use RequestStore.delete to remove a key-value pair from the store. It returns the removed value or nil if the key was not found. An optional block can be provided to handle cases where the key is absent, similar to Hash#delete. ```ruby RequestStore.store[:temp_flag] = true ``` ```ruby RequestStore.delete(:temp_flag) # => true (removed value) RequestStore.delete(:temp_flag) # => nil (already gone) ``` ```ruby RequestStore.delete(:temp_flag) { |k| "#{k} not found" } # => "temp_flag not found" ``` -------------------------------- ### Reset the Store with RequestStore.clear! Source: https://context7.com/steveklabnik/request_store/llms.txt RequestStore.clear! replaces the current request store with a new, empty hash. This method is automatically called by the RequestStore::Middleware after each request but can be manually invoked in tests or background jobs to reset the state. ```ruby # No code example provided in source for this section. ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.