1

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.

  1. Take File.dirname(__FILE__)
  2. Go to the parent which is the root
  3. append lib/mygem.rb

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

1 Answer 1

3

Theory

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).

Examples

[3]

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" 

[4]

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" 

[5]

Going from [4], it just goes to the subfolder lib.

[8]

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.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.