jest nieco brzydkim idiomem Rubiego do pobierania bezwzględnej ścieżki do pliku, gdy znasz ścieżkę względną do bieżącego pliku. Innym sposobem zapisu jest to:
oba są brzydkie, ale pierwszy wariant jest krótszy. Pierwszy wariant jest jednak również bardzo nieintuicyjny, dopóki go nie opanujesz. Dlaczego ekstra ..? (ale drugi wariant może dać wskazówkę, dlaczego jest potrzebny).
Oto jak to działa: File.expand_pathzwraca bezwzględną ścieżkę do pierwszego argumentu względem drugiego argumentu (który domyślnie wskazuje bieżący katalog roboczy). __FILE__to ścieżka do pliku, w którym znajduje się kod. Ponieważ drugi argument w tym przypadku jest ścieżką do pliku i File.expand_pathzakłada katalog, musimy wstawić dodatkową ..ścieżkę, aby uzyskać właściwą ścieżkę. Tak to działa:
File.expand_pathjest zasadniczo zaimplementowany w ten sposób (w poniższym kodzie pathbędzie miał wartość ../../Gemfilei relative_tobędzie miał wartość /path/to/file.rb):
defFile.expand_path(path, relative_to=Dir.getwd)# first the two arguments are concatenated, with the second argument first
absolute_path = File.join(relative_to, path)
while absolute_path.include?('..')
# remove the first occurrence of /<something>/..
absolute_path = absolute_path.sub(%r{/[^/]+/\.\.}, '')
end
absolute_path
end
(jest w tym trochę więcej, rozwija się ~do katalogu domowego i tak dalej - prawdopodobnie są też inne problemy z powyższym kodem)
Przejście przez wywołanie powyższego kodu absolute_pathnajpierw spowoduje pobranie wartości /path/to/file.rb/../../Gemfile, a następnie dla każdej rundy w pętli pierwsza ..zostanie usunięta wraz ze składnikiem ścieżki przed nią. Najpierw /file.rb/..jest usuwany, a następnie w następnej rundzie /to/..jest usuwany i otrzymujemy /path/Gemfile.
Krótko mówiąc, File.expand_path('../../Gemfile', __FILE__)jest sztuczką polegającą na uzyskaniu bezwzględnej ścieżki do pliku, gdy znasz ścieżkę względną do bieżącego pliku. Dodatkowym ..elementem ścieżki względnej jest wyeliminowanie nazwy pliku w formacie __FILE__.
W Ruby 2.0 istnieje Kernelfunkcja o nazwie, __dir__która jest zaimplementowana jako File.dirname(File.realpath(__FILE__)).
Czy jest jakiś powód, dla którego nie powinieneś po prostu używać 'require_relative' innego niż niezgodność z wersją wcześniejszą Ruby 1.9.2?
Danny Andrews
9
Od Ruby 2.0 możesz używaćFile.expand_path('../Gemfile',__dir__)
Phrogz
W tym wierszu Theo w końcu udało mi się kliknąć File.expand_path assumes a directory, mimo że __FILE__nie jest to katalog. Aby rzeczy miały sens, użyj tego, __dir__który w rzeczywistości jest katalogiem.
widzisz Gemfile, co prowadzi mnie do wniosku, że File.expand_path("../../Gemfile", __FILE__)odwołuje się do następującego pliku:/path/to/this/file/../../Gemfile
Odpowiedzi:
File.expand_path('../../Gemfile', __FILE__)
jest nieco brzydkim idiomem Rubiego do pobierania bezwzględnej ścieżki do pliku, gdy znasz ścieżkę względną do bieżącego pliku. Innym sposobem zapisu jest to:
File.expand_path('../Gemfile', File.dirname(__FILE__))
oba są brzydkie, ale pierwszy wariant jest krótszy. Pierwszy wariant jest jednak również bardzo nieintuicyjny, dopóki go nie opanujesz. Dlaczego ekstra
..
? (ale drugi wariant może dać wskazówkę, dlaczego jest potrzebny).Oto jak to działa:
File.expand_path
zwraca bezwzględną ścieżkę do pierwszego argumentu względem drugiego argumentu (który domyślnie wskazuje bieżący katalog roboczy).__FILE__
to ścieżka do pliku, w którym znajduje się kod. Ponieważ drugi argument w tym przypadku jest ścieżką do pliku iFile.expand_path
zakłada katalog, musimy wstawić dodatkową..
ścieżkę, aby uzyskać właściwą ścieżkę. Tak to działa:File.expand_path
jest zasadniczo zaimplementowany w ten sposób (w poniższym kodziepath
będzie miał wartość../../Gemfile
irelative_to
będzie miał wartość/path/to/file.rb
):def File.expand_path(path, relative_to=Dir.getwd) # first the two arguments are concatenated, with the second argument first absolute_path = File.join(relative_to, path) while absolute_path.include?('..') # remove the first occurrence of /<something>/.. absolute_path = absolute_path.sub(%r{/[^/]+/\.\.}, '') end absolute_path end
(jest w tym trochę więcej, rozwija się
~
do katalogu domowego i tak dalej - prawdopodobnie są też inne problemy z powyższym kodem)Przejście przez wywołanie powyższego kodu
absolute_path
najpierw spowoduje pobranie wartości/path/to/file.rb/../../Gemfile
, a następnie dla każdej rundy w pętli pierwsza..
zostanie usunięta wraz ze składnikiem ścieżki przed nią. Najpierw/file.rb/..
jest usuwany, a następnie w następnej rundzie/to/..
jest usuwany i otrzymujemy/path/Gemfile
.Krótko mówiąc,
File.expand_path('../../Gemfile', __FILE__)
jest sztuczką polegającą na uzyskaniu bezwzględnej ścieżki do pliku, gdy znasz ścieżkę względną do bieżącego pliku. Dodatkowym..
elementem ścieżki względnej jest wyeliminowanie nazwy pliku w formacie__FILE__
.W Ruby 2.0 istnieje
Kernel
funkcja o nazwie,__dir__
która jest zaimplementowana jakoFile.dirname(File.realpath(__FILE__))
.źródło
File.expand_path('../Gemfile',__dir__)
File.expand_path assumes a directory
, mimo że__FILE__
nie jest to katalog. Aby rzeczy miały sens, użyj tego,__dir__
który w rzeczywistości jest katalogiem.Dwie referencje:
__FILE__
działa w RubimNatknąłem się na to dzisiaj:
boot.rb commit w Rails Github
Jeśli przejdziesz do dwóch katalogów w górę z boot.rb w drzewie katalogów:
/ railties / lib / rails / generators / rails / app / templates
widzisz Gemfile, co prowadzi mnie do wniosku, że
File.expand_path("../../Gemfile", __FILE__)
odwołuje się do następującego pliku:/path/to/this/file/../../Gemfile
źródło