Дядьки бородачи, объясните в Ruby отличие require от require_relative. Верной ли дорогой иду.
require # абсолютный путь к файлу.require_relative # относительный путь к файлу.
Есть ли еще какие отличия.
require производит поиск в папках, указанных в $LOAD_PATH (это такая глобальная переменная в Ruby). По порядку, подставляет искомый путь к каждой записи из массива и пытается найти файл. Если нигде нет — LoadError.require_relative производит поиск от текущей папки (файл из которой на данный момент исполняется, видимый в константе __FILE__; не путайте с рабочей папкой, которую можно получить с помощью File.expand_path ".").Абсолютные пути они воспринимают обе и одинаково.
Но с абсолютными путями подобные действия обычно не совершают. Во всяком случае из файлов с кодом (в противоположность REPL вроде irb или pry), т. к. интересующую папку с кодом можно добавить в $LOAD_PATH при старте и "реквайрить" файлы по пути от неё.
Например, в гипотетическом файле /home/user/foo/run.rb мог бы быть такой код:
$LOAD_PATH << File.join(__dir__, "lib") # Добавить лежащую рядом с файлом папку `lib`
require "bar" # Будет последовательно искать `bar.rb` в каждой папке из `$LOAD_PATH`
# Первая строчка требует посмотреть по пути `/home/user/foo/lib/bar.rb`
Отметьте, что если переместить папку foo целиком в другое место, загружаться при выполнении run.rb будет тот же файл. Чего не произошло бы, если бы в файле был зашит абсолютный путь.
require, которым обычно пользуются, не из Ruby, а из RubyGems. RubyGems добавляет поиск указанного гема и добавление папки с его кодом (обычно подпапка lib в геме) в $LOAD_PATH, после чего передаёт управление в обычный require.
RubyGems оставляет исходный require под именем gem_original_require (хотя это может быть деталь реализации), а можно запустить Ruby с ключом --disable-gems и получить оригинальный require на своём месте. Но это очень редко нужно.
На код require из RubyGems можно запросто взглянуть, поставив Pry REPL и сделав в нём:
show-source require
# ИЛИ
$ require # то же самое, но короче