Jaka jest różnica między wymaganiem a wymaganiem w Ruby?

302

Jaka jest różnica między require_relativei requirew Ruby?

agentbanks217
źródło
9
W wersji wcześniejszej niż 1.9.2 nie było potrzeby wymaganiarelatywnego, ponieważ znajdował się w nim aktualny katalog skryptu $:. Zobacz stackoverflow.com/questions/2900370
Nakilon,
1
wymagany_relatyw wymaga pliku specjalnie wskazanego w stosunku do pliku, który go wywołuje. wymaga wymaga pliku zawartego w $ LOAD_PATH.
Donato
przydatny artykuł o różnicach => medium.com/@ellishim/…
ahmed hamdy

Odpowiedzi:

298

Wystarczy spojrzeć na dokumenty :

require_relativeuzupełnia wbudowaną metodę require, umożliwiając załadowanie pliku względnego do pliku zawierającego require_relativeinstrukcję.

Na przykład, jeśli masz klasy testów jednostkowych w katalogu „test”, a dane dla nich w katalogu testowym „test / data”, możesz użyć takiego wiersza w przypadku testowym:

require_relative "data/customer_data_1"
miku
źródło
28
Czy jest jakaś różnica między require './file.rb'i require_relative 'file.rb'?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
69
@CiroSantilli Tak. require_relativepozwala „załadować plik względny do pliku zawierającego require_relativeinstrukcję ”. Z require, ./wskazuje na ścieżkę, która jest w stosunku do aktualnego katalogu roboczego.
Ajedi32,
16
Myślę, że ważniejsze jest, aby pamiętać, że require strzawsze przeszukuje katalogi w $ LOAD_PATH. Powinieneś użyć, require_relativegdy plik, który chcesz załadować, istnieje gdzieś w stosunku do pliku, który wymaga załadowania. Rezerwa requirena zależności „zewnętrzne”.
rthbound
97

require_relative jest wygodnym podzbiorem require

require_relative('path')

równa się:

require(File.expand_path('path', File.dirname(__FILE__)))

jeśli __FILE__jest zdefiniowane lub rodzi się LoadErrorinaczej.

To daje do zrozumienia ze:

  • require_relative 'a'i require_relative './a'wymagają względem bieżącego pliku ( __FILE__).

    To jest to, czego chcesz użyć, gdy wymagasz w bibliotece, ponieważ nie chcesz, aby wynik zależał od bieżącego katalogu osoby dzwoniącej.

  • eval('require_relative("a.rb")')podnosi, LoadErrorponieważ __FILE__nie jest zdefiniowany w środku eval.

    Dlatego nie można używać require_relativew testach RSpec, które są evaledytowane.

Następujące operacje są możliwe tylko w przypadku require:

  • require './a.rb'wymaga względem bieżącego katalogu

  • require 'a.rb'używa $LOAD_PATHwymaganej ścieżki wyszukiwania ( ). Nie znajduje plików względem bieżącego katalogu lub ścieżki.

    Nie jest to możliwe, require_relativeponieważ dokumenty mówią, że wyszukiwanie ścieżki ma miejsce tylko wtedy, gdy „nazwa pliku nie jest przekształcana na ścieżkę bezwzględną” (tzn. Zaczyna się od /lub ./lub ../), co zawsze ma miejsce File.expand_path.

W obu przypadkach możliwa jest następująca operacja, ale będziesz chciał jej użyć, requireponieważ jest ona krótsza i bardziej wydajna:

  • require '/a.rb'i require_relative '/a.rb'oba wymagają bezwzględnej ścieżki.

Czytanie źródła

Gdy dokumenty nie są jasne, zalecamy zapoznanie się ze źródłami (przełączanie źródła w dokumentach). W niektórych przypadkach pomaga zrozumieć, co się dzieje.

wymagać:

VALUE rb_f_require(VALUE obj, VALUE fname) {
  return rb_require_safe(fname, rb_safe_level());
}

wymagana_relatywna:

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

To pozwala nam dojść do wniosku

require_relative('path')

jest taki sam jak:

require(File.expand_path('path', File.dirname(__FILE__)))

ponieważ:

rb_file_absolute_path   =~ File.expand_path
rb_file_dirname1        =~ File.dirname
rb_current_realfilepath =~ __FILE__
Ciro Santilli
źródło
74

Z Ruby API :

wymagany_relatywny uzupełnia wymaganą przez wbudowaną metodę, umożliwiając załadowanie pliku, który jest względny w stosunku do pliku zawierającego instrukcję Requ_relative.

Kiedy używasz wymaga załadowania pliku, zazwyczaj uzyskujesz dostęp do funkcji, które zostały poprawnie zainstalowane i udostępnione w twoim systemie. Wymagane nie oferuje dobrego rozwiązania do ładowania plików w kodzie projektu. Może to być przydatne na etapie programowania, do uzyskiwania dostępu do danych testowych, a nawet do dostępu do plików „zablokowanych” w projekcie, nieprzeznaczonych do użytku zewnętrznego.

Na przykład, jeśli masz klasy testów jednostkowych w katalogu „test”, a dane dla nich w katalogu testowym „test / data”, możesz użyć takiego wiersza w przypadku testowym:

