ENV["BUNDLE_GEMFILE"] = File.expand_path("../../Gemfile", __FILE__)
Я просто пытаюсь получить доступ к файлу .rb из некоторого каталога, и в учебном руководстве мне предлагается использовать этот код, но я не понимаю, как он находит файл драгоценного камня.
Ответы:
File.expand_path('../../Gemfile', __FILE__)
это несколько уродливая идиома Ruby для получения абсолютного пути к файлу, когда вы знаете путь относительно текущего файла. Другой способ записать это:
File.expand_path('../Gemfile', File.dirname(__FILE__))
оба уродливы, но первый вариант короче. Однако первый вариант также очень неинтуитивен, пока вы не освоите его. Почему лишнее
..
? (но второй вариант может подсказать, зачем он нужен).Вот как это работает:
File.expand_path
возвращает абсолютный путь первого аргумента относительно второго аргумента (который по умолчанию соответствует текущему рабочему каталогу).__FILE__
- это путь к файлу, в котором находится код. Поскольку второй аргумент в этом случае - это путь к файлу иFile.expand_path
предполагает наличие каталога, мы должны добавить в путь дополнительный аргумент,..
чтобы получить правильный путь. Вот как это работает:File.expand_path
в основном реализован следующим образом (в следующем кодеpath
будет иметь значение../../Gemfile
иrelative_to
будет иметь значение/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
(есть
~
еще кое- что, он расширяется до домашнего каталога и так далее - вероятно, есть и другие проблемы с приведенным выше кодом)При пошаговом вызове приведенного выше кода
absolute_path
сначала будет получено значение/path/to/file.rb/../../Gemfile
, затем для каждого раунда в цикле первый..
будет удален вместе с компонентом пути перед ним. Сначала/file.rb/..
снимается, потом на следующем раунде/to/..
снимается, и мы получаем/path/Gemfile
.Короче говоря,
File.expand_path('../../Gemfile', __FILE__)
это уловка, позволяющая получить абсолютный путь к файлу, когда вы знаете путь относительно текущего файла. Дополнительное значение..
в относительном пути - исключить имя файла в__FILE__
.В Ruby 2.0 есть
Kernel
функция,__dir__
которая реализована какFile.dirname(File.realpath(__FILE__))
.источник
File.expand_path('../Gemfile',__dir__)
File.expand_path assumes a directory
, хотя__FILE__
это и не каталог. Чтобы вещи имели смысл использовать,__dir__
который на самом деле является каталогом.Две ссылки:
__FILE__
работает в RubyСегодня я наткнулся на это:
boot.rb коммит в Rails Github
Если вы перейдете на два каталога вверх от boot.rb в дереве каталогов:
/ Railties / lib / рельсы / генераторы / рельсы / приложение / шаблоны
вы видите Gemfile, что заставляет меня думать, что он
File.expand_path("../../Gemfile", __FILE__)
ссылается на следующий файл:/path/to/this/file/../../Gemfile
источник