Project

General

Profile

Actions

Feature #20676

closed

Pathnames aren't Comparable

Added by gmcgibbon (Gannon McGibbon) 3 months ago. Updated 3 months ago.

Status:
Feedback
Assignee:
-
Target version:
-
[ruby-core:118844]

Description

👋

I was working with Pathnames recently and noticed that I could do:


Pathname("/a/b").to_s <= Pathname("/a/b/c").to_s

but could not do:

Pathname("/a/b") <= Pathname("/a/b/c")

to check if pathnames are subdirectories of each other.

Pathname implements <=> with case insensitive matching for use-cases like this, but does not include Comparable. I think Pathname should include Comparable. I've opened a PR here for your consideration.

Thanks!

Updated by byroot (Jean Boussier) 3 months ago

to check if pathnames are subdirectories of each other

I don't understand.

>> Pathname("/a/b").to_s <= Pathname("/a/b/c").to_s
=> true
>> Pathname("/a/b").to_s <= Pathname("/a/c").to_s
=> true

<= doesn't tell you the right hand-side is a subdirectory of the left hand-side.

Updated by nobu (Nobuyoshi Nakada) 3 months ago

Probably you may want to do:

(Pathname("/a/b/c").to_s+"/").start_with?(Pathname("/a/b").to_s+"/")
Actions #3

Updated by nobu (Nobuyoshi Nakada) 3 months ago

  • Status changed from Open to Feedback

Updated by Hanmac (Hans Mackowiak) 3 months ago

nobu (Nobuyoshi Nakada) wrote in #note-2:

Probably you may want to do:

(Pathname("/a/b/c").to_s+"/").start_with?(Pathname("/a/b").to_s+"/")

Pathname class already has this kind of logic in the <=> function

it just doesn't include the Comparable module to add the other compare functions like <= too

Updated by ufuk (Ufuk Kayserilioglu) 3 months ago

Hanmac (Hans Mackowiak) wrote in #note-4:

nobu (Nobuyoshi Nakada) wrote in #note-2:

Probably you may want to do:

(Pathname("/a/b/c").to_s+"/").start_with?(Pathname("/a/b").to_s+"/")

Pathname class already has this kind of logic in the <=> function

It doesn't, at least not in the way the original poster asked for or as @nobu (Nobuyoshi Nakada) suggested. This is clear from @byroot's example above.

The Pathname#<=> method only does a case-insensitive string comparison of the pathnames, which does not imply any subdirectory relationship between the two.

In case another example is helpful:

irb(main):001> p1 = Pathname.new("/a/b/c")
=> #<Pathname:/a/b/c>
irb(main):002> p2 = Pathname.new("/a/b/d")
=> #<Pathname:/a/b/d>
irb(main):003> p1 <=> p2
=> -1

Lexicographically, it is true that "/a/b/c" would sort before "/a/b/d", but that does NOT imply any subdirectory relationship as you can see.

Updated by Eregon (Benoit Daloze) 3 months ago

I think we should add Pathname#start_with?(path) for convenience, or maybe Pathname#inside?(path).
FWIW it already exists in my path gem: https://github.com/eregon/path/blob/a5e1d4d35a66466cfe8ab201f67982916cbbe845/lib/path.rb#L91-L96

Updated by byroot (Jean Boussier) 3 months ago

I think we should add Pathname#start_with?(path) for convenience, or maybe Pathname#inside?(path).

Yes, having methods to check if a path is a child or parent of the other would be very convenient. Should be opened as a new feature request though.

Updated by gmcgibbon (Gannon McGibbon) 3 months ago

It looks like I got it wrong. <=> does case-sensitive matching and doesn't behave the way I thought it did. Generally, I agree Pathname#inside?(path) would be a good addition that addresses my concern.

Thank you!

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0