require_relative "data/customer_data_1" 

Ponieważ ani „test”, ani „test / dane” prawdopodobnie nie znajdują się w ścieżce biblioteki Ruby (i nie bez powodu), normalne wymaganie ich nie znajdzie. Wymagany_relatyw jest dobrym rozwiązaniem tego konkretnego problemu.

Możesz dołączyć lub pominąć rozszerzenie (.rb lub .so) ładowanego pliku.

ścieżka musi odpowiadać na to_str.

Dokumentację można znaleźć na stronie http://extensions.rubyforge.org/rdoc/classes/Kernel.html

svilenv
źródło
50

Podsumowanie

Użyj requiredla zainstalowanych klejnotów

Użyj require_relativedo plików lokalnych

requireużywa twojego $LOAD_PATHdo znalezienia plików.
require_relativeużywa bieżącej lokalizacji pliku za pomocą instrukcji


wymagać

Wymaganie polega na tym, że zainstalowałeś (np. gem install [package]) Pakiet gdzieś w systemie dla tej funkcjonalności.

Podczas korzystania requirety może użyć „ ./” format pliku w bieżącym katalogu, na przykład require "./my_file", ale to nie jest powszechną praktyką i czy zalecana należy użyć require_relativezamiast.

wymaga_relatywnego

Oznacza to po prostu dołączenie pliku „względem położenia pliku z instrukcją Requ_relative”. I na ogół zalecają pliki powinny być „w” bieżącym drzewie katalogów, w przeciwieństwie do „up”, na przykład nie używania

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

(w górę o 3 poziomy katalogów) w systemie plików, ponieważ powoduje to zbędne i kruche zależności. Jednak w niektórych przypadkach, jeśli jesteś już „głęboko” w drzewie katalogów, wówczas może być potrzebna inna gałąź drzewa katalogów. Mówiąc prościej, nie używaj parametru wymagania_relatywnego dla plików poza tym repozytorium (zakładając, że używasz git, który jest w dużej mierze de facto standardem w tym momencie, pod koniec 2018 roku).

Zauważ, że require_relativeużywa bieżącego katalogu pliku z instrukcją requ_relative (więc niekoniecznie twojego bieżącego katalogu, z którego korzystasz z polecenia). Dzięki temu require_relativeścieżka jest „stabilna”, ponieważ zawsze musi być względna w stosunku do pliku wymagającego jej w ten sam sposób.

Michael Durrant
źródło
27

Najważniejsze odpowiedzi są poprawne, ale głęboko techniczne. Dla nowszych do Ruby:

  • require_relative najprawdopodobniej zostanie użyty do wprowadzenia kodu z innego napisanego pliku.

na przykład, co jeśli masz dane ~/my-project/data.rbi chcesz je uwzględnić ~/my-project/solution.rb? w solution.rbdodałeś require_relative 'data'.

ważne jest, aby pamiętać, że te pliki nie muszą znajdować się w tym samym katalogu. require_relative '../../folder1/folder2/data'jest również ważny.

  • require najprawdopodobniej zostanie użyty do wprowadzenia kodu z biblioteki napisanej przez kogoś innego.

na przykład, co jeśli chcesz użyć jednej z funkcji pomocniczych zawartych w active_supportbibliotece? musisz zainstalować klej za pomocą, gem install activesupporta następnie w pliku require 'active_support'.

require 'active_support/all'
"FooBar".underscore

Powiedział inaczej -

  • require_relative wymaga pliku specjalnie wskazanego w stosunku do pliku, który go wywołuje.

  • requirewymaga pliku zawartego w $LOAD_PATH.

jastrząb nocny
źródło
3
Jak mogę zagłosować na tę odpowiedź i doprowadzić ją na sam szczyt, aby każdy odwiedzający tę stronę pytań otrzymał od razu jasną i zrozumiałą odpowiedź, nie psując przy tym swoich mózgów?
TiredOfProgramming
16

Właśnie widziałem, że kod RSpec ma komentarz na temat require_relativestałej O (1) i requireliniowości O (N). Prawdopodobnie różnica polega na tym, że require_relativejest to preferowany niż require.

mech
źródło
1
Ciekawy. Wylądowałem tutaj, szukając informacji na temat porównania prędkości. Myślałem, że require_relativebyło to szybsze, ponieważ moduł ładujący nie musi przechodzić przez ścieżkę ładowania w poszukiwaniu pliku. Zasadniczo require_relativezapewnia bezpośredni link.
Clint Pachl
Wczesne omówienie wymaganej prędkości względnej i dziennika zmian RSpec .
Clint Pachl
1

Chcę dodać, że podczas korzystania z systemu Windows można użyć, require './1.rb'jeśli skrypt jest uruchamiany lokalnie lub z zamapowanego dysku sieciowego, ale gdy jest uruchamiany ze \\servername\sharename\folderścieżki UNC , należy go użyć require_relative './1.rb'.

Nie mieszam się w dyskusji, której użyć z innych powodów.

Piotr
źródło
Chciałem wiedzieć, w jaki sposób require_relative
ładujesz