在Rails 3中运行时加载gem

时间:2011-12-13 16:25:03

标签: ruby-on-rails ruby ruby-on-rails-3 rubygems bundler

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

我想要完成的是像往常一样加载我的应用程序,由Bundler加载常规gem。之后我想加载位于特定目录中的所有gem(Rails Engines)(但直到运行时,我不知道那将是什么宝石)。

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

2 个答案:

答案 0 :(得分:6)

你要做的是危险的。如果你的每个Rails引擎都是宝石 - 那么它们也会有Gemfiles和其他依赖项,而那些依赖于其他依赖项等。如果你允许Bundler解决这些问题,那么你在运行时会遇到较少的问题。

这是你如何做到没有任何黑客。请记住,您的Gemfile只是Ruby代码,您可以拥有默认情况下未加载的宝石。

# 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一次,或者在您添加/删除该文件夹中的任何引擎时运行。{/ p>

好消息是,这些宝石只会 注册,而不会被加载。因此,在您的生产代码中,您现在可以通过说require <your-engine-name>

来加载您在运行时选择的任何gem

编辑:额外代码评论

答案 1 :(得分:0)

试试这个:

Bundler.with_clean_env do
  # require gems...
end