Ruby 捆绑器 - 同一 gemfile 中的多个 Ruby 版本

Ruby Bundler - Multiple Ruby versions in the same gemfile

我在 macOS 上使用 rbenvbundler

我需要为我的应用程序维护 Ruby 的多个版本。特别是 2.2.4 和 2.5.5。不同的用户会有不同的版本。

目前我只使用 2.2.4,所以我执行以下操作。我的 gemfile 看起来像这样

source "https://rubygems.org"
ruby '2.2.4'

gem "net-ssh", "4.1.0"
gem "net-scp", "2.0.0"
.....

安装我 运行 bundle install 然后用我的应用程序部署我 运行

bundle install --deployment --path src/mct-tools/ext/gems

这会在我的应用程序中生成一个文件夹 src/mct-tools/ext/gems/ruby/2.2.0,然后我会分发该文件夹。

现在我想添加 ruby 2.5.5 和更新的 gem,所以我想知道是否可以接受像这样的 gemfile

source "https://rubygems.org"
ruby '2.2.4'

gem "net-ssh", "4.1.0"
gem "net-scp", "2.0.0"
.....

ruby '2.5.5'

gem "net-ssh", "6.1.0"
gem "net-scp", "3.0.0"
.....

这样当我使用 bundle install --deployment --path src/mct-tools/ext/gems 部署时,这两个版本就会添加到 gems 文件夹中。

这是正确的做法吗?另一种方法是为每个版本指定两个不同的 gemfile,然后在它们之间切换。

Gemfiles 声明依赖关系

Gemfile 在 Ruby 版本上声明 依赖关系 ,有或没有 semantic versioning 约束。它并不意味着控制您的应用程序的多个构建目标。它只是强制您的 app/gem 可用的 Ruby 版本是您定义的任何版本。例如:

# Will fail if run with a different RUBY_VERSION.
ruby '2.2.4'

# Allows RUBY_VERSION >= 2.2.4, but <= 2.3.
ruby '~> 2.2.4'

# Allows either Ruby 2.2.4+ or 2.5.5+, with
# a minimum (but no maximum) patch version.
ruby '~> 2.2.4', '~> 2.5.5'

但是,它不会安装给定的 Ruby,也不会在 运行 bundler install 时引发错误和 non-zero 退出状态。您需要采用不同的方法来测试多个目标。

使用持续集成(CI)工具更改构建目标

如果您使用的是外部 CI,例如 TravisCI,您可以创建一个 build matrix 来针对多个 Ruby 版本进行测试。是完全删除 Ruby 版本限制,还是指定受支持的范围,由您决定。利用您的 CI 工具针对您计划支持的 Ruby 版本进行构建确实是最好的方法,但是,无论您是否将 Ruby 运行时限制在 Gemfile 中。

例如,您可以在 travis.yml 中使用矩阵,如下所示:

language: ruby
rvm:
  - 2.2.4
  - 2.5.5

切换 Gemfiles

如果你坚持按照你的方式去做,在你的 Gemfile 中允许一个单一的 Ruby 版本,那么你可能会考虑在你的源代码树中有两个不同名称的独立 gemfile,例如作为 Gemfile-2.2.4 和 Gemfile-2.5.5。然后,您可以指定要与 Bundler's --gemfile flag 一起使用的 Gemfile,或者通过将自定义 Gemfile 符号链接到项目的规范 Gemfile

这里有一些要考虑的例子:

# Resolve against a specific Gemfile with
# hard-coded Ruby version.

$ ls Gemfile*
Gemfile-2.2.4  Gemfile-2.5.5

$ bundle install --gemfile="Gemfile-2.2.4"
# Resolve against whatever custom file is
# symlinked to your ./Gemfile.

$ ln -sf Gemfile{-2.5.5,}

$ ls -F Gemfile*
Gemfile@       Gemfile-2.2.4  Gemfile-2.5.5

$ bundle install

这两种方法都有效,但前者更灵活,代价是每次都需要指定您选择的 Gemfile,而后者在您的 development/testing 工作流程不支持 Bundler 的 --gemfile旗帜。

与 Ruby 经理一起更换红宝石

如果您在开发中有多个 Ruby 版本,最佳做法是使用版本管理器,例如 rvm、rbenv 或 chruby。您可以使用版本管理器根据需要手动来回更改红宝石。

您还可以检查您的版本管理器是否在 .ruby-version 或其他配置文件上支持 auto-switching。每次要针对不同的 Ruby 构建或测试时,您仍然需要更新该文件,但您不必不断更改 Gemfile 内容、re-pointing Gemfile 符号链接或更新每次调用 Bundler 时都有一个标志。

任何给定的方法是否优于其他方法将取决于您的工作流程。没有适合所有情况的技术解决方案,因此您的里程可能会有所不同。