Вопрос

У меня есть приложение 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 в стойке

В промежуточном программном обеспечении...

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top