1208

I find myself repeatedly looking for a clear definition of the differences of nil?, blank?, and empty? in Ruby on Rails. Here's the closest I've come:

  • blank? objects are false, empty, or a whitespace string. For example, "", " ", nil, [], and {} are blank.

  • nil? objects are instances of NilClass.

  • empty? objects are class-specific, and the definition varies from class to class. A string is empty if it has no characters, and an array is empty if it contains no items.

Is there anything missing, or a tighter comparison that can be made?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Arrel
  • 13,558
  • 7
  • 26
  • 24
  • 30
    One gotcha is an empty array returns false for `present?`. Which is because `blank?` returns true for an empty array. – Kris Apr 25 '12 at 10:41
  • 4
    One nice thing is to see that `:nil?` is defined on `::Kernel` and overridden on `::NilClass`, while `:empty?` is implemented separately on many classes (natively on `::String`, `::Array`, `::Hash`, and non-natively on other classes like `::Set` from stdlib and `::ActiveRecord::Relation` from rails). So `:nil?` is available in all subclasses of `::Object` and also in every class that includes `::Kernel` by itself, where `:empty?` must be implemented or included specifically in your classes. – rewritten Mar 22 '16 at 10:00
  • If you try to understand the whole `nil` concept [start here](https://lukaszwrobel.pl/blog/ruby-is-nil/). – totymedli Jun 13 '18 at 18:07
  • ```[1] pry(main)> [].blank? => true``` – Michael Mar 23 '19 at 03:46

15 Answers15

1492

.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 
alhimik45
  • 92
  • 1
  • 10
Corban Brook
  • 21,270
  • 4
  • 28
  • 34
  • 28
    As mentioned in the question, some non-empty strings count as blank. – Andrew Grimm May 20 '09 at 23:20
  • 1
    Why haven't they overwritter nil's .empty? if they could add .blank? – tillda Mar 02 '11 at 23:01
  • 7
    Also: `false.blank? == true` – Shannon Nov 05 '12 at 18:02
  • is `nil.blank?` something added by Rails? In `1.9.3p194` I get `NoMethodError: undefined method 'blank?' for nil:NilClass` in irb. E: Yep, here it is: http://api.rubyonrails.org/classes/Object.html#method-i-blank-3F – Factor Mystic Mar 04 '13 at 19:21
  • 1
    I've seen `blank?` erroneously used in non-rails contexts before. If you **really** need it you can [include it](http://stackoverflow.com/a/4239625/645491): `require 'active_support/core_ext/object/blank'` – TrinitronX Apr 09 '13 at 20:23
  • When talking about `present?` don't forget to mention `presence`. http://blog.bmonkeys.net/2014/overview-about-nil-blank-present-presence-try-and-other-basic-things – 2called-chaos Mar 23 '14 at 00:33
  • 2
    As an addition to the all-blank-array gotcha that Tom is mentioning in his answer, be aware that this can lead to security issues where an attacker can use unprepared code that simply checks for unless params.nil? or unless params.blank?, and is the cause of much discussion and work currently in Rails. See here for more information: https://github.com/rails/rails/issues/13420 – Houen Jul 30 '14 at 15:54
  • I am using something like this to avoid crashes on nil objects if (myString.to_s.strip.length != 0) # do something end – jcpennypincher Nov 19 '15 at 01:25
  • I've used `x.to_s.empty?` on a number of occasions where I want to do the same thing whether a variable is nil or a string / array that is empty. `nil.to_s == ""` – Brett Oct 07 '18 at 17:02
  • `[ nil, '' ].all? &:blank? == true` returns `TypeError (wrong argument type FalseClass (expected Proc))` for ruby ruby 2.5.0p0 – vishless Dec 06 '19 at 06:41
711

I made this useful table with all the cases:

enter image description here

blank?, present? are provided by Rails.

dimpiax
  • 12,093
  • 5
  • 62
  • 45
Julian Popov
  • 17,401
  • 12
  • 55
  • 81
  • 58
    It should be noted that blank? and present? are Rails-only. They return Exception: NoMethodError in Ruby 2.0.0. – Lonny Eachus Feb 20 '14 at 23:27
  • 17
    Consider adding `any?` if you ever update the table. – Dennis Sep 05 '14 at 17:07
  • `blank?` and `present?` are not "_Rails-only_", they're automatically included by Rails but can easily be included in non-Rails code by using ActiveSupport's Core extensions. See https://stackoverflow.com/questions/4238867/how-do-i-use-active-support-core-extensions?noredirect=1&lq=1 – the Tin Man Jan 28 '20 at 18:16
229

Just extend Julian's table:

enter image description here

Ref: empty?blank?nil?傻傻分不清楚

Sibevin Wang
  • 4,480
  • 3
  • 27
  • 27
66

Quick tip: !obj.blank? == obj.present?

Can be handy/easier on the eyes in some expressions

Alexander Malfait
  • 2,691
  • 1
  • 23
  • 23
59

enter image description here

  • Everything that is nil? is blank?
  • Everything that is empty? is blank?
  • Nothing that is empty? is nil?
  • Nothing that is nil? is empty?

tl;dr -- only use blank? & present? unless you want to distinguish between "" and " "

steve
  • 3,276
  • 27
  • 25
57

One difference is that .nil? and .empty? are methods that are provided by the programming language Ruby, whereas .blank? is something added by the web development framework Rails.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Andrew Grimm
  • 78,473
  • 57
  • 200
  • 338
18

A special case is when trying to assess if a boolean value is nil:

false.present? == false
false.blank? == true
false.nil? == false

In this case the recommendation would be to use .nil?

Alan H
  • 1,263
  • 1
  • 15
  • 21
16

Just a little note about the any? recommendation: He's right that it's generally equivalent to !empty?. However, any? will return true to a string of just whitespace (ala " ").

And of course, see the 1.9 comment above, too.

davemyron
  • 2,483
  • 3
  • 24
  • 33
15

Don't forget any? which is generally !empty?. In Rails I typically check for the presence of something at the end of a statement with if something or unless something then use blank? where needed since it seems to work everywhere.

  • 4
    .any? doesn't work with strings in ruby 1.9, as .any? requires enumerable, and string#each by itself doesn't work in ruby 1.9. – Andrew Grimm May 20 '09 at 00:59
  • 4
    Careful about `any?` for checking non-emptiness. It returns false if you have an array of falsy values. A way to get around that is to pass a always-true block: `[nil, false].any?{ true }`, but `!empty?` is shorter and you don't have remember the weird behavior. – Kelvin May 01 '13 at 19:30
14

nil? is a standard Ruby method that can be called on all objects and returns true if the object is nil:

b = nil
b.nil? # => true

empty? is a standard Ruby method that can be called on some objects such as Strings, Arrays and Hashes and returns true if these objects contain no element:

a = []
a.empty? # => true

b = ["2","4"]
b.empty? # => false

empty? cannot be called on nil objects.

blank? is a Rails method that can be called on nil objects as well as empty objects.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
neha
  • 174
  • 1
  • 2
9

Everybody else has explained well what is the difference.

I would like to add in Ruby On Rails, it is better to use obj.blank? or obj.present? instead of obj.nil? or obj.empty?.

obj.blank? handles all types nil, '', [], {}, and returns true if values are not available and returns false if values are available on any type of object.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Manish Shrivastava
  • 30,617
  • 13
  • 97
  • 101
8

Though there n-number of answers available to this question but I liked the way its being explained here so posted one more answer :-)

