Reputation: 8055
I'm not sure I understand the order in which operations are done with File.expand_path
. Below is an example pry
session:
[1] pry(main)> File.expand_path('.')
=> "/Users/max/Dropbox/work/src/github.com/mbigras/foobie"
[2] pry(main)> File.expand_path('..')
=> "/Users/max/Dropbox/work/src/github.com/mbigras"
[3] pry(main)> File.expand_path('..', "cats")
=> "/Users/max/Dropbox/work/src/github.com/mbigras/foobie"
[4] pry(main)> File.expand_path('..', __FILE__)
=> "/Users/max/Dropbox/work/src/github.com/mbigras/foobie"
[5] pry(main)> File.expand_path('../lib', __FILE__)
=> "/Users/max/Dropbox/work/src/github.com/mbigras/foobie/lib"
[7] pry(main)> File.expand_path('./lib')
=> "/Users/max/Dropbox/work/src/github.com/mbigras/foobie/lib"
[8] pry(main)> File.expand_path('./lib', __FILE__)
=> "/Users/max/Dropbox/work/src/github.com/mbigras/foobie/(pry)/lib"
[9] pry(main)>
[1]
makes sense, I'm expanding the path of the current working directory.
[2]
makes sense, I'm expanding the path of the parent directory of the cwd
[3]
doesn't make sense, I accept from reading another answer that for some reason ruby implicitly takes the File.dirname
of the second arg and in the case of File.dirname('cats')
it expands to the cwd .
because 'cats'
isn't nested. But then why doesn't File.expand_path('..', '.')
have the same result?
[18] pry(main)> File.expand_path('..', 'cats')
=> "/Users/max/Dropbox/work/src/github.com/mbigras/foobie"
[19] pry(main)> File.dirname('cats')
=> "."
[20] pry(main)> File.expand_path('..', '.')
=> "/Users/max/Dropbox/work/src/github.com/mbigras"
[4]
doesn't make sense but for the same reason as [3]
. In this case the "random string" is "(pry)"
because p __FILE__ #=> "(pry)"
while inside a pry session.
[5]
doesn't make sense, why would File.expand_path
go to seemingly noone's parent directory and then magically come back to the cwd and decide to go into lib
[7]
makes sense, but doesn't help me understand [5]
[8]
doesn't make sense, why is the "random string" now wedged between the cwd .
and lib
From the docs:
File.expand_path("../../lib/mygem.rb", __FILE__)
#=> ".../path/to/project/lib/mygem.rb"
So first it resolves the parent of __FILE__, that is bin/, then go to the parent, the root of the project and appends lib/mygem.rb.
The order of operations doesn't really add up to me.
File.dirname(__FILE__)
Steps 2 and 3 don't help. Why are we going to the parent? Why did we even do Step 1 in the first place? Why is there ../..
? Doesn't that mean go two levels up from the current working directory?
Would love some guiding principles to understand these examples.
Edit to add the Gold:
File.expand_path
goes to the first parameter from the directory specified by the second parameter (Dir.pwd
if not present). - Eric Duminil
Upvotes: 1
Views: 3915
Reputation: 54223
I think you missed a ..
while reading the answer you link to.
No File.dirname
is ever done implicitely by expand_path
.
File.expand_path('../../Gemfile', __FILE__)
# ^^ Note the difference between here and
# vv there
File.expand_path('../Gemfile', File.dirname(__FILE__))
What confused me at first was that the second parameter is always considered to be a directory by File.expand_path
, even if it doesn't exist, even if it looks like a file or even if it is an existing file.
File.expand_path
goes to the first parameter from the directory specified by the second parameter (Dir.pwd
if not present).
File.expand_path('..', "cats")
It is executed in the current directory, which is "/Users/max/Dropbox/work/src/github.com/mbigras/foobie"
.
Is cats
an existing file, an existing directory or a non-existent directory?
It doesn't matter to File.expand_path
: "cats"
is considered to be an existing directory, and File.expand_path
starts inside it.
This command is equivalent to launching :
File.expand_path('..')
inside the "/Users/max/Dropbox/work/src/github.com/mbigras/foobie/cats"
directory.
So expand_path
goes back one directory, and lands back to :
"/Users/max/Dropbox/work/src/github.com/mbigras/foobie"
Same thing. It is equivalent to File.expand_path('..')
from the (probably) non-existing :
"/Users/max/Dropbox/work/src/github.com/mbigras/foobie/(pry)"
So it is :
"/Users/max/Dropbox/work/src/github.com/mbigras/foobie"
Going from [4], it just goes to the subfolder lib
.
Starting from "/Users/max/Dropbox/work/src/github.com/mbigras/foobie/(pry)"
, it just goes to the subfolder lib
.
Once again, File.expand_path
never checks if the corresponding folders and subfolders exist.
Upvotes: 2