Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Concatenating absolute paths with the Pathname class

Tags:

ruby

pathname

I am working on a project where I have a dynamically determined mount point and am provided a set of absolute paths to do work on on the target volume. Since these files don't exist yet, I am using the Pathname class to handle the filename manipulations. However, Pathname seems to be doing something a bit clever when it comes to concatenating paths that have the same root. I have observed the following behavior:

p1 = Pathname.new('/foo/bar')                         # #<Pathname:/foo/bar>
p2 = Pathname.new('/baz/quux')                        # #<Pathname:/baz/quux>
p3 = p1 + p2                                          # #<Pathname:/baz/quux>
p4 = p1.join p2.relative_path_from(Pathname.new('/')) # #<Pathname:/foo/bar/baz/quux>
p5 = Pathname.new(p1.to_s.concat p2)                  # #<Pathname:/foo/bar/baz/quux>

So with p4 and p5, I am able to get the behavior I wanted, but the constructions are a little contrived. Is there a cleaner way to do this?

like image 306
angelixd Avatar asked Sep 17 '12 17:09

angelixd


2 Answers

It's fairly easy to work around Ruby's odd behavior here using string manipulation.

Borrowing the OP's example...

p1 = Pathname.new('/foo/bar')
p2 = '/baz/quux'
p1 + p2.sub(/\A\//, '')
# => #<Pathname:/foo/bar/baz/quux>

Caveat: The second p2 must be a String in order for the sub operation to occur. You can easily convert a Pathname object using #to_s.

Pathname.new('/some/path/').to_s
# => "/some/path"
like image 139
Frank Koehl Avatar answered Nov 30 '22 04:11

Frank Koehl


From the fine manual:

+(other)

Pathname#+ appends a pathname fragment to this one to produce a new Pathname object.

p1 = Pathname.new("/usr")      # Pathname:/usr
p2 = p1 + "bin/ruby"           # Pathname:/usr/bin/ruby
p3 = p1 + "/etc/passwd"        # Pathname:/etc/passwd

Emphasis mine. The + operator for Pathname is specified to append pathname fragments but a pathname with a leading slash is not a fragment. The documentation doesn't explicitly specify what is supposed to happen if you try to add two pathnames or add a non-fragment to a Pathname but the examples imply that you're seeing the expected behavior.

like image 34
mu is too short Avatar answered Nov 30 '22 03:11

mu is too short