module AccountSlug PATTERN = /(\d+)/ PATH_INFO_MATCH = /\A(\/#{AccountSlug::PATTERN})/ class Extractor def initialize(app) @app = app end # We're using account id prefixes in the URL path. Rather than namespace # all our routes, we're "mounting" the Rails app at this URL prefix. def call(env) request = ActionDispatch::Request.new(env) # $1, $2, $' == script_name, slug, path_info if request.script_name && request.script_name =~ PATH_INFO_MATCH # Likely due to restarting the action cable connection after upgrade env["fizzy.external_account_id"] = AccountSlug.decode($2) elsif request.path_info =~ PATH_INFO_MATCH # Yanks the prefix off PATH_INFO and move it to SCRIPT_NAME request.engine_script_name = request.script_name = $1 request.path_info = $'.empty? ? "/" : $' # Stash the account's Queenbee ID. env["fizzy.external_account_id"] = AccountSlug.decode($2) end if env["fizzy.external_account_id"] account = Account.find_by(external_account_id: env["fizzy.external_account_id"]) Current.with_account(account) do @app.call env end else Current.without_account do @app.call env end end end end def self.decode(slug) slug.to_i end def self.encode(id) id.to_s end end Rails.application.config.middleware.insert_after Rack::TempfileReaper, AccountSlug::Extractor