Как получить доступ к среде Rack из Rails?
У меня есть приложение 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
Ответы
Ответ 1
Я уверен, вы можете использовать объект 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
Ответ 2
Краткий ответ: Используйте request.env
или env
внутри контроллера.
Длинный ответ:
В соответствии с Rails Guide on 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
, за исключением того, что его изменение изменяет переменную среды Rack, специфичную для Rails (и поэтому изменения останутся постоянный через экземпляры ActionDispatch::Request
).
Однако мне все еще не удалось найти метод session
. Оказывается, это совсем не в документации. После поиска исходного кода ActionController::Metal
я наконец нашел его на этой строки. Это правильно, это просто ярлык для request.session.
Подводя итог:
В контроллере...
- Используйте
request.env
или env
для доступа к объекту исходной среды
- Используйте
params
для чтения строк строк в стойке и отправки данных из входного потока стойки. (Например, Rack::Request#params
)
- Используйте
session
для доступа к значению rack.session
в среде стойки
В промежуточном программном обеспечении...