В чем разница между require_relative и requireв Ruby?
В чем разница между require_relative и requireв Ruby?
Ответы:
Просто посмотрите на документы :
require_relativeдополняет встроенный методrequire, позволяя загружать файл относительно файла, содержащегоrequire_relativeинструкцию.Например, если у вас есть классы модульных тестов в каталоге «test», а данные для них - в каталоге «test / data», то вы можете использовать такую строку в тестовом примере:
require_relative "data/customer_data_1"
require './file.rb'и require_relative 'file.rb'?
require_relativeпозволяет вам «загрузить файл, относящийся к файлу, содержащему require_relativeинструкцию ». С require, ./указывает путь относительно вашего текущего рабочего каталога.
require strвсегда будет искать по каталогам в $ LOAD_PATH. Вы должны использовать, require_relativeкогда файл, который вам нужно загрузить, существует где-то относительно файла, который вызывает загрузку. Резерв requireдля «внешних» зависимостей.
require_relative является удобным подмножеством require
require_relative('path')
равна:
require(File.expand_path('path', File.dirname(__FILE__)))
если __FILE__определено, или оно поднимается LoadErrorиначе.
Это подразумевает, что:
require_relative 'a'и require_relative './a'требует относительно текущего файла ( __FILE__).
Это то, что вы хотите использовать, когда требуется внутри вашей библиотеки, так как вы не хотите, чтобы результат зависел от текущего каталога вызывающей стороны.
eval('require_relative("a.rb")')повышает, LoadErrorпотому что __FILE__не определяется внутри eval.
Вот почему вы не можете использовать require_relativeв тестах RSpec, которые получают evalред.
Следующие операции возможны только с require:
require './a.rb'требует относительно текущего каталога
require 'a.rb'использует для поиска путь ( $LOAD_PATH). Он не находит файлы относительно текущего каталога или пути.
Это невозможно, require_relativeпоскольку в документах говорится, что поиск пути происходит только тогда, когда «имя файла не разрешается до абсолютного пути» (т. Е. Начинается с /или ./или ../), что всегда имеет место для File.expand_path.
Следующая операция возможна с обоими, но вы захотите использовать, requireпоскольку она короче и эффективнее:
require '/a.rb'и require_relative '/a.rb'оба требуют абсолютного пути.Чтение источника
Когда документы не ясны, я рекомендую вам взглянуть на источники (переключать источник в документах). В некоторых случаях это помогает понять, что происходит.
требуется:
VALUE rb_f_require(VALUE obj, VALUE fname) {
return rb_require_safe(fname, rb_safe_level());
}
require_relative:
VALUE rb_f_require_relative(VALUE obj, VALUE fname) {
VALUE base = rb_current_realfilepath();
if (NIL_P(base)) {
rb_loaderror("cannot infer basepath");
}
base = rb_file_dirname(base);
return rb_require_safe(rb_file_absolute_path(fname, base), rb_safe_level());
}
Это позволяет нам сделать вывод, что
require_relative('path')
такой же как:
require(File.expand_path('path', File.dirname(__FILE__)))
так как:
rb_file_absolute_path =~ File.expand_path
rb_file_dirname1 =~ File.dirname
rb_current_realfilepath =~ __FILE__
Из Ruby API :
require_relative дополняет встроенный метод require, позволяя загрузить файл, относящийся к файлу, содержащему оператор require_relative.
Когда вы используете требование загрузки файла, вы обычно получаете доступ к функциональности, которая была правильно установлена и сделана доступной в вашей системе. require не предлагает хорошего решения для загрузки файлов в коде проекта. Это может быть полезно на этапе разработки, для доступа к тестовым данным или даже для доступа к файлам, которые «заблокированы» внутри проекта и не предназначены для внешнего использования.
Например, если у вас есть классы модульных тестов в каталоге «test», а данные для них - в каталоге «test / data», то вы можете использовать такую строку в тестовом примере:
require_relative "data/customer_data_1"Поскольку ни «test», ни «test / data», скорее всего, не находятся в пути к библиотеке Ruby (и по уважительной причине), обычное требование не найдет их. require_relative - хорошее решение для этой конкретной проблемы.
Вы можете включить или опустить расширение (.rb или .so) загружаемого вами файла.
путь должен отвечать to_str.
Вы можете найти документацию по адресу http://extensions.rubyforge.org/rdoc/classes/Kernel.html.
requireдля установленных драгоценных камнейrequire_relativeдля локальных файловrequireиспользует ваш, $LOAD_PATHчтобы найти файлы.
require_relativeиспользует текущее местоположение файла, используя инструкцию
Require зависит от того, что вы установили (например gem install [package]) пакет где-то в вашей системе для этой функции.
При использовании requireвы можете использовать ./формат " " для файла в текущем каталоге, например, require "./my_file"но это не является обычной или рекомендуемой практикой, и вы должны использовать require_relativeвместо этого.
Это просто означает включение файла «относительно местоположения файла с оператором require_relative». Обычно я рекомендую, чтобы файлы находились «внутри» текущего дерева каталогов, а не «вверх», например , не используйте
require_relative '../../../filename'
(до 3 уровней каталогов) в файловой системе, потому что это имеет тенденцию создавать ненужные и хрупкие зависимости. Однако в некоторых случаях, если вы уже «глубоко» в дереве каталогов, тогда может понадобиться «вверх и вниз» другой ветви дерева каталогов. Проще говоря, не используйте require_relative для файлов за пределами этого репозитория (при условии, что вы используете git, который на данный момент является стандартом де-факто, конец 2018 года).
Обратите внимание, что require_relativeиспользуется текущий каталог файла с оператором require_relative (поэтому не обязательно ваш текущий каталог, из которого вы используете команду). Это сохраняет require_relativeпуть «стабильным», так как он всегда будет относиться к файлу, требующему его одинаковым образом.
Лучшие ответы правильные, но глубоко технические. Для новичков в Ruby:
require_relative Скорее всего, будет использоваться для ввода кода из другого файла, который вы написали. например, что если у вас есть данные, ~/my-project/data.rbи вы хотите включить их в ~/my-project/solution.rb? в solution.rbты бы добавилrequire_relative 'data' .
важно отметить, что эти файлы не обязательно должны находиться в одном каталоге. require_relative '../../folder1/folder2/data'также действует.
require скорее всего, будет использоваться для ввода кода из библиотеки, написанной кем-то другим.например, что если вы хотите использовать одну из вспомогательных функций, предоставляемых в active_supportбиблиотеке? вам нужно установить гем с, gem install activesupportа затем в файл require 'active_support'.
require 'active_support/all'
"FooBar".underscore
Сказал иначе
require_relative Требуется файл, специально указанный относительно файла, который его вызывает.
requireтребуется файл, включенный в $LOAD_PATH.
Я только что видел, что в коде RSpec есть некоторые комментарии о том, require_relativeчто O (1) константа и requireO (N) линейно. Так что, вероятно, разница в том, что require_relativeпредпочтительнее, чем require.
require_relativeбыло быстрее, потому что загрузчик не должен пересекать путь загрузки при поиске файла. По сути, require_relativeобеспечивает прямую ссылку.
Я хочу добавить, что при использовании Windows вы можете использовать, require './1.rb'если скрипт запускается локально или с подключенного сетевого диска, но при запуске с UNC- \\servername\sharename\folderпути вам нужно использоватьrequire_relative './1.rb' .
Я не смешиваюсь в обсуждении, которое можно использовать по другим причинам.
$:. См stackoverflow.com/questions/2900370