Как мне получить доступ к среде Rack из Rails?
-
21-08-2019 - |
Вопрос
У меня есть приложение Rack, которое выглядит так:
class Foo
def initialize(app)
@app = app
end
def call(env)
env["hello"] = "world"
@app.call(env)
end
end
После подключения моего приложения Rack к Rails, как мне получить доступ к env["hello"]
изнутри Rails?
Обновлять:Спасибо Гаюсу за ответ.Rack and Rails позволяют хранить данные на время запроса или сеанса:
# in middleware
def call(env)
Rack::Request.new(env)["foo"] = "bar" # sticks around for one request
env["rack.session"] ||= {}
env["rack.session"]["hello"] = "world" # sticks around for duration of session
end
# in Rails
def index
if params["foo"] == "bar"
...
end
if session["hello"] == "world"
...
end
end
Решение
Я почти уверен, что вы можете использовать Rack::Request
объект для передачи переменных области запроса:
# middleware:
def call(env)
request = Rack::Request.new(env) # no matter how many times you do 'new' you always get the same object
request[:foo] = 'bar'
@app.call(env)
end
# Controller:
def index
if params[:foo] == 'bar'
...
end
end
Альтернативно, вы можете добраться до этого "env
" объект напрямую:
# middleware:
def call(env)
env['foo'] = 'bar'
@app.call(env)
end
# controller:
def index
if request.env['foo'] == 'bar'
...
end
end
Другие советы
Короткий ответ: Использовать request.env
или env
внутри контроллера.
Длинный ответ:
Согласно Руководство Rails по контроллерам Rails, ActionController предоставляет request
метод, который вы можете использовать для доступа к информации о текущем HTTP-запросе, на который отвечает ваш контроллер.
При дальнейшем рассмотрении документов на ActionController::Base#request
, мы видим, что он «Возвращает экземпляр ActionDispatch::Request, который представляет текущий запрос».
Если мы посмотрим на документы для ActionDispatch::Request
, мы видим, что он наследуется от Rack::Request
.Ага!Вот так.
Теперь, если вы не знакомы с документацией по Rack::Request
, По сути, это оболочка среды Rack.Поэтому в большинстве случаев вы можете использовать его как есть.Если вам действительно нужен необработанный хэш среды, вы можете получить его с помощью Rack::Request#env
.Итак, внутри контроллера Rails это будет просто request.env
.
Копать глубже:
После дальнейшего изучения методов экземпляра ActionController::Base
, Я заметил, что там особо не на что смотреть.В частности, я заметил params
и session
переменные, кажется, отсутствуют.Итак, я поднялся на один уровень выше, ActionController::Metal
, который ActionController::Base
наследует от.
В ActionController::Metal
, я открыл метод env
у которого не было документации о том, что он делал, но я мог догадаться.Оказывается, я был прав.Эта переменная была будучи назначенным на request.env
.
ActionController::Metal
также содержал params
метод, который, по мнению источник, было установлено на request.parameters
по умолчанию.Как выясняется из, request.parameters
не из Rack::Request
, но ActionDispatch::Http::Параметры, который включен в ActionDispatch::Request
.Этот метод очень похож на Rack::Request#params
метод, за исключением того, что его изменение изменяет специфичную для Rails переменную среды Rack (и, следовательно, изменения будут оставаться постоянными во всех экземплярах ActionDispatch::Request
).
Однако я все еще не мог найти session
метод.Оказывается, этого вообще нет в документации.После поиска исходного кода для ActionController::Metal
, я наконец нашел это на эта линия.Правильно, это просто ярлык для запрос.сессия.
Обобщить:
В контроллере...
- Использовать
request.env
илиenv
чтобы добраться до необработанного объекта среды - Использовать
params
для чтения строк запроса Rack и публикации данных из входного потока стойки.(Например.Rack::Request#params
) - Использовать
session
чтобы получить доступ к значениюrack.session
в стойке
В промежуточном программном обеспечении...
- Доступ к свойствам среды обычным способом через хэш среды.
- Доступ к сеансу Rails через
rack.session
свойство в хеше среды - Прочитайте параметры через
Rack::Request#params
- Обновить параметры через
Rack::Request#update_param
иRack::Request#delete_param
(как указано в документации дляRack::Request#params
) - Обновите параметры специфическим для Rails способом, используя
ActionDispatch::Http::Parameters#params
черезActionDispatch::Request