我有一个看起来像这样的Rack应用程序:
class Foo
def initialize(app)
@app = app
end
def call(env)
env["hello"] = "world"
@app.call(env)
end
end
将我的Rack应用程序挂钩到Rails后,如何从Rails中访问env["hello"]
?
更新:感谢Gaius的回答。 Rack和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
答案 0 :(得分:26)
我很确定您可以使用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
答案 1 :(得分:21)
简答:在控制器内使用request.env
或env
。
根据Rails Guide on Rails controllers,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
继承了。{/ p>
在ActionController::Metal
中,我发现了一种方法env
,它没有关于它做了什么的文档 - 但我可以猜到。事实证明我是对的。该变量为being assigned to request.env
。
ActionController::Metal
还包含params
方法,根据the source,默认设置为request.parameters
。事实证明,request.parameters
不是Rack::Request
,而是ActionDispatch::Http::Parameters,ActionDispatch::Request
包含Rack::Request#params
。此方法与ActionDispatch::Request
方法非常相似,不同之处在于更改它会修改特定于Rails的Rack环境变量(因此更改将在ActionController::Metal
的实例之间保持持久性。)
但是,我似乎仍然无法找到session
方法。事实证明,根本不在文档中。在搜索this line的源代码后,我终于在request.session上找到了它。没错,它只是Rack::Request#params
的捷径。
在控制器中......
request.env
或env
获取原始环境对象params
读取Rack查询字符串并从机架输入流发布数据。 (例如Rack::Request#params
)session
访问机架环境中rack.session
的值在中间件......
rack.session
属性访问Rails会话
Rack::Request#update_param
Rack::Request#delete_param
和Rack::Request#params
更新参数(如ActionDispatch::Http::Parameters#params
的文档中所述)ActionDispatch::Request
到{{3}}