2009-05-07 12 views
79

Widziałem dwie powszechnie używane techniki dodawania katalogu aktualnie wykonywanego pliku do $ LOAD_PATH (lub $ :). Widzę zalety robienia tego w przypadku, gdy nie pracujesz z klejnotem. Jeden wydaje się bardziej gadatliwy niż drugi, oczywiście, ale czy istnieje powód, by iść z jednym nad drugim?

Pierwszy rozwlekły sposób (może być przesadą):

$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) unless $LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__))) 

i bardziej proste, szybkie i-brudny:

$:.unshift File.dirname(__FILE__) 

jakikolwiek powód, aby przejść z jednego nad drugim?

+1

A ** ** nieco mniej gadatliwy wersja gadatliwym jeden jest. 'File.expand_path (File.dirname (__ __ FILE)) {dotknij | pwd | $ LOAD_PATH.unshift (PWD), chyba $ LOAD_PATH.include? (PWD)} ' –

+0

jak o klauzuli "o ile"? Jak oba powyższe mogą być równoważne? – inger

+0

Jako ktoś, kto przyszedł tutaj, aby spróbować zrozumieć, jak tego użyć, jest to bardzo tajemnicze. Nie widzę, skąd nazwa katalogu pochodzi z przykładów. Byłbym wdzięczny, gdyby ktoś mógł to wyjaśnić. – SlySherZ

Odpowiedz

47

Powiedziałbym, żebym poszedł z $:.unshift File.dirname(__FILE__) z drugiej strony, po prostu dlatego, że widziałem o wiele więcej wykorzystania go w kodzie niż $LOAD_PATH, a także jest krótszy!

+0

Kiedy zaczynałem od Ruby, oczywiście myślałem, że $ LOAD_PATH jest lepsze. Ale gdy już ukończysz status początkującego, użyłbym tylko $ LOAD_PATH, jeśli próbowałem uczynić mój kod bardziej czytelnym dla początkującego. Meh to kompromis. To zależy od tego, jak "publiczny" jest kod, o ile użycie pamięci jest takie samo dla każdego, co, jak przypuszczam, jest w istocie. –

+0

Co powiesz na sprawdzenie, czy $: zawiera już wpis? – inger

+4

W zależności od stylu, który obserwujesz w projekcie. Popularna [Ruby Style Guide] (https://github.com/bbatsov/ruby-style-guide#syntax) mówi „Unikaj używania zmiennych Perl stylu specjalnych (takich jak $ :, $ ;, itd.) Są one dość tajemnicze, a ich stosowanie w skryptach zawierających tylko jedną linijkę jest odradzane. " – bobmagoo

18

Nie przepadam za "szybkim i brudnym" sposobem. Wszyscy nowi w Ruby będą zastanawiać się, co to jest $:..

Uważam, że jest to bardziej oczywiste.

libdir = File.dirname(__FILE__) 
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir) 

Lub jeśli dbam o posiadaniu pełnej ścieżki ...

libdir = File.expand_path(File.dirname(__FILE__)) 
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir) 

UPDATE 2009/09/10

jak późno Robiłem co następuje:

$:.unshift(File.expand_path(File.dirname(__FILE__))) unless 
    $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__))) 

Widziałem to w całej masie różnych projektów ruby, podczas gdy wiosłując GitHub.

Wydaje się być konwencją?

+0

@LukeAntins, to jest naprawdę świetne, ale gdzie powinienem "załadować" load_path w aplikacji? – gaussblurinc

+0

@gaussblurinc Gdzieś "blisko szczytu" twojej biblioteki/aplikacji, ale to naprawdę zależy. Gdybyś miał plik 'bin', który zawsze był względny w stosunku do twojego' code' i byłby kiedykolwiek uruchamiany przez plik 'bin' ... bootstrap w bin.Jeśli masz bibliotekę, to bootstrap na górze to kod biblioteki jak w 'lib/code.rb', aby uzyskać dostęp do wszystkiego pod' lib/code/'. Mam nadzieję, że to wędrowanie pomoże! –

+0

RuboCop informuje mnie, że '__dir__' może być użyty do uzyskania ścieżki do katalogu bieżącego pliku. – Raphael

136

