This post originated from an RSS feed registered with Ruby Buzz
by Daniel Berger.
Original Post: Pathname#relative_path_from
Feed Title: Testing 1,2,3...
Feed URL: http://djberg96.livejournal.com/data/rss
Feed Description: A blog on Ruby and other stuff.
I realized last week that I never implemented Pathname#relative_path_from in my pathname2 package. So, I dutifully wrote the method based on Tanaka's code, got all the tests to pass (except 1, for reasons I won't bother you with here), and published it.
I realized after I published it that I had completely forgotten to test it on Windows. Looking at the Windows API, I saw that they had a function called RelativePathTo(). Ok, great, I figured I'd just use that behind the scenes and be done with it.
Except that it works much differently than Tanaka's version.
First, it lets you set whether or not the path in question refers to a file or directory. How does this matter? Consider the following example:
# Pseudo code atm
path1 = Pathname.new("c:\\a\\b\\path")
path2 = Pathname.new("c:\\a\\x\\y\\file")
p path2.relative_path_from(path1)
# RESULTS
# path1 is a directory, path2 is a file
"..\\..\\x\\y\\file"
# path1 is a file, path2 is a directory
"..\\x\\y\\file"
# both path1 and path2 are files
"..\\x\\y\\file"
# both path1 and path2 are directories
"..\\..\\x\\y\\file"
In effect, the basename of the path you're relative from affects the overall relative path if it's a file or directory. Or, to simplify even further, if the basename of the argument (path1) is a file, it's discarded for the overall calculation. Tanaka's version assumes that both paths are directories.
Second, you cannot calculate a relative path from one relative path to another relative path using PathRelativePathTo(). They must be absolute. This makes sense, depending on your perspective. How is path "a" relative to path "b"? Tanaka's version makes the assumption that the paths are at the same depth level to start off with. Consider this example, using Tanaka's Pathname class:
path1 = "a"
path2 = "b"
path2.relative_path_from(path1) # '../b'
The Window's function takes the stance that you cannot possibly know the relative position of one relative path to another relative path, because you have no idea at what depth level they are at to begin with.
My own feeling is that the Windows version is "correct" while Tanaka's version is "pragmatic".
What to do then on the Window's version? If I choose to be pragmatic rather than correct, I think the easiest thing to do is just cheat behind the scenes by temporarily turning relative paths into absolute paths, calculating the relative path based on that, and then remove the absolute portion of the path.
I'm also going to allow two optional arguments in the Windows version that let you specify whether or not the base and/or argument should be considered a file or directory. I'm not sure if I'll do that for Unix or not yet, but I'll decide that later.