在Rails 3中在运行时加载Gem

10

我有一个Rails 3.0.x应用程序。我想在运行时加载gem,而不使用。

我的目标是像往常一样加载应用程序,让Bundler加载常规的gems。然后,我想加载位于特定目录中的所有gems(Rails Engines),但在运行时之前,我不知道会有哪些gems。

是否有人知道这在Rails中是否可能,也许使用Bundler API?


出于好奇,你能解释一下使用案例吗?我不清楚为什么你想要这样做。 - nathanvda
想法是创建一个模块化的Rails应用程序,在运行时加载其模块。我希望将模块/宝石放入目录中,启动应用程序并保持灵活性 :) - maciej-rosiek
好的,我假设你有一个通用的Rails应用程序,你会在客户现场安装它,并根据某些选项(费用/许可证),在文件夹中安装正确的模块。但是如果你只编辑Gemfile并运行bundle install呢?这样做的工作量更小,更安全,而且唯一的编辑/配置就是编辑Gemfile。这就是我们所做的。我们为自己的“私有”gems托管了自己的gemserver。如果启用或禁用了一个模块,我们只需编辑Gemfile、bundle并重新启动即可。 - nathanvda
当然,这是其中一种选择,这也是最终所做的(请记住,这个问题不是最近才被问到的)。但是能够在运行时加载模块会很好。 - maciej-rosiek
2个回答

6
您试图做的事情是危险的。如果您的每个Rails引擎也是一个gem,则它们也会有其他依赖项的Gemfile,这些依赖项又会有其他依赖项等等。如果允许Bundler解决这些问题,那么您在运行时将会遇到较少的问题。
以下是如何不使用任何黑客技巧实现的方法。请记住,您的Gemfile只是Ruby代码,您可以拥有默认未加载的gem。
# In your Gemfile, add at the end:
Dir[YOUR_RAILS_ENGINES_SUBFOLDER + "/*/*.gemspec"].each do |gemspec_file|
  dir_name = File.dirname(gemspec_file)
  gem_name = File.basename(gemspec_file, File.extname(gemspec_file))

  # sometimes "-" and "_" are used interchangeably in gems
  # for e.g. gemspec_file is "engines/my-engine/my_engine.gemspec"
  #   dir_name will be engines/my-engine
  #   gem_name will be my_engine

  # Register that engine as a dependency, *without* being required
  gem gem_name, :path => dir_name, :require => false

  # e.g. this is similar to saying
  #  gem 'my_engine', :path => 'engines/my-engine', :require => false
end

现在你已经将所有动态Rails引擎注册为gem依赖项。Bundler将解决它们及其所有子依赖关系,因此您不必担心任何问题。只需在运行应用程序之前或每次添加/删除该文件夹中的任何引擎时运行bundle install一次即可。
好处是,这些gems将仅被注册,而不会被加载。因此,在生产代码中,您现在可以通过简单地说require <your-engine-name>来在运行时加载任何所选的gem。
编辑:额外的代码注释

1
很好,我1.5年前问过这个问题,现在我不再使用Rails了,但我认为这就是我当时正在寻找的东西,它实际上可能会起作用。谢谢。 - maciej-rosiek
1
我不是原帖作者,但我为这个问题开始了悬赏。问题的提出是如何在运行时动态加载引擎,而不是在启动时加载。如果在启动时加载就足够了,那么一个更简单的方法是从boot.rb调用Bundler.load_gemspec。 - Rafael de F. Ferreira
这段代码远未能够动态地加载宝石。 - Nowaker

0

试试这个:

Bundler.with_clean_env do
  # require gems...
end

我之前尝试过,但我不知道是否有遗漏什么,如果我将这行代码添加到 boot.rb 中,我会收到错误提示:'my_gem' 不是 bundle 的一部分。请将其添加到 Gemfile 中。 - maciej-rosiek
你在写代码时所说的 # require gems... 是什么意思?也许这就是我缺失的东西? - maciej-rosiek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接