Ścieżka ładowania Rubiego jest bardzo często opisywana jako $:, ale tylko dlatego, że jest krótka, nie czyni jej lepszym. Jeśli wolisz jasność od sprytu, lub jeśli zwięzłość ze względu na nią wzmaga swędzenie, nie musisz tego robić tylko dlatego, że wszyscy inni. Pozdrów ...

$LOAD_PATH 

... i pożegnać ...

# I don't quite understand what this is doing... 
$: 
+25

Ponadto, Google jest trudniejsze w przypadku ciągów takich jak "$:", które zawierają tylko symbole. – DSimon

+35

@ DSimon Nie * Google * dla '$:', użyj http://www.symbolhound.com/ – Sparhawk

7

Jeśli wpiszesz script/console w projekcie Rails i wprowadź $:, dostaniesz tablicę obejmuje wszystkie katalogi potrzebne do załadowania Rubiego. Zabranie tego małego ćwiczenia polega na tym, że $: jest tablicą. W związku z tym można na nim wykonywać funkcje, takie jak tworzenie innych katalogów za pomocą metody unshift lub operatora <<. Jak sugerujesz w swoim oświadczeniu $: i $LOAD_PATH są takie same.

Wadą w tym szybkim i brudnym sposobie, o którym wspomniałeś, jest to, że: jeśli już posiadasz katalog w ścieżce rozruchowej, to się powtórzy.

Przykład:

Mam plugin utworzonego nazwie todo. Mój katalog jest skonstruowany w taki sposób:

 
/---vendor 
    | 
    |---/plugins 
     | 
     |---/todo 
       | 
       |---/lib 
        | 
        |---/app 
          | 
          |---/models 
          |---/controllers 
       | 
       |---/rails 
        | 
        |---init.rb 

W pliku init.rb wszedłem następujący kod:

## In vendor/plugins/todo/rails/init.rb 
    %w{ models controllers models }.each do |dir| 
     path = File.expand_path(File.join(File.dirname(__FILE__), '../lib', 'app', dir)) 
     $LOAD_PATH << path 
     ActiveSupport::Dependencies.load_paths << path 
     ActiveSupport::Dependencies.load_once_paths.delete(path) 
    end 

zauważyć, jak mówię blok kodu do wykonywania czynności wewnątrz bloku do strun "modele", "kontrolery" i "modele", w których powtarzam "modele". (FYI, %w{ ... } to kolejny sposób, aby powiedzieć Ruby, aby trzymał tablicę łańcuchów). Kiedy uruchamiam script/console, I wpisz:

>> puts $: 

I wpisać to tak, że łatwiej jest odczytać zawartość w ciągu. Wyjście pojawia się:

 
... 
... 
./Users/Me/mySites/myRailsApp/vendor/plugins/todo/lib/app/models 
./Users/Me/mySites/myRailsApp/vendor/plugins/todo/lib/app/controllers 
./Users/Me/mySites/myRailsApp/vendor/plugins/todo/lib/app/models 

Jak widać, choć jest to tak proste, przykładem może utworzyć podczas korzystania projekt Obecnie pracuję dalej, jeśli nie jesteś ostrożny szybki i brudny sposób doprowadzi do powtarzających się ścieżek. Dłuższy sposób sprawdzi powtarzające się ścieżki i upewni się, że nie występują.

Jeśli jesteś doświadczonym programistą Rails, prawdopodobnie masz bardzo dobry pomysł, co robisz i prawdopodobnie nie popełnia błąd powtarzając ścieżek. Jeśli jesteś nowicjuszem, wybrałbym dłuższą drogę, dopóki nie zrozumiesz, co naprawdę robisz.

+0

Twoja odpowiedź jest bardzo pomocna i dobrze wyjaśniona. Sugerowana edycja: metoda 'load_paths' oraz' load_once_paths.delete' zostały uznane za przestarzałe. Pomożemy zaktualizować wiersze, które się do nich odnoszą: 'ActiveSupport :: Dependencies.autoload_paths << ścieżka' ' ActiveSupport :: Dependencies.autoload_once_paths.delete (ścieżka) ' – Uzzar

4

Najlepszy mam natknąć dodawania dir poprzez ścieżki względnej podczas używania RSpec. Uważam, że jest wystarczająco gadatliwy, ale nadal jest niezły.

$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) 
Powiązane problemy