To Be Or Not To Be in Ruby

Jan Taras
5 min readMar 16, 2021

The questions that a programmer asks when learning a new language are akin to questions

a first year philosophy student would ask: “What does it mean to exist?”, “What is true and what is false?”,

“Can I make a decent salary after learning this?”.

In today’s article I am going to answer one of the questions above for Ruby language:

“What does it mean to exist in Ruby?”

Suppose you have an object. You do not know what the object’s value is, but you just want to know whether the object resolves to true or not in a logical expression. Suppose you have no knowledge of the Ruby language but you have played around with some other languages before. Which operator would you use to fulfill the task?

I hope you picked the **!** negation operator, because this article is not prepared for any other possibility.

irb(main)> !truthy_value

=> false

irb(main)> !falsey_value

=> true

irb(main)> !!truthy_value

=> true

Yes the handy good old bang works like it does in any other decent language and return the opposite of a logical value of an expression it precedes and is plenty useful in Ruby.

However what could be the actual value of **falsey_value**? In Ruby there are two possibilities:

**false** and **nil**:

irb(main)> falsey = false

irb(main)> nilly = nil

irb(main)> !!falsey

=> false

irb(main)> !!nilly

=> false

__Note: Beware of the zero though as unlike in many other languages it resolves to true in Ruby:__

irb(main)> !0

=> false

Both false and nil logically resolve to false. Nil being the null reference type for Ruby and false representing a negative logical value. How one would discern one from the other — for that Ruby provides a **.nil?** method to which only a **nil** object responds with true.

irb(main)> false.nil?

=> false

irb(main)> nil.nil?

=> true

irb(main)> truthy_value.nil?

=> false

Of course false and nil are drastic sates of non-existence, but what about less explicit states of non-existence.

Suppose you have an Array representing your fridges contents and you would like to check whether there is any food left in there:

my_fridge = []

if my_fridge.____?

p ‘Horray, there is food in the fridge’

else

p ‘Alright fellas, who ate my yoghurt?’

end

There are few ways to solve that dilemma in plain Ruby.

One of them would be to utilize **any?** method available for any Enumerable object of which Array is an example.

Without block provided it will return **true** if the collection contains any object that is not **false** or **nil** (you cannot eat a false logical value, unless our philosophy student allows you to do so).

my_fridge = []

if my_fridge.any?

p ‘Horray, there is food in the fridge’

else

p ‘Alright fellas, who ate my yoghurt?’

end

=> ‘Alright fellas, who ate my yoghurt?’

Suppose our philosophy student agrees that falsehood indeed can be consumed then we can provide a block to **any?** method to make it happen.

my_fridge = [false]

if my_fridge.any? { |food| food || !food }

p ‘Yummy, negative logical value up my tummy’

else

p ‘Alright fellas, who ate my yoghurt?’

end

=> ‘Yummy, negative logical value up my tummy’

You can of course provide different condition in your block depending on your use case.

Similarly we could uses Enumerable method **detect** which detects and returns the first element meeting the conditions described in a block.

my_fridge = [false]

if my_fridge.detect { |food| food == ‘My goddamn yoghurt’ }

p ‘Yoghurt — my precious’

else

p ‘Last chance! Where is HE?’

end

=> ‘Last chance! Where is HE?’

But suppose you will eat literally anything in your fridge regardless of what the philosophy student say, the method you would use would be **.empty** which returns true unless the array contains no elements, regardless of elements logical value. (Checking `array.size == 0` would be another less elegant way to put it):

my_fridge = [false]

if my_fridge.empty?

p ‘There is nothing in my fridge’

else

p ‘There is something in my fridge’

end

=> ‘There is something in my fridge’

my_fridge = []

if my_fridge.empty?

p ‘There is nothing in my fridge’

else

p ‘There is something in my fridge’

end

=> ‘There is nothing in my fridge’

The very same method is also available for Strings and Hashes, and Sets:

irb(main)> [].empty?

=> true

irb(main)> ‘’.empty?

=> true

irb(main)> {}.empty?

=> true

irb(main)> {foo: ‘bar’}.empty?

=> false

irb(main)> ‘string’.empty?

=> false

irb(main)> Set[].empty?

=> true

irb(main)> Set[:my, :yoghurt].empty?

=> false

Your mind must now due to its software development conditioning be buzzing for the opposite of **empty?** that would show us whether the resource really exists. You are in for a disappointment since plain Ruby does not provide a direct opposite of that. A beloved Ruby library ActiveSupport however does.

The name of the method is **present?** and it works just as you would imagine

irb(main)> [].present?

=> false

irb(main)> ‘’.present?

=> false

irb(main)> {}.present?

=> false

irb(main)> {foo: ‘bar’}.present?

=> true

irb(main)> ‘string’.present?

=> true

irb(main)> Set[].present?

=> false

irb(main)> Set[:my, :yoghurt].present?

=> false

It also handles nil and false:

irb(main)> nil.present?

=> false

irb(main)> false.present?

=> false

irb(main)> true.present?

=> true

It has its opposite method in Active record called **blank?** I would recommend to use it instead

of **empty?** as the former is not applicable for all possible objects that may appear in your output:

irb(main)> [].empty?

=> true

irb(main)> [].blank?

=> true

irb(main)> ‘’.empty?

=> true

irb(main)> ‘’.blank?

=> true

irb(main)> nil.empty?

NoMethodError (KABOOM!!!)

irb(main)> nil.blank?

=> true

irb(main)> false.empty?

NoMethodError (KABOOM!!!)

irb(main)> false.blank?

=> true

The resultant difference stems from how **blank** method is defined [here](https://apidock.com/rails/v4.2.7/Object/blank%3F).

The last existence of this article is **exists?** method of ActiveRecord.

Imagine you have a following ActiveRecord definitions:

class Knight < ApplicationRecord

self.table_name = “knights”

has_one :shield

end

class Shield < ApplicationRecord

self.table_name = “shields”

belongs_to :shield

end

This little method is directly linked to the object in a database and will ALWAYS check for

presence of the record with an SQL query and return true or false depending on whether the object exists:

# triggers SQL query if shield not loaded

shield_id = knight.shield&.id

# triggers a secondary query regardless of preloaded value — use with caution

knight.shield.exists? ? ‘Defensive knight’ : ‘Knight who says Ni’

As mentioned above use this method with caution and only if you need the most current binary information about the existence of the object. This method is often cause of performance drops and N+1 queries (what those are and how to fight them is a story for another time).

As a last note in the article I would like to emphasize that due to Ruby’s metaprogramming and money patching properties your experience may vary as some programmers may be keen to override **!~** or **empty?** methods for whatever reason.

Hope you enjoyed the read and me and our philosophy student will see you in the next article :).

Cheers,

--

--