在Rails 3中运行时加载gem

mac*_*iek 9 ruby rubygems ruby-on-rails bundler ruby-on-rails-3

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

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

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

Sub*_*has 6

你要做的是危险的.如果你的每个Rails引擎都是宝石 - 那么它们也会有其他依赖项的Gemfiles,而这些依赖项还有其他依赖项等.如果你允许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
Run Code Online (Sandbox Code Playgroud)

现在,您已将所有动态Rails引擎注册为gem依赖项.Bundler将解决它们及其所有子依赖关系,因此您不必担心任何事情.只需bundle install在运行应用程序之前运行一次,或者在您添加/删除该文件夹中的任何引擎时运行.

好消息是,这些宝石只会被注册,而不会被加载.因此,在您的生产代码中,您现在只需通过说明即可加载您在运行时选择的任何gemrequire <your-engine-name>

编辑:额外的代码评论