Look at the data metric below - Its self explanatory with the various data-types used across available methods for it.

#nil? #empty? #blank? #present?
5 false NoMethodError false true
"" false true true false
" " false false true false
"\t\n" false false true false
[] false true true false
["a"] false false false true
{} false true true false
{a: "b"} false false false true
Set.new false true true false
nil true NoMethodError true false
true false NoMethodError false true
false false NoMethodError true false

Reference: https://blog.appsignal.com/2018/09/11/differences-between-nil-empty-blank-and-present.html

stealththeninja
  • 3,576
  • 1
  • 26
  • 44
shahjapan
  • 13,637
  • 22
  • 74
  • 104
7

exists? method can be used to check whether the data exists in the database or not. It returns boolean values either true or false.

ndnenkov
  • 35,425
  • 9
  • 72
  • 104
kelvin
  • 179
  • 4
  • 12
6

Rails 4

an alternative to @corban-brook 's 'Array gotcha: blank?' for checking if an arrays only holds empty values and can be regarded as blank? true:

[ nil, '' ].all? &:blank? == true

one could also do:

[nil, '', "", " ",' '].reject(&:blank?).blank? == true
mahatmanich
  • 10,791
  • 5
  • 63
  • 82
5

nil? can be used on any object. It determines if the object has any value or not, including 'blank' values.

For example:

example = nil
example.nil?  # true

"".nil?  # false

Basically nil? will only ever return true if the object is in fact equal to 'nil'.

empty? is only called on objects that are considered a collection. This includes things like strings (a collection of characters), hashes (a collection of key/value pairs) and arrays (a collection of arbitrary objects). empty? returns true is there are no items in the collection.

For example:

"".empty? # true
"hi".empty?   # false
{}.empty?  # true
{"" => ""}.empty?   # false
[].empty?   # true
[nil].empty?  # false

nil.empty?  # NoMethodError: undefined method `empty?' for nil:NilClass

Notice that empty? can't be called on nil objects as nil objects are not a collection and it will raise an exception.

Also notice that even if the items in a collection are blank, it does not mean a collection is empty.

blank? is basically a combination of nil? and empty? It's useful for checking objects that you assume are collections, but could also be nil.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Chitra
  • 1,294
  • 2
  • 13
  • 28