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

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

Ответ 1

Просто посмотрите docs:

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

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

require_relative "data/customer_data_1"

Ответ 2

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' оба требуют абсолютного пути.

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

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

требуется:

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__

Ответ 3

В Ruby API:

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

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

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

require_relative "data/customer_data_1" 

Поскольку ни "тест" или "тест/данные", скорее всего, быть в пути библиотеки Rubys (и для хорошая причина), нормальный требует Найди их. require_relative - хороший решение этой конкретной проблемы.

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

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

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

Ответ 4

require использует текущий каталог, из которого вы запускаете программу из

require_relative использует каталог, в котором находится сама программа.

Например, если программа находится в ~/code и называется 1.rb, и вы сделали cd в этом каталоге

cd ~/code

и вы пытаетесь запустить рубиновую программу с помощью

ruby 1.rb

затем внутри 1.rb

require './2.rb'
require_relative '3.rb'

оба будут работать.

Однако, если вы находитесь в другом каталоге, скажите

cd ~/tmp

и вы пытаетесь запустить программу с помощью

ruby ../1.rb

тогда вы получите сообщение об ошибке, например

/home/durrantm/.rvm/rubies/ruby-2.1.2/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/kernel_require.rb:54:in `require': cannot load such file -- ./2.rb (LoadError)
    from /home/durrantm/.rvm/rubies/ruby-2.1.2/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/kernel_require.rb:54:in `require'
    from ../1.rb:1:in `<main>'

при попытке использовать

require './2.rb'

тогда как

require_relative '3.rb'

все еще работает нормально _ потому что ссылка (до 3.rb) относится к тому каталогу, в котором находится программа (1.rb).

Ответ 5

Лучшие ответы правильные, но глубоко технические. Для тех, кто новичок в 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.

Ответ 6

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

Ответ 7

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