В чем разница между require_relative и require в Ruby? - PullRequest
289 голосов
/ 09 сентября 2010

В чем разница между require_relative и require в Ruby?

Ответы [ 7 ]

287 голосов
/ 09 сентября 2010

Просто посмотрите на документы :

require_relative дополняет встроенный метод require, позволяя вам загрузить файл, относящийся к файлу, содержащему оператор require_relative.

Например, если у вас есть классы модульных тестов в каталоге «test», а данные для них - в каталоге «test / data», то вы можете использовать такую ​​строку в тестовом примере:

require_relative "data/customer_data_1"
85 голосов

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 ed.

Следующие операции возможны только с require:

  • require './a.rb' требуется относительно текущего каталога

  • require 'a.rb' использует требуемый путь поиска ($LOAD_PATH).Он не находит файлы, относящиеся к текущему каталогу или пути.

    Это невозможно с require_relative, поскольку в документах говорится, что поиск пути происходит только тогда, когда «имя файла не преобразуется в абсолютный путь» (т.е. начинаетсяс / или ./ или ../), что всегда имеет место для File.expand_path.

Следующая операция возможна с обоими, но вы захотите использоватьrequire так как он короче и эффективнее:

  • require '/a.rb' и require_relative '/a.rb' оба требуют абсолютного пути.

Чтение источника

Когда документы не ясны, я рекомендую вам взглянуть на источники (переключить источник в документах).В некоторых случаях это помогает понять, что происходит.

require:

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__
74 голосов
/ 09 сентября 2010

Из Ruby API :

require_relative дополняет встроенный метод требует, позволяя вам загрузить файл, который относится к файл, содержащий require_relative заявление.

При использовании требуется загрузить файл, вы обычно получаете доступ функциональность, которая была правильно установлен и сделан доступным, в ваша система. требуют не предлагает хорошее решение для загрузки файлов в код проекта. Это может быть полезно на этапе разработки, для доступ к тестовым данным, или даже для доступ к файлам, которые «заблокированы» прочь внутри проекта, не предназначен для наружное использование.

Например, если у вас есть юнит-тест классы в каталоге «test», и данные для них под тест каталог "test / data", тогда вы можете используйте такую ​​строку в тестовом примере:

require_relative "data/customer_data_1" 

Так как ни «тест» или «тест / данные», скорее всего, быть в пути библиотеки Ruby (и для хорошая причина), нормальная потребность не будет найдите их. require_relative это хорошо решение этой конкретной проблемы.

Вы можете включить или опустить расширение (.rb или .so) файла, которым вы являетесь загрузка.

путь должен отвечать to_str.

Вы можете найти документацию по http://extensions.rubyforge.org/rdoc/classes/Kernel.html

43 голосов
/ 25 апреля 2015

Резюме

Используйте require для установленных драгоценных камней

Используйте require_relative для локальных файлов

require использует ваш $LOAD_PATH для поиска файлов.
require_relative использует текущее местоположение файла, используя оператор


требуется

Require зависит от того, что вы установили (например, gem install [package]) пакет где-то в вашей системе для этой функции.

При использовании require вы можете использовать формат "./" для файла в текущем каталоге, например, require "./my_file" но это не обычная или рекомендуемая практика, и вы должны использовать require_relative вместо.

require_relative

Это просто означает включение файла «относительно местоположения файла с оператором require_relative». Я обычно рекомендую, чтобы файлы находились "в" текущем дереве каталогов, а не "вверх", например не использовать

require_relative '../../../filename'

(до 3 уровней каталогов) в файловой системе, поскольку это приводит к созданию ненужных и хрупких зависимостей. Однако в некоторых случаях, если вы уже «глубоко» в дереве каталогов, тогда может потребоваться «вверх и вниз» другая ветвь дерева каталогов. Проще говоря, не используйте require_relative для файлов вне этого репозитория (при условии, что вы используете git, который на данный момент является стандартом де-факто в конце 2018 года).

Обратите внимание, что require_relative использует текущий каталог файла с оператором require_relative (поэтому не обязательно ваш текущий каталог, из которого вы используете команду). Это делает путь require_relative «стабильным», так как он всегда будет относиться к файлу, требующему его одинаковым образом.

23 голосов
/ 06 октября 2016

Лучшие ответы правильные, но глубоко технические.Для новичков в Ruby -

  • require_relative, скорее всего, будет использоваться для ввода кода из другого файла, который вы написали.Например,

, что если у вас есть данные в ~/my-project/data.rb, и вы хотите включить их в ~/my-project/solution.rbsolution.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.

14 голосов
/ 04 августа 2014

Я только что увидел, что в коде RSpec есть некоторые комментарии о том, что require_relative является O (1) константой, а require является O (N) линейной.Поэтому, вероятно, разница в том, что require_relative предпочтительнее, чем require.

1 голос
/ 03 февраля 2016

Я хочу добавить, что при использовании Windows вы можете использовать require './1.rb', если скрипт запускается локально или с подключенного сетевого диска, но при запуске из пути к папке UNC \ servername \ sharename \ вам необходимо использовать require_relative './1.rb' Я не смешиваюсь в обсуждении, которое нужно использовать по другим причинам.

...