So you might be doing some ruby on rails coding and you see stuff like .nil?, and .empty? and .blank? and wonder what the heck is the difference between them all? I thought the same thing and here’s what the Google gods have told me:

.nil?

  1. .nil is available on every class
  2. It’s defined in the ‘Object’ class and overridden in the ‘NilClass’ class
  3. .nil? returns true if the object is nil, and is available on all objects.
  4. e.g.
    1. nil.nil? => true
    2. “helloworld”.nil? => false

.empty?

  1. .empty? is only available on strings, arrays, and Hashes((There are actually a couple other classes that implement .empty? like Queue, and GDBM. Also you can add the #empty? method to any class you wanted.)). If you try to call it on other objects it will throw an error.
  2. .empty? returns true, if the string/array/hash has length = 0, aka “empty”. This means a string with no characters (including white spaces), an array with no items, and a hash with no keys.
  3. e.g.
    1. [].empty? => true
    2. { key: “value”}.empty? => false
    3. “”.empty? => true
    4. “ “.empty? => false

.blank?

  1. Is actually a custom method added to the base object by the Rails team and subsequently, can only be used in the context of rails.
  2. .blank? returns true, if an object is nil, false, a whitespace character only, or is empty?
  3. Basically this allows you to do .nil?, and .empty? call at the same time, and for strings check also check for white spaces.
  4. e.g.
    1. “ \n“.blank? => true
    2. [].blank? => true
    3. nil.blank? => true
    4. “hello world”.blank? => false

.present?

  1. present?, like .blank? is a creating of rails and can only be used in the context of Rails.
  2. .present? is simply !.blank?
  3. e.g.
    1. “ \n“.present? => false
    2. [].present? => false
    3. nil.present? => false
    4. “hello world”.present? => true

if conditions

  1. Often we write code like if(myVar) and implicitly check the truthiness((truthy values are values that return true when used in an if condition. Likewise, falsy values are values that return false when used in an if condition. For example, in ruby, nil, and false are falsy, but for javascript, null, 0, “”, [], {}, and false are all falsy. In Ruby 0, “”, [], and {} are all truthy. This can cause confusing when using and reading different languages. e.g. var i = 0; if(i), will not act the same way for ruby and javascript.)) of the variable. This can be especially confusing since many developers write similar code in different languages but it act differently for each language.
  2. For ruby a falsy value is nil or false . All other values are true.
  3. e.g.
    1. if (false) => false
    2. if (true) => true
    3. if (nil) => false
    4. if (“”) => true
    5. if ([]) => true

TLDR:

So in summary here are the concepts that are important to remember:

  1. .nil? is available on ALL objects
  2. .blank? and .present? are ONLY available in Rails. Dont try using these in other non-Rails projects.
  3. .nil? checks if an object is nil
  4. .empty? is available only on string, array and hash, and checks if the length = 0.
  5. .blank? returns true, if an object is nil, false, a whitespace character only, or is empty?
  6. .present? is the opposite of .blank?
  7. if conditions are false if they are nil or boolean false, true otherwise
  8. A string of only whitespace characters returns false for .empty? and true for .blank?

Also here is a completely original reference table that summarizes all the usecases.((Its not original at all. Credit goes to stackoverflow user ju. (Julian Popov) here Thanks for the great resource!))

ruby-grid

Anyways hopefully this helps people remember what each does and when to use each function if you already hadn’t read one of the many other blog posts on this topic!

Extra: Tips / Gotchas

  1. FixNum 0 is truthy. This might be confusing to those coming from JavaScript where 0 in a if condition evaluates to false.
  2. !myVar.nil? is not equivalent to myVar . Though this is typically true, this is not the case for boolean values. If myVar = false, then !myVar.nil? evaluates to true, and myVar = false.
  3. .blank? can be used on all objects in Rails even though it doesn’t always makes logical sense. For example, if i create a custom class MyClass, in rails, then MyClass.new.blank? is available even though my class might not have any concept of blank? or empty?. So this can be kind of confusing, and I like to keep my usage of .blank? to mainly strings and checking .nil? || .empty?.
  4. blank? will return false even if all elements of an array are blank((http://stackoverflow.com/a/888877/341692)). To determine blankness in this case, use all? with blank?, for example:
    1. [ nil, '' ].blank? == false
    2. [ nil, '' ].all? &:blank? == true

Extra: Still want more information?

Looking at the source code and seeing exactly how things are implemented can help solidify the information and understanding of how things work.

.nil?

Nil has a super simple implementation. Basically if the object’s type is NilClass, .nil? it returns false. All other objects simply return true. No logic at all!

nil? implementation for the NilClass((reference: http://www.ruby-doc.org/core-2.1.2/NilClass.html#method-i-nil-3F
source: https://github.com/ruby/ruby/blob/ruby_2_1/object.c#L1361))

static VALUE
rb_true(VALUE obj)
{
   return Qtrue;
}

nil? implementation for Object((reference: http://ruby-doc.org/core-2.1.2/Object.html#method-i-nil-3F
source: https://github.com/ruby/ruby/blob/ruby_2_1/object.c#L1376))

static VALUE
rb_false(VALUE obj)
{
   return Qfalse;
}

.empty?

We mentioned earlier that empty? is checking to see if the length == 0, and you can see from the implementations of empty for array, string, and hash, this is an accurate description!

.empty? implementation for array((source: https://github.com/ruby/ruby/blob/ruby_2_1/array.c#L1879
reference: http://www.ruby-doc.org/core-2.1.2/Array.html#method-i-empty-3F))

static VALUE
rb_ary_empty_p(VALUE ary)
{
    if (RARRAY_LEN(ary) == 0)
	return Qtrue;
    return Qfalse;
}

You can see that the code is very straightforward. If the array’s length equal zero then return true. Here RARRAY_LEN is a macro that gets the length of the array((Heres an interesting talk on reading the ruby c source code as well as talking about the macros like RARRAY_LEN http://patshaughnessy.net/2013/1/23/ruby-mri-source-code-idioms-1-accessing-data-via-macros)).

.empty? implementation for string((source: https://github.com/ruby/ruby/blob/ruby_2_1/string.c#L1334
reference: http://www.ruby-doc.org/core-2.1.2/String.html#method-i-empty-3F))

static VALUE
rb_str_empty(VALUE str)
{
    if (RSTRING_LEN(str) == 0)
	return Qtrue;
    return Qfalse;
}

Again, you can see that the code is very straight forward and essentially identical to Array’s implementation of empty?. If the string length equals zero then return true.

.empty? implementation for hash((source: https://github.com/ruby/ruby/blob/ruby_2_1/hash.c#L1522
source 2: https://github.com/ruby/ruby/blob/ruby_2_1/include/ruby/ruby.h#L931
reference: http://www.ruby-doc.org/core-2.1.2/Hash.html#method-i-empty-3F))

static VALUE

rb_hash_empty_p(VALUE hash)
{
  return RHASH_EMPTY_P(hash) ? Qtrue : Qfalse;
}

#define RHASH_EMPTY_P(h) (RHASH_SIZE(h) == 0)

Here we see a slightly more abstract implementation where there is a macro RHASH_EMPTY_P that checks if the hash is empty. But if we look at the implementation of RHASH_EMPTY_P we see that its exactly like array and string where it checks if the size (or length) is equal to zero.

So we just confirmed that the description for empty? as checking the length equals 0 is pretty much 100% accurate! No gotchas here.

.blank?

Unlike .nil? and .empty?, .blank? is implemented completely in ruby((source: https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/object/blank.rb)). There is a general implementation of .blank? on the Object class, but this is overridden by more specific implementations for NilClass, FalseClass, TrueClass((More about NilClass, TrueClass, FalseClass http://ruby.about.com/od/beginningruby/ss/Trueclass-Falseclass-And-Nilclass-Quick-Reference.htm)), Array, Hash, String, and Numeric. Let’s take a look.

NilClass and FalseClass

Both these classes always evaluate to true. You COULD make the argument that False ( like 0) shouldn’t be considered blank, since it does have some value.

def blank?
   true
end

TrueClass and Numeric

TrueClass and Numeric are always false. That is why even 0.blank? is false.

def blank?
   false
end

Array and Hash

For array had hash, .blank? is just an alias for .empty?

alias_method :blank?, :empty?

String

String has the most “complicated” implementation. Basically the string is checked against a regular expression to see if its made up of all whitespace.

BLANK_RE = /\A[[:space:]]*\z/
def blank?
   BLANK_RE === self
end

Object

This is the default implementation for all other objects. Basically if the object has an empty? method, it delegates to that, otherwise it checks if the object is nil or not.

def blank?
   respond_to?(:empty?) ? !!empty? : !self
end

That’s everything for blank! You can now clearly see how blank? is implemented in rails. Since we know that blank? uses empty? if its available, we can create custom classes that implement empty?, and blank? will automatically use that method. Also we can see that the implementation of blank? using alias_method for array and hash is actually redundant. Object’s implementation of blank? already calls the .empty? method if it exists, so there is no need explicitly alias blank? to empty?. Maybe the rails team did this for the slight performance gain or improved understandability of their code? I don’t know

.present?

.present? has the simplest implementation, which doesn’t require much explanation. Its simply the opposite of blank.

def present?
   !blank?
end

Final Summary

Anyways that’s it for our tour into Ruby and Rails implementation of .nil?, .empty?, .blank?, and .present?. As you can see all the implementations are very straight forward and hopefully should help you remember what each of them do!

I can’t believe you made it this far. Thanks for reading!