Ruby\Rubygems他们如何决定加载哪些宝石



这是一个更令人好奇的问题,而不是问题。当系统上存在多个版本时,使用require命令时会选择哪些版本?故事的背景是:我在项目(而不是Rails项目)中实现了bundlergem。我没有问题,但其他开发人员有问题,经过快速调查,我意识到我没有使用

require "bundler/setup"

它基本上装载捆绑的宝石。快速修复,但它让我想知道ruby是如何通过rubygems决定使用哪些宝石的。因为Ruby应用程序使用了其中一个gem的旧版本,而不是新版本,所以代码中断了。这意味着它没有使用"最新"的宝石,那么它背后的逻辑是什么?

更新

为了进一步解释这个问题,假设您有gemfoo-1.0.1foo-1.0.2,当您说require 'foo'时,ruby如何知道要加载哪一个?

在Ruby中,您require文件,而不是宝石。如果在当前加载路径上找不到该文件,Rubygems将在安装的gem中搜索具有该名称的文件,如果找到该文件,则该gem被激活(意味着它被添加到laod路径),然后需要该文件。通常情况下,gem的lib目录中会有一个同名文件。gem只能激活一个版本。

被激活的gem是可用的最新版本,与任何其他激活的gem兼容。通常情况下,这只意味着安装的最新版本将被激活,但如果您已经激活了一些gem,这些gem声明了对您试图激活的gem的早期版本的依赖关系,则情况可能并非如此。

例如,如果安装了foo-1.0.1foo-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'

最新更新