你究竟是如何使用 Rack 的 env hash 的?

How exactly do you use Rack's env hash?

我有一个 Rails 4.2 应用程序,文件上传流量很大。

我想覆盖 rack.multipart.tempfile_factory 以提供与 Rack 在接受文件上传时在后台创建的临时文件相关联的额外行为。

那么在哪里以及如何更改 Rack 的 env 散列 完全 ?尝试在初始化程序中执行 env['...'] = ...,说 env 未定义。将其更改为 ENV 会引发一个错误,指出它无法将 lambda 转换为字符串(rack.multipart.tempfile_factory 需要一个 lambda,所以我不能只将其更改为字符串)。在控制器方法中使用 request.env 没有任何效果。我通过复制粘贴stock Rack factory的一行代码并添加了将随机数写入具有固定路径的文件来测试最后一个;在上传了一些文件后,该文件一开始就没有创建,所以就这样吧。

我正在寻找官方解决方案,无意对 Rack 进行猴子修补。它的规范说明这是可能的,那么我应该怎么做呢?

当然,如果一切都失败了,我会诉诸黑客,但我更愿意先听听官方的做法。

(当我们讨论这个问题时,您能否推荐一个无宝石解决方案来覆盖 rack.hijack_io,并提供一些真实世界的示例?特别是搜索那个东西不是非常有帮助,似乎没有人提供端到端的工作解决方案,只有点点滴滴。

感谢您的考虑。

第 1 部分:如何修改 Rack 的 env

您只需覆盖 Application#call。在 config/application.rb (或者 config/environments/production.rb 如果你喜欢)你添加这个方法:

class Application < Rails::Application
  ...
  def call(env)
    env["rack.multipart.tempfile_factory"] = ->(what, now) { "lambda time" }
    super(env)
  end
  ...
end

有关详细信息,请参阅 #call

第 2 部分:ENV

的含义

ENV 是 Ruby 中的常量,对应于 shell 环境。这允许您在 shell 脚本中执行以下操作:

$ export MY_VAR=hahahaha
...
irb> ENV['MY_VAR'] #=> "hahahaha"

它不仅仅是一个 Rack 变量——它是一个 Ruby 常量!

您的错误 "cannot convert lambda to string" 是因为所有 ENV 值都必须是字符串。所以即使你这样做

$ export MY_VAR=42

你会得到

irb> ENV['MY_VAR'] #=> "42"

其中 "42" 是字符串,而不是整数。