Feature #20676
closedPathnames aren't Comparable
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+"/")
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!