ENV["BUNDLE_GEMFILE"] = File.expand_path("../../Gemfile", __FILE__)
Estou apenas tentando acessar um arquivo .rb de algum diretório e um tutorial está me dizendo para usar este código, mas não vejo como ele encontra o arquivo gem.
ENV["BUNDLE_GEMFILE"] = File.expand_path("../../Gemfile", __FILE__)
Estou apenas tentando acessar um arquivo .rb de algum diretório e um tutorial está me dizendo para usar este código, mas não vejo como ele encontra o arquivo gem.
Respostas:
File.expand_path('../../Gemfile', __FILE__)
é um idioma Ruby um tanto feio para obter o caminho absoluto para um arquivo quando você conhece o caminho relativo ao arquivo atual. Outra maneira de escrever é esta:
File.expand_path('../Gemfile', File.dirname(__FILE__))
ambos são feios, mas a primeira variante é mais curta. A primeira variante, no entanto, também é muito não intuitiva até que você pegue o jeito. Por que o extra ..? (mas a segunda variante pode dar uma pista de por que é necessário).
Funciona assim: File.expand_pathretorna o caminho absoluto do primeiro argumento, relativo ao segundo argumento (que é padronizado para o diretório de trabalho atual). __FILE__é o caminho para o arquivo em que o código está. Como o segundo argumento, neste caso, é um caminho para um arquivo e File.expand_pathassume um diretório, temos que inserir um item extra ..no caminho para obter o caminho correto. É assim que funciona:
File.expand_pathé basicamente implementado assim (no código a seguir pathterá o valor de ../../Gemfilee relative_toterá o valor de /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
(há um pouco mais, ele se expande ~para o diretório inicial e assim por diante - provavelmente também há alguns outros problemas com o código acima)
Percorrer uma chamada para o código acima absolute_pathobterá primeiro o valor e /path/to/file.rb/../../Gemfile, em seguida, para cada rodada no loop, a primeira ..será removida, junto com o componente de caminho antes dela. Primeiro /file.rb/..é removido, então na próxima rodada /to/..é removido e nós obtemos /path/Gemfile.
Para encurtar a história, File.expand_path('../../Gemfile', __FILE__)é um truque para obter o caminho absoluto de um arquivo quando você conhece o caminho relativo ao arquivo atual. O extra ..no caminho relativo é eliminar o nome do arquivo em __FILE__.
No Ruby 2.0, existe uma Kernelfunção chamada __dir__que é implementada como File.dirname(File.realpath(__FILE__)).
File.expand_path('../Gemfile',__dir__)
File.expand_path assumes a directory, embora __FILE__não seja um diretório. Para que as coisas façam sentido, use o __dir__que na verdade é um diretório.
Duas referências:
Me deparei com isso hoje:
boot.rb commit no Rails Github
Se você subir dois diretórios de boot.rb na árvore de diretórios:
/ railties / lib / rails / generators / rails / app / templates
você vê Gemfile, o que me leva a acreditar que faz File.expand_path("../../Gemfile", __FILE__)referência ao seguinte arquivo:/path/to/this/file/../../Gemfile