5

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?

angelixd
  • 300
  • 1
  • 7

2 Answers2

5

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"
Frank Koehl
  • 3,104
  • 2
  • 29
  • 37
4

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.

mu is too short
  • 426,620
  • 70
  • 833
  • 800