这是一个更令人好奇的问题,而不是问题。当系统上存在多个版本时,使用require
命令时会选择哪些版本?故事的背景是:我在项目(而不是Rails项目)中实现了bundler
gem。我没有问题,但其他开发人员有问题,经过快速调查,我意识到我没有使用
require "bundler/setup"
它基本上装载捆绑的宝石。快速修复,但它让我想知道ruby是如何通过rubygems决定使用哪些宝石的。因为Ruby应用程序使用了其中一个gem的旧版本,而不是新版本,所以代码中断了。这意味着它没有使用"最新"的宝石,那么它背后的逻辑是什么?
更新
为了进一步解释这个问题,假设您有gemfoo-1.0.1
和foo-1.0.2
,当您说require 'foo'
时,ruby如何知道要加载哪一个?
在Ruby中,您require
是文件,而不是宝石。如果在当前加载路径上找不到该文件,Rubygems将在安装的gem中搜索具有该名称的文件,如果找到该文件,则该gem被激活(意味着它被添加到laod路径),然后需要该文件。通常情况下,gem的lib
目录中会有一个同名文件。gem只能激活一个版本。
被激活的gem是可用的最新版本,与任何其他激活的gem兼容。通常情况下,这只意味着安装的最新版本将被激活,但如果您已经激活了一些gem,这些gem声明了对您试图激活的gem的早期版本的依赖关系,则情况可能并非如此。
例如,如果安装了foo-1.0.1
和foo-1.0.2
,那么require 'foo'
(假设它们的lib
目录中有一个名为foo.rb
的文件,而其他gem没有)将导致1.0.2版本被激活。但是,如果您还有一个依赖于1.0.1
的gembar
,那么在激活bar
后调用require 'foo'
将导致激活foo
的1.0.1。
此外,如果你试图在另一个订单require 'foo'; require 'bar';
中要求它们,那么你会得到类似的东西
Gem::LoadError: Unable to activate bar-1, because foo-2 conflicts with foo (= 1)
在这里,您无法激活bar
,这取决于foo
的1.0.1版本,因为您已经激活了foo
的1.0.2版本。
如果没有Bundler,您必须指定所需的每个gem。例如
require 'my_gem'
require 'my_other_gem'
然而,Bundler可以使用Gemfile
使这一点更容易
如果这是您的Gemfile
gem 'my_gem'
gem 'my_other_gem'
调用此将包括所有宝石
require 'bundler/setup'