Ruby (and Rails) have many ways to test whether something is … present. But each method behaves slightly differently, and some are Ruby-native while some are added by Rails.
Here’s the summary, in case you don’t feel like reading the full details below1:
.nil? (Ruby) | .empty? (Ruby) | .blank? (Rails) | .present? (Rails) | |
---|---|---|---|---|
true | false | NoMethodError | false | true |
false | false | NoMethodError | true | false |
nil | true | NoMethodError | true | false |
“” | false | true | true | false |
” “ | false | false | true | false |
{} | false | true | true | false |
[] | false | true | true | false |
“hi” | false | false | false | true |
0 | false | NoMethodError | false | true |
1 | false | NoMethodError | false | true |
.nil? (Ruby)
This method is beautiful in its simplicity, and I’ve never been confused by it. It does one very specific thing: it compares with nil
. No surprises here.
.empty? (Ruby)
This method is the only one of these four that can raise an error when used on the wrong type. Empty is only available on ruby collections, which includes strings, as they are collections of characters. If you try and use it on a non-collection, like integers, booleans, or nil, it’ll raise NoMethodError
.
.blank? (Rails)
The blank? method in rails seems to exist to patch the cases where .empty?
can raise NoMethodError
—it can be safely called on integers, booleans and nil. Otherwise it behaves just like empty does.
.present? (Rails)
Present works mostly like you would expect, but there are two confusing cases.
Confusing case one: 0
This isn’t an issue with the present method, it’s a confusing design decision in the Ruby language itself:
0.present? # true
In nearly every other language, 0
is a falsey value, but not in Ruby:
# This will return 'yes'
if 0
return 'yes'
else
return 'no'
end
I can understand the design decision. Zero is a value, it’s not null
, but this breaks the standard set by most other languages and I’ve been burned by it many times.
Confusing case two: whitespace-only strings
Non-empty strings, containing only whitespace, are also not considered present:
" ".present? # false
" ".empty? # false
" ".blank? # true
If you think hard about it and take the literal meanings of the method names, I guess you could consider a whitespace-only string non-empty but also not present, since a whitespace-only string contains no meaning. That feels like a stretch though, and this is not what I would expect in code. Fortunately, a whitespace-only string is not a common occurrence, so this one shouldn’t burn you very often (if ever).
Notes
- This is also for my own future reference, I never remember these ↩︎