Ruby-on-rails 如何从 Rails 中访问 Rack 环境?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/848591/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I access the Rack environment from within Rails?
提问by Michael Gundlach
I have a Rack application that looks like this:
我有一个如下所示的 Rack 应用程序:
class Foo
def initialize(app)
@app = app
end
def call(env)
env["hello"] = "world"
@app.call(env)
end
end
After hooking my Rack application into Rails, how do I get access to env["hello"]from within Rails?
将 Rack 应用程序挂接到 Rails 后,如何env["hello"]从 Rails 内部访问?
Update: Thanks to Gaius for the answer. Rack and Rails let you store things for the duration of the request, or the duration of the session:
更新:感谢 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
采纳答案by James A. Rosen
I'm pretty sure you can use the Rack::Requestobject for passing request-scope variables:
我很确定您可以使用该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
Alternatively, you can get at that "env" object directly:
或者,您可以env直接获取该 " " 对象:
# middleware:
def call(env)
env['foo'] = 'bar'
@app.call(env)
end
# controller:
def index
if request.env['foo'] == 'bar'
...
end
end
回答by Ajedi32
Short answer:Use request.envor envinside a controller.
简短回答:使用request.env或env在控制器内部。
Long answer:
长答案:
According to the Rails Guide on Rails controllers, ActionController provides a requestmethod that you can use to access information about the current HTTP request your controller is responding to.
根据Rails 控制器的Rails 指南,ActionController 提供了一种request方法,您可以使用该方法访问有关控制器正在响应的当前 HTTP 请求的信息。
Upon further inspection of the docs for ActionController::Base#request, we see that it "Returns an ActionDispatch::Request instance that represents the current request."
在进一步检查 的文档后ActionController::Base#request,我们看到它“返回一个代表当前请求的 ActionDispatch::Request 实例”。
If we look at the docs for ActionDispatch::Request, we see that it inherits from Rack::Request. Aha! Here we go.
如果我们查看 的文档ActionDispatch::Request,我们会看到它继承自Rack::Request. 啊哈!开始了。
Now, in case you're not familiar with the docs for Rack::Request, it's basically a wrapper around the Rack environment. So for most cases, you should just be able to use it as-is. If you really do want the raw environment hash though, you can get it with Rack::Request#env. So within the Rails controller, that would just be request.env.
现在,如果您不熟悉 的文档Rack::Request,它基本上是 Rack 环境的包装器。因此,在大多数情况下,您应该能够按原样使用它。但是,如果您确实想要原始环境哈希,则可以使用Rack::Request#env. 所以在 Rails 控制器中,那只是request.env.
Digging deeper:
深层发掘:
After further examining the instance methods of ActionController::Base, I noticed there's not a whole lot there to look at. In particular, I noticed the paramsand sessionvariables seem to be missing. So, I moved up one level to ActionController::Metal, which ActionController::Baseinherits from.
在进一步检查了 的实例方法之后ActionController::Base,我注意到没有太多可看的。特别是,我注意到params和session变量似乎丢失了。所以,我上移了一个级别到ActionController::Metal,它ActionController::Base继承自。
In ActionController::Metal, I discovered a method envwhich had no documentation as to what it did - but I could guess. Turns out I was right. That variable was being assigned to request.env.
在 中ActionController::Metal,我发现了一种方法env,该方法没有关于它的作用的文档 - 但我可以猜到。原来我是对的。该变量被分配给request.env.
ActionController::Metalalso contained the paramsmethod, which, according to the source, was set to request.parametersby default. As it turns out, request.parametersisn't from Rack::Request, but ActionDispatch::Http::Parameters, which is included by ActionDispatch::Request. This method is very similar to the Rack::Request#paramsmethod, except that altering it modifies a Rails-specific Rack environment variable (and therefore changes will remain persistent across instances of ActionDispatch::Request).
ActionController::Metal还包含该params方法,根据来源,该方法request.parameters默认设置为。事实证明,request.parameters不是 from Rack::Request,而是ActionDispatch::Http::Parameters,它包含在ActionDispatch::Request. 此方法与 方法非常相似Rack::Request#params,不同之处在于更改它会修改特定于 Rails 的 Rack 环境变量(因此更改将在 的实例中保持不变ActionDispatch::Request)。
However, I still couldn't seem to find the sessionmethod. Turns out, it's not in the documentation at all. After searching the source code for ActionController::Metal, I finally found it on this line. That's right, it's just a shortcut for request.session.
但是,我似乎仍然找不到session方法。事实证明,它根本不在文档中。搜索源代码后ActionController::Metal,我终于在这一行找到了。没错,它只是request.session的快捷方式。
To summarize:
总结一下:
In the controller...
在控制器...
- Use
request.envorenvto get at the raw environment object - Use
paramsto read Rack query strings and post data from the rack input stream. (E.g.Rack::Request#params) - Use
sessionto access the value ofrack.sessionin the rack environment
- 使用
request.env或env获取原始环境对象 - 使用
params读取从机架输入流机架查询字符串和后数据。(例如Rack::Request#params) - 使用
session访问的价值rack.session在机架环境
In the middleware...
在中间件...
- Access properties of the environment the usual way through the environment hash
- Access the Rails session through the
rack.sessionproperty on the environment hash - Read params through
Rack::Request#params - Update params through
Rack::Request#update_paramandRack::Request#delete_param(as stated in the docs forRack::Request#params) - Update params in a Rails specific way using
ActionDispatch::Http::Parameters#paramsthroughActionDispatch::Request
- 通过环境哈希以通常的方式访问环境的属性
- 通过
rack.session环境哈希上的属性访问 Rails 会话 - 通过读取参数
Rack::Request#params - 通过
Rack::Request#update_param和更新参数Rack::Request#delete_param(如文档中所述Rack::Request#params) - 使用
ActionDispatch::Http::Parameters#paramsthrough以特定于 Rails 的方式更新参数ActionDispatch::Request

![Ruby-on-rails 在 Rails 中,如何以可与 ActiveSupport::TimeZone[zone].parse() 一起使用的格式获取当前时区 (Time.zone)?](/res/img/loading.gif)