Yak of the week! Ruby 2.4 Pathname empty?
changed to look at file size!
Pathname.present?
is false for existing file with empty contents! and a good example of Pry saving me!
I had failing tests in React on Rails due Ruby 2.4.1 due to a change in the Pathname API. Previously, for Ruby 2.3, Pathname.empty? would return false if the file’s name is not empty, not the contents!
[43] (pry) #<ReactOnRails::AssetsPrecompile>: 0> assets_path.blank?
true
[44] (pry) #<ReactOnRails::AssetsPrecompile>: 0> assets_path.to_s
"/var/folders/rp/_k99k0pn0rsb4d3lm9l3dnjh0000gn/T/d20170603-96466-zk7di7"
[45] (pry) #<ReactOnRails::AssetsPrecompile>: 0> assets_path.present?
false
[58] (pry) #<ReactOnRails::AssetsPrecompile>: 0> assets_path.presence
nil
WTF?
[59] (pry) #<ReactOnRails::AssetsPrecompile>: 0> $ assets_path.presence
From: /Users/justin/.rvm/gems/ruby-2.4.1@react_on_rails/gems/activesupport-5.1.1/lib/active_support/core_ext/object/blank.rb @ line 43:
Owner: Object
Visibility: public
Number of lines: 3
def presence
self if present?
end
[60] (pry) #<ReactOnRails::AssetsPrecompile>: 0> $ assets_path.present?
From: /Users/justin/.rvm/gems/ruby-2.4.1@react_on_rails/gems/activesupport-5.1.1/lib/active_support/core_ext/object/blank.rb @ line 23:
Owner: Object
Visibility: public
Number of lines: 3
def present?
!blank?
end
[46] (pry) #<ReactOnRails::AssetsPrecompile>: 0> assets_path.nil?
false
[52] (pry) #<ReactOnRails::AssetsPrecompile>: 0> assets_path.exist?
true
[53] (pry) #<ReactOnRails::AssetsPrecompile>: 0> assets_path.blank?
true
WTF!!!
The file exists, but blank?
is true.
[54] (pry) #<ReactOnRails::AssetsPrecompile>: 0> $ assets_path.blank?
From: /Users/justin/.rvm/gems/ruby-2.4.1@react_on_rails/gems/activesupport-5.1.1/lib/active_support/core_ext/object/blank.rb @ line 16:
Owner: Object
Visibility: public
Number of lines: 3
def blank?
respond_to?(:empty?) ? !!empty? : !self
end
[55] (pry) #<ReactOnRails::AssetsPrecompile>: 0> $ assets_path.empty?
From: ext/pathname/pathname.c (C Method):
Owner: Pathname
Visibility: public
Number of lines: 10
static VALUE
path_empty_p(VALUE self)
{
VALUE path = get_strpath(self);
if (RTEST(rb_funcall(rb_mFileTest, rb_intern("directory?"), 1, path)))
return rb_funcall(rb_cDir, rb_intern("empty?"), 1, path);
else
return rb_funcall(rb_mFileTest, rb_intern("empty?"), 1, path);
}
[56] (pry) #<ReactOnRails::AssetsPrecompile>: 0> assets_path.empty?
true
[57] (pry) #<ReactOnRails::AssetsPrecompile>: 0> assets_path.class
Pathname < Object
The reason why is that empty?
is true!
These are my pry shortcuts! Pry is so useful!
See My .pryrc for debugging and productivity
Debugging Shortcuts
ss : step
nn : next
cc : continue
fin : finish
uu : up
dd : down
bb : break
ww : whereami
ff : frame
sss : show-stack
$ : show whole method of context
Run 'pry_debug' or 'pd' to display shorter debug shortcuts
Utility method to solve the problem with tests
Utils.rb
module ReactOnRails
module Utils
# https://forum.shakacode.com/t/yak-of-the-week-ruby-2-4-pathname-empty-changed-to-look-at-file-size/901
# return object if truthy, else return nil
def self.truthy_presence(obj)
if obj.nil? || obj == false
nil
else
obj
end
end
end
Tests
module ReactOnRails
RSpec.describe Utils do
describe ".truthy_presence" do
context "With non-empty string" do
subject { "foobar" }
it "returns subject (same value as presence) for a non-empty string" do
expect(Utils.truthy_presence(subject)).to eq(subject.presence)
# Blank strings are nil for presence
expect(Utils.truthy_presence(subject)).to eq(subject)
end
end
context "With empty string" do
subject { "" }
it "returns \"\" for an empty string" do
expect(Utils.truthy_presence(subject)).to eq(subject)
end
end
context "With nil object" do
subject { nil }
it "returns nil (same value as presence)" do
expect(Utils.truthy_presence(subject)).to eq(subject.presence)
# Blank strings are nil for presence
expect(Utils.truthy_presence(subject)).to eq(nil)
end
end
context "With pathname pointing to empty dir (obj.empty? is true)" do
subject(:empty_dir) { Pathname.new(Dir.mktmpdir) }
it "returns Pathname object" do
# Blank strings are nil for presence
expect(Utils.truthy_presence(empty_dir)).to eq(empty_dir)
end
end
context "With pathname pointing to empty file" do
let(:empty_dir) { Pathname.new(Dir.mktmpdir) }
subject(:empty_file) { File.basename(Tempfile.new("tempfile",
empty_dir)) }
it "returns Pathname object" do
expect(Utils.truthy_presence(empty_file)).to eq(empty_file)
end
end
end
end
end