When to use nil, blank, empty?
nil?
- checks to see if variable is referencing an object or notempty?
- may be used to check on various object types like empty string "" or empty array []blank?
- checks fornil?
orempty?
.
Difference between .nil?, .blank? and .empty?
In Ruby, nil
in an object (a single instance of the class NilClass
). This means that methods can be called on it. nil?
is a standard method in Ruby that can be called on all objects and returns true
for the nil
object and false
for anything else.
empty?
is a standard Ruby method on some objects like Arrays, Hashes and Strings. Its exact behaviour will depend on the specific object, but typically it returns true
if the object contains no elements.
blank?
is not a standard Ruby method but is added to all objects by Rails and returns true
for nil
, false
, empty, or a whitespace string.
Because empty?
is not defined for all objects you would get a NoMethodError
if you called empty?
on nil
so to avoid having to write things like if x.nil? || x.empty?
Rails adds the blank?
method.
After answering, I found an earlier question, "How to understand nil vs. empty vs. blank in Rails (and Ruby)", so you should check the answers to that too.
How to understand nil vs. empty vs. blank in Ruby
.nil?
can be used on any object and is true if the object is nil.
.empty?
can be used on strings, arrays and hashes and returns true if:
- String length == 0
- Array length == 0
- Hash length == 0
Running .empty?
on something that is nil will throw a NoMethodError
.
That is where .blank?
comes in. It is implemented by Rails and will operate on any object as well as work like .empty?
on strings, arrays and hashes.
nil.blank? == true
false.blank? == true
[].blank? == true
{}.blank? == true
"".blank? == true
5.blank? == false
0.blank? == false
.blank?
also evaluates true on strings which are non-empty but contain only whitespace:
" ".blank? == true
" ".empty? == false
Rails also provides .present?
, which returns the negation of .blank?
.
Array gotcha: blank?
will return false
even if all elements of an array are blank. To determine blankness in this case, use all?
with blank?
, for example:
[ nil, '' ].blank? == false
[ nil, '' ].all? &:blank? == true
nil v/s empty in ruby
Apparently @stores
is not nil
but initialized to an empty array []
.
So !@stores.nil?
is true because @stores.nil?
is false. I'm not familiar with logger.info
so I'm not sure why it prints nil
for the third line. empty?
returns true if there is no element in the array.
Should I use `.blank?` in a view of performance?
Theory
All three methods have various realizations for various classes:
:nil?
:# NilClass
def nil?
true
end
# Object
def nil?
false
end:empty?
:# String, Array
def empty?
if self.size == 0
true
else
false
end
end:blank?
:# FalseClass, NilClass
def blank?
true
end
# Object
def blank?
respond_to?(:empty?) ? empty? : !self
end
# TrueClass
def blank?
false
end
# String
def blank?
self !~ /[^[:space:]]/
end
As you may see the various classes implement various methods style. In case of String
class it takes time of a single Regexp
, in case of Object
, including Hash
, and Array
it takes time of call to :respond
and return a value nil
or not Object
. The seconds are just operations that takes time similar to :nil?
. :respond?
method checks the presense of the :empty?
method that takes theoretically slight more times than two times
to :empty?
.
Investigations
I wrote simple script that simulates the behaviour of those methods, and calculates execution time of them:
#! /usr/bin/env ruby
require 'benchmark'
obj = Object.new
array = []
empty_string = ''
non_empty_string = ' '
funcs =
[ proc { empty_string.empty? },
proc { non_empty_string.empty? },
proc { obj.nil? },
proc { nil.nil? },
proc { true },
proc { respond_to?(:empty?) ? empty? : !self },
proc { array.respond_to?(:empty?) ? array.empty? : !array },
proc { non_empty_string !~ /[^[:space:]]/ } ]
def ctime func
time = 0
1000.times { time += Benchmark.measure { 1000.times { func.call } }.to_a[5].to_f }
rtime = time /= 1000000
end
funcs.each {| func | p ctime( func ) }
And results:
# empty String :empty?
# 4.604020118713379e-07
# non_empty String :empty?
# 4.5903921127319333e-07
# Object :nil?
# 5.041143894195557e-07
# NilClass :nil?
# 4.7951340675354e-07
# FalseClass, NilClass, TrueClass :blank?
# 4.09862756729126e-07
# main :blank? ( respond_to returns false )
# 6.444177627563477e-07
# Array :blank? ( respond_to returns true )
# 6.491720676422119e-07
# String :blank?
# 1.4315705299377442e-06
As you may see, obvious champion from the end of table in case of speed is method :blank?
of String
class. It has execution time descreased in 3-4 times against an simple empty?
method of a class. Object's :blank?
method has only 1.5 times execution time degradation. Note, that :respond_to
method in it has just a few time to execute, becase as far as I see the ruby interpreter caches the result of its execution. So, conclusion. Try to avoid using String's .blank?
method.
Additional, if you need to know how to use the methods see here.
Testing for empty or nil-value string
The second clause does not need a !variable.nil?
check—if evaluation reaches that point, variable.nil
is guaranteed to be false (because of short-circuiting).
This should be sufficient:
variable = id if variable.nil? || variable.empty?
If you're working with Ruby on Rails, Object.blank?
solves this exact problem:
An object is blank if it’s false, empty, or a whitespace string. For example,
""
," "
,nil
,[]
, and{}
are all blank.
Return string if data is empty, nil or blank?
check if you have presence
available in your rails version. If it is, you can do the following
<%= f.text_area :comment, placeholder: @response.followup.presence || "Would you like to add a note?" %>
If it's not available, you can choose one of the following
- use a decorator/presenter (i think this is overkill)
set the value of the placeholder in the controller
@response.followup = 'Would you like to add a note?' if response.blank?
use a ternary operator in the view
<%= f.text_area :comment, placeholder: (@response.followup.blank? ? "Would you like to add a note?" : @response.followup) %>
Ruby when nil or empty string
You can use activesupport's Object#presence
method, like this:
foo = params[:customer][:language].presence || 'es'
Check if not nil and not empty in Rails shortcut?
There's a method that does this for you:
def show
@city = @user.city.present?
end
The present?
method tests for not-nil
plus has content. Empty strings, strings consisting of spaces or tabs, are considered not present.
Since this pattern is so common there's even a shortcut in ActiveRecord:
def show
@city = @user.city?
end
This is roughly equivalent.
As a note, testing vs nil
is almost always redundant. There are only two logically false values in Ruby: nil
and false
. Unless it's possible for a variable to be literal false
, this would be sufficient:
if (variable)
# ...
end
This is preferable to the usual if (!variable.nil?)
or if (variable != nil)
stuff that shows up occasionally. Ruby tends to wards a more reductionist type of expression.
One reason you'd want to compare vs. nil
is if you have a tri-state variable that can be true
, false
or nil
and you need to distinguish between the last two states.
Related Topics
How to Reference a File from Inside of a Gem
Replacing Text in One CSV Column Using Fastercsv
How to Programmatically Generate Heroku-Like Subdomain Names
Mongodb with Mongoid in Rails - Geospatial Indexing
How Would You Test Observers with Rspec in a Ruby on Rails Application
Ruby: Module, Require and Include
Ruby 1.9, Force_Encoding, But Check
Rubygems + Cygwin: Posix Path Not Found by Ruby.Exe
Generate Letters to Represent Number Using Ruby
Could Not Find a Valid Gem 'Rails' (>= 0) in Any Repository
Why Doesn't 'User Installation Directory' Match with the Ruby Version
How to Set Up a Sinatra App Under Apache with Passenger
Read Input from Console in Ruby
Generate Unique Random String with Letters and Numbers in Lower Case
Active Admin: Customize Only New Form