Pathname#present? for directories in Ruby 2.4

36 views
Skip to first unread message

Dominik Menke

unread,
Jul 28, 2017, 10:45:17 AM7/28/17
to Ruby on Rails: Core
Hi,

Ruby 2.4 introduced `Pathname#empty?` which delegates to `File#empty?` and `Dir#empty?`.

This caused a surprise in our code base, where we have this guard clause:

    def initialize(storage_path)
      raise ArgumentError, "no storage path configured" unless storage_path.present?
      # ...
    end

where `storage_path` points to a directory and is constructed via `Rails.root.join("data/foo/bar").tap(&:mkpath)`.

We've changed the guard to `if storage_path.nil?` as a workaround, but I still find it surprising that an existing path on disk is not `#present?`.

    foo = Pathname.new("/tmp").join(SecureRandom.uuid)
    foo.exist?   #=> false
    foo.present? #=> false
    
    foo.mkpath
    foo.exist?   #=> true
    foo.present? #=> false

Now, I don't know how strict the negation of `Object#present?` (i.e. `== !blank?`) is intended be, or else I'd have opened an issue/PR on GitHub and asked for another core extension, in the likes of

    if Pathname.instance_methods.include?(:empty?)
      class Pathname
        alias present? exist?
      end
    end

but that would lead to an instance beeing simultaneously `#blank?` and `#present?` (considering an `#empty?` directory ought to be `#blank?`).

So... what do you think?

Xavier Noria

unread,
Aug 12, 2017, 6:30:37 PM8/12/17
to rubyonrails-core
I think the current behavior is somewhat surprising, but not because of Rails, it is because of Ruby.

The first paragraph of Pathname in the official docs says:

Pathname represents the name of a file or directory on the filesystem, but not the file itself.

Nice, since we are dealing with file names I would expect Pathname#empty? to be like String#empty?

Problem is, Pathname actually has the String-like manipulation API one would expect from the description, and also a whole lot of file and directory API! This is later also acknowledged in the docs

All functionality from File, FileTest, and some from Dir and FileUtils is included, in an unsurprising way. It is essentially a facade for all of these, and more.

If you ask me, I don't really understand this API to be honest, but that is the way it is.

So, who decides if #empty? should be interpreted String-wise or File-wise? The Ruby team, and they have decided File-wise. Therefore, our expectacion of #empty? being String-wise has to be corrected.

And after that conclusion, the fact that present? is consistent follows, because it is documented that anything that is empty is blank, and that present? is just a convenience negation of being blank.

Reply all
Reply to author
Forward
0 new messages