【问题标题】:Proper way to use a Rack middleware from a gem in a Rails project with Bundler使用 Bundler 在 Rails 项目中使用 gem 中的 Rack 中间件的正确方法
【发布时间】:2023-10-28 17:39:01
【问题描述】:

我有一个使用 Bundler 设置的 Rails 项目。我捆绑的其中一个 gem 提供了一个 Rack 中间件,我想在我的 Rails 应用程序中使用它(但只能在“生产”Rails 环境中使用)。

如果我只是在config/environments/production.rb 中输入这样的内容,我会得到一个未知的常量错误:

config.middleware.use ::Rack::MyMiddleware

...大概是因为此时尚未调用Bundler.require,并且我的捆绑 gem 都不可用。

我找到了一些解决此问题的方法,但似乎都不是很好,我想知道是否有我缺少的更标准的解决方案:

  1. config/environments/production.rb 中明确require 'my_middleware_gem'
  2. config.middleware.use 调用包装在 after_initialize 块中,确保 Bundler 在我尝试引用常量之前有机会完成它的工作。
  3. 使用字符串 ("::Rack::MyMiddleware") 代替裸类常量。由于某种原因,这似乎不适用于 Unicorn,但确实适用于其他一些服务器(对于 Unicorn,它最终会尝试调​​用 "::Rack::MyMiddleware".new,这当然会失败)。

我错过了一些更好的方法吗?预计在初始化过程中的什么时候捆绑的 gem 应该可用?

【问题讨论】:

  • 捆绑的 gems 应该在您的环境中可用 - 在 require 'rails/all' 之后调用 Bundle.require。 gem 的名称是什么,与所需文件的名称相同吗?你的Gemfile 中需要gem 'my_middleware_gem', :require => 'rack/my_middleware' 之类的东西吗?见:gembundler.com/gemfile.html
  • 抱歉,我忘了说我还在使用 Rails 2.3.8(我知道,我知道),设置在gembundler.com/rails23.html 中描述。我怀疑 Rails 2 关于何时调用 Bundler.require 的行为可能会有所不同。不过,关于您的建议 - gem 的名称与使用它所需的 require 语句相匹配,并在我的添加 :require 选项Gemfile 似乎对这种特殊行为没有影响。
  • 我错了——Gemfile 在 Rails 2 和 3 中的环境 之后 才会加载。看起来 Rails 自动加载常量 确实如此 虽然有效,有时这就足够了,但在这种情况下似乎不行。
  • 我认为在这种情况下使用after_initialize 块是正确的方法。
  • 是的,这就是我最终的结果。谢谢!关于原始问题中提到的独角兽问题,原来我遇到了这个问题:davidvollbracht.com/blog/…

标签: ruby-on-rails bundler rack middleware


【解决方案1】:

从 cmets 复制答案,以便从“未回答”过滤器中删除此问题:

matt 建议:

我认为在这种情况下使用after_initialize 块是正确的方法。

grumbler确认:

是的,这就是我最终选择的。谢谢!关于原始问题中提到的独角兽问题,原来我遇到了这个问题:http://davidvollbracht.com/blog/headachenewunicorn-capistrano-bundler-usr2

【讨论】: