Это происходило в моей системе, поэтому я немного покопался в ней. Кажется, это несовместимость между Ruby 2.5 и RubyGems <2.6.10. </p>
Краткий ответ
Если вы хотите установить Ruby 2.5, убедитесь, что у вас RubyGems> = 2.6.10. Вы можете явно указать, какую версию RubyGems использовать (например, я назвал rvm rubygems 2.7.7
), или она может просто обновиться до более новой версии RVM / rbenv / и т. Д.
Более длинное объяснение
Как показано в обратном следе в вопросе, ошибка возникает при вызове require
. Это версия require
, которую RubyGems написал для замены определения, поставляемого с Ruby. В RubyGems до 2.6.10 эта часть кода выглядит примерно так:
spec = Gem.find_unresolved_default_spec(path)
if spec
Gem.remove_unresolved_default_spec(spec)
gem(spec.name)
end
( источник )
Ошибка возникает при вызове gem(spec.name)
, но почему?
В конечном итоге это связано с причудой Руби. Хотя require
выглядит как встроенное ключевое слово, на самом деле это метод в модуле Kernel
. Этот модуль включен в Object
, поэтому метод может быть вызван из любого объекта, который происходит от Object
(включая «основной» объект на верхнем уровне скрипта / консоли). Но, в конце концов, это все еще метод для любого объекта, из которого вы вызываете его, поэтому любые вызовы методов в require
, которые не имеют явного получателя, вызываются для того же объекта.
Применяются обычные правила наследования, поэтому, если у вашего объекта нет явного gem
метода, будет вызван метод, определенный в Kernel
RubyGems, и это здорово. Но если у вашего объекта есть собственный метод gem
, он будет вызван вместо этого, что вряд ли сработает. В этом случае require 'fileutils'
вызывается из инициализатора для Gem::Installer
(https://github.com/rubygems/rubygems/blob/v2.6.9/lib/rubygems/installer.rb#L162).. Класс Gem::Installer
имеет собственный метод gem
с нулевыми параметрами, созданный attr_reader :gem
. require
Код пытается вызвать его с одним параметром, и там у нас есть ошибка.
(Эта проблема была решена в RubyGems 2.6.10 путем изменения вызова gem
на Kernel.send(:gem, spec.name)
в https://github.com/rubygems/rubygems/pull/1822. Это было вызвано несколько похожими трудностями в библиотеке Bundler, которая также имела объект, определяющий ее собственный gem
метод.)
Последний вопрос: почему это произошло в Ruby 2.5, но не раньше? Оказывается, этот конкретный вызов gem
происходит только при попытке потребовать гем «по умолчанию». В версиях Ruby до 2.5 "fileutils" не был гемом по умолчанию, поэтому этим версиям удалось избежать этой конкретной проблемы, даже с более старыми версиями RubyGems. Эта странная проблема возникла только в Ruby 2.5, который сделал «fileutils» драгоценным камнем по умолчанию.