根据日期或 Ruby 版本设置 Ruby 环境
Posted
技术标签:
【中文标题】根据日期或 Ruby 版本设置 Ruby 环境【英文标题】:Setup Ruby environment based on date or Ruby version 【发布时间】:2021-08-24 15:19:51 【问题描述】:出于测试目的,我想安装一个基于过去日期的 Ruby 环境。例如,Ruby 2.5.0p0 于 2017 年 12 月 25 日发布,在某处我读到 Rails 5.2.6 是使用它的版本。我想要的是一种编程方式来了解 gem 的版本/日期应该与什么版本的 Ruby 一起使用。我错过了一些超级简单的方法吗?
编辑:
我在某个日期就已经存在的 Ruby 环境中进行测试的想法似乎很难处理,而且可能没有必要。所以我要做的是运行几个主要的 Ruby 版本并安装它们的 best Rails versions 并让所有其他 gem 浮动到任何版本。
Ruby Rails
2.5.0 5.2.6
2.5.9 5.2.6
2.6.7 6.0.3.7
2.7.3 6.0.3.7
3.0.1 latest
【问题讨论】:
Rails 维护了每个主要 Rails 版本支持的Ruby Versions 的官方列表。 这是基于一个错误的假设,即 gem 上只有一个版本可以与某个版本的 Ruby 配合使用。现实并非如此——相反,您可以通过使用 bundler 或 rubygems.org API 获得给定 Ruby 版本的兼容 gem 版本列表。 @max,您能否提供一个示例代码行来生成“给定 Ruby 版本的兼容 gem 版本列表”? @oaklodge 如果您查看random gem onrubygems.org
,您可能会看到它的内容类似于:REQUIRED RUBY VERSION: >= 2.5.0
。 bundler
使用此信息,然后为项目安装依赖项。
换句话说,例如,您不能将 ruby 2.4 与 nokigiri 1.11.7 一起使用。但是您也不需要知道/关心哪个是支持 ruby 2.4 的最新版本的 nokogiri,因为 bundler 会自动为您找出答案!
【参考方案1】:
Rails 和所有其他 gem 可以声明最低要求的 ruby 版本。运行 bundle update
时会自动考虑这一点。
但是,有两个问题:
库作者并不总是完美地做到这一点 - 因此,您可能会使用古老的 ruby 版本运行现代 gem,并且只在运行时发现不兼容。
图书馆作者无法预测未来;他们可能会正确指定 最低 所需的 ruby 版本,但他们不可能提前知道 最大 兼容的 ruby 版本。
但是,有一线希望:Ruby 非常擅长向后兼容。因此,除非您尝试使用古老的库和现代 ruby 运行一个大型项目(例如,使用 ruby 2.7 的 rails 4 项目),否则您不太可能在这里遇到很多问题。
而且,正如我在上面所建议的,这可能只是 大型 gems 的问题,例如 rails 框架。 It's fairly well documented which minimum version of ruby is supported by each major rails release:
Rails 7 需要 Ruby 2.7.0 或更高版本。
Rails 6 需要 Ruby 2.5.0 或更高版本。
Rails 5 需要 Ruby 2.2.2 或更高版本。
【讨论】:
根据我的经验,大多数 Ruby 不兼容问题都与依赖于外部库(如 Nokogiri)的 gem 相关(以及 1 Infinite Loop 的 schenanigans)。【参考方案2】:我想要的是一种编程方式来了解 gem 的版本/日期 应该使用什么版本的 Ruby。
一种方法是使用the API provided by RubyGems.org:
# run with ruby get_versions.rb gemname rubyversion
require 'json'
require 'uri'
require 'net/http'
require 'pp'
gemname = ARGV[0] || 'rails'
uri = URI("https://rubygems.org/api/v1/versions/#gemname.json")
target_ruby_version = Gem::Version.new(ARGV[1] || '2.7.0')
puts "getting #uri"
response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
puts '...'
request = Net::HTTP::Get.new uri
http.request(request)
end
# error handling is boring so lets just assume this will always work
json = JSON.parse(response.body)
compatible = json.each_with_object() do |gem_version, hash|
hash[gem_version["number"]] = gem_version["ruby_version"]
end.select do |gemv, rubyv|
Gem::Requirement.new(rubyv)
.satisfied_by?(target_ruby_version)
end
puts "The following versions of #gemname satifisy the Ruby requirement #target_ruby_version:"
pp compatible.keys
但是,它在测试 gem 是否与给定版本的 Ruby 真正兼容时的实际用处是非常值得怀疑的。由于作者通常不指定 ruby 版本的范围,它只会告诉您给定的 Ruby 版本是否满足最低版本要求。 Tom Lord 很好地描述了为什么这是有问题的。
您在 Ruby 2.7.0 上运行 Rails 0.8.0 的体验可能会有所不同。
【讨论】:
以上是关于根据日期或 Ruby 版本设置 Ruby 环境的主要内容,如果未能解决你的问题,请参考以下文章
如何为项目设置特定的 Ruby 版本(无 rvm 和 rbenv)
使用 rvmrc 或 ruby-version 文件使用 RVM 设置项目 gemset?