У меня есть мультитенантное приложение Ruby on Rails 4.2, в котором я хочу, чтобы каждый арендатор использовал свои собственные файлы cookie сеанса и параметры cookie.Я пробовал разные подходы, но я не могу понять каждую деталь правильно.
Чтобы добавить больше контекста, клиент выбирается из URL-адреса хоста в запросе, в Middleware, и ему присваивается переменная потока, к которой я могу обращаться по стеку.Давайте назовем этот объект настроек как Settings.current_account
.
Опция 1: промежуточное ПО :
class AccountableSessionCookies
def initialize(app)
@app = app
end
# @param [Hash] The Rack environment.
def call(env)
dup.call!(env)
end
# @param env [Hash] The Rack environment.
def call!(env)
env['rack.session.options'][:key] = Settings.current_account.session_key
env['rack.session.options'][:expire_after] = Settings.current_account.session_expiration
@app.call(env)
end
end
, а затем в инициализаторе
Rails.application.config.session_store :cookie_store, key: 'bla',
expire_after: 1_209_600
Результат: это позволит мне установить expire_after
, но не имя куки, которое останется bla
.
Вариант 2: пользовательское хранилище куки
module ActionDispatch
module Session
class AccountCookieStore < CookieStore
def initialize(app, options={})
super(app, options.merge!(key: Settings.current_account.session_key),
expire_after: Settings.current_account.session_expiration)))
end
end
end
end
и затем в инициализаторе:
Rails.application.config.session_store :account_cookie_store, key: 'bla',
expire_after: 1_209_600
Но тогда создается впечатление, что экземпляр AccountCookieStore
загружается ДО того, как вызов поступит на промежуточное программное обеспечение, если Settings.current_account
, поэтому из запроса нельзя извлечь значения и использовать их для создания файла cookie.
Вариант 3: after_filter в ApplicationController
after_filter :short_session
def short_session
request.session_options = request.session_options.dup
request.session_options[:expire_after] = 100.days.to_i
request.session_options[:key] = 'mynewkey'
request.session_options.freeze
end
Это просто не работает.
Чего мне не хватает?Любые идеи о том, как я могу это сделать?