Яка різниця між Requ_relative і вимогою в Ruby?


302

У чому різниця між require_relativeі requireв Ruby?


9
До 1.9.2 не було необхідності в Requ_relative, тому що поточний каталог сценарію був у $:. Див stackoverflow.com/questions/2900370
Nakilon

1
Requ_relative вимагає файл, спеціально вказаний на відносно файлу, який його викликає. вимагає потрібний файл, включений у $ LOAD_PATH.
Донато

корисна стаття про відмінності => medium.com/@ellishim/…
ahmed hamdy

Відповіді:


298

Подивіться на документи :

require_relativeдоповнює вбудований метод require, дозволяючи завантажити файл, який відносно файлу, що містить require_relativeоператор.

Наприклад, якщо у каталозі "тест" є одиничні тестові класи та дані для них у тестовому каталозі "тест / дані", ви можете використовувати такий рядок у тестовому випадку:

require_relative "data/customer_data_1"

28
Чи є різниця між require './file.rb'і require_relative 'file.rb'?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

69
@CiroSantilli Так. require_relativeдозволяє "завантажити файл, який відносно файлу, що містить require_relativeзаяву ". З require, ./вказує шлях, який відповідає вашому поточному робочому каталогу.
Ajedi32

16
Я думаю, що важливіше зазначити, що require strзавжди буде шукати каталоги в $ LOAD_PATH. Ви повинні використовувати, require_relativeколи файл, який потрібно завантажити, існує десь відносно файлу, який вимагає завантаження. Резерв requireдля "зовнішніх" залежностей.
rthbound

97

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());
}

Requ_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

Від API Ruby :

Requ_relative доповнює вбудований метод вимагає, дозволяючи завантажувати файл, який відносно файлу, що містить оператор requ_relative.

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

Наприклад, якщо у каталозі "тест" є одиничні тестові класи та дані для них у тестовому каталозі "тест / дані", ви можете використовувати такий рядок у тестовому випадку:

require_relative "data/customer_data_1" 

Оскільки "тест" і "тест / дані", ймовірно, не знаходяться на шляху бібліотеки Рубі (і з поважних причин), звичайна вимога їх не знайде. Requ_relative є хорошим рішенням для цієї конкретної проблеми.

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

шлях повинен відповідати to_str.

Ви можете знайти документацію на веб-сайті http://extensions.rubyforge.org/rdoc/classes/Kernel.html


50

Підсумок

Використовуйте requireдля встановлених дорогоцінних каменів

Використовувати require_relativeдля локальних файлів

requireвикористовує ваш, $LOAD_PATHщоб знайти файли.
require_relativeвикористовує поточне розташування файлу за допомогою оператора


вимагають

Вимоги покладаються на те, що ви встановили (наприклад gem install [package]) пакет десь у вашій системі для цієї функції.

При використанні requireви можете використовувати " ./" формат для файлу в поточному каталозі, наприклад, require "./my_file"але це не є звичайною або рекомендованою практикою, і вам слід скористатися require_relativeнатомість.

вимагають відносних

Це просто означає, що включіть файл "відносно місця розташування файлу із заявою Requ_relative". Я зазвичай рекомендую, щоб файли знаходилися "в" поточному дереві каталогів на відміну від "вгору", наприклад , не використовувати

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

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

Зауважте, що require_relativeвикористовується поточний каталог файлу із заявою Requ_relative (тому не обов'язково ваш поточний каталог, з якого ви використовуєте команду). Це зберігає require_relativeшлях "стабільним", оскільки він завжди має відношення до файлу, який вимагає його однаково.


27

Верхні відповіді правильні, але глибоко технічні. Для тих, хто новіший до Рубі:

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


3
Як я можу проголосувати за цю відповідь і довести її до вершини, тож кожен відвідувач цієї сторінки питань одразу отримає чітку і зрозумілу відповідь, не порушуючи їх мізки?
TiredOfProgramming

16

Я щойно бачив, що код RSpec має коментар щодо require_relativeтого, що він O (1) постійний і requireO (N) лінійний. Тому, ймовірно, різниця полягає в тому, що require_relativeє кращим require.


1
Цікаво. Я приземлився тут, шукаючи інформацію про порівняння швидкості. Думаю, що це require_relativeбуло швидше, тому що завантажувач не повинен проходити шлях завантаження в пошуках файлу. По суті, require_relativeзабезпечує пряме посилання.
Клінт Пахл

Раннє обговорення питання про швидкість Requ_relative та протокол змін RSpec .
Клінт Пахл

1

Хочу додати, що при використанні Windows ви можете використовувати, require './1.rb'якщо скрипт виконується локально або з картографічного мережевого накопичувача, але при запуску зі \\servername\sharename\folderшляху UNC, який потрібно використовувати require_relative './1.rb'.

Я не втручаюся в дискусію, яку використовувати з інших причин.


Я хотів би знати , як ви завантажили require_relativeфайл Чи не могли б ви кинути ідею в цьому stackoverflow.com/questions/43487784 / ...
Emjey
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.