Como faço para acessar o ambiente de rack de dentro Rails?
-
21-08-2019 - |
Pergunta
Eu tenho uma aplicação Rack que se parece com isso:
class Foo
def initialize(app)
@app = app
end
def call(env)
env["hello"] = "world"
@app.call(env)
end
end
Depois de ligar a minha aplicação Rack em Rails, como faço para obter acesso a env["hello"]
de dentro Rails?
Atualizar : Graças a Caio para a resposta. Rack e Rails permitem armazenar coisas para a duração do pedido, ou a duração da sessão:
# 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
Solução
Eu tenho certeza que você pode usar o objeto Rack::Request
para passar variáveis ??pedido de escopo:
# 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
Como alternativa, você pode obter naquele objeto "env
" diretamente:
# middleware:
def call(env)
env['foo'] = 'bar'
@app.call(env)
end
# controller:
def index
if request.env['foo'] == 'bar'
...
end
end
Outras dicas
Resposta curta:. Use request.env
ou env
dentro de um controlador
Resposta longa:
De acordo com a Guia do Rails on Rails controladores , ActionController fornece uma método request
que você pode usar para acessar informações sobre a solicitação HTTP atual controlador está respondendo a.
Após uma inspecção mais aprofundada dos documentos para ActionController::Base#request
, vemos que ela "Retorna uma instância ActionDispatch :: Request que representa a solicitação atual."
Se olharmos para os documentos para ActionDispatch::Request
, vemos que ele herda de Rack::Request
. Aha! Aqui vamos nós.
Agora, no caso de você não estiver familiarizado com a documentação para Rack::Request
, é basicamente um invólucro em torno do ambiente rack. Assim, para a maioria dos casos, você deve apenas ser capaz de usá-lo como está. Se você realmente quer o hash ambiente crua, porém, você pode obtê-lo com Rack::Request#env
. Então, dentro do controlador Rails, que seria apenas request.env
.
Indo mais fundo:
Depois de examinar ainda mais os métodos de instância de ActionController::Base
, notei que não é um lote inteiro lá para olhar. Em particular, eu notei a params
e variáveis ??session
parecem estar faltando. Então, eu me mudei para um nível acima para ActionController::Metal
, que ActionController::Base
herda a partir
Na ActionController::Metal
, eu descobri um método env
que não tinha documentação, como o que ele fez - mas eu podia adivinhar. Acontece que eu estava certo. Essa variável foi sendo atribuído a request.env
.
ActionController::Metal
também continha o params
método, que, de acordo com a fonte , foi definido como request.parameters
por padrão. Como se vê, request.parameters
não é de Rack::Request
, mas ActionDispatch :: Http :: Parâmetros , que é incluído por ActionDispatch::Request
. Este método é muito semelhante ao método Rack::Request#params
, salvo que a alteração modifica uma variável ambiente cremalheira específicos de carris (e, por conseguinte, muda permanecerá persistente entre instâncias de ActionDispatch::Request
).
No entanto, eu ainda podia não parecem encontrar o método session
. Acontece que, não é na documentação em tudo. Depois de pesquisar o código fonte para ActionController::Metal
, eu finalmente encontrei-o em esta linha . É isso mesmo, é apenas um atalho para request.session .
Para resumir:
No controlador ...
- Use
request.env
ouenv
para chegar ao objeto ambiente cru - Use
params
para ler seqüências de consulta da cremalheira e postar dados do fluxo de entrada rack. (Por exemploRack::Request#params
) - Use
session
para acessar o valor derack.session
no ambiente cremalheira
No middleware ...
- propriedades de acesso do ambiente da maneira usual, através do hash de ambiente
- Acesse as Rails sessão através da propriedade
rack.session
sobre o hash de ambiente - Leia params através
Rack::Request#params
- Atualização params através
Rack::Request#update_param
eRack::Request#delete_param
(como indicado na documentação paraRack::Request#params
) - Atualização params de uma maneira específica Rails usando
ActionDispatch::Http::Parameters#params
ActionDispatch::Request