Ruby has this defined?
keyword that helps you check if a variable is defined or not.
If the variable exists you’ll get its type:
apple = 1 defined?(apple) # "local-variable"
If it doesn’t you’ll get nil:
defined?(bacon) # nil
This is like Javascript’s typeof
operator. If you want to know the class of an object use the class
method instead of this.
A few interesting points to note:
defined?
is a keyword, not a methoddefined?
is one of the few things in Ruby that ends in a question mark, but doesn’t follow the usual convention to return eithertrue
orfalse
defined?
can tell the difference between a nil value & a variable that has never been set before
These special attributes make this keyword worth learning about.
A Better Way To Check For Defined Variables
This keyword can be useful, but it has some problems.
Why?
Because of its low operator precedence.
If you do something like this:
defined? orange && orange.size
The result is “expression”.
Because orange && orange.size
is interpreted as the argument to defined?
.
The correct way to do this would be:
defined?(orange) && orange.size
Ruby has other ways to check if a variable has been defined or not.
For local variables:
local_variables.include?(:orange)
For instance variables:
instance_variable_defined?("@food")
But you don’t want to use any of that.
In 99% of the cases, if a local variable is missing you have a typo or someone forgot to declare that variable.
What about instance variables?
Undefined instance variables are always nil
, so you want to check for that.
Try the “safe navigator operator” (Ruby 2.3+) which only calls a method if the variable is not nil
.
Here’s an example:
if @user&.country == "Spain" # ... end
This the equivalent to:
if @user && @user.country == "Spain" # ... end
These aren’t as universal as the defined?
keyword, but they are more predictable & less prone to errors.
Check If A Method Is Defined
You can use defined?
to check if a method is defined, but it’s not that practical.
Example:
defined?(puts) # "method"
Because it’s a keyword & not a method you can’t use it with an object.
This is what I mean:
[].defined?(:size) # undefined method `defined?' for []:Array
You’re looking for the respond_to?
method.
Here’s how to use it:
[].respond_to?(:size) # true [].respond_to?(:orange) # false
Check If A Class Exists
Example:
defined?(Object) # "constant" defined?(A) # nil
A better option is to use the const_defined?
method.
Like this:
Object.const_defined?(:String) # true Object.const_defined?(:A) # false
Summary
There you go, you learned an easy way to check if a given variable, class or method exists!
When working with variables what you want most of the time is to check for nil
, instead of whether or not a variable is defined. Or even better, convert the variable into a known class using a conversion method.
I hope you found this article useful! If you did please share it so more people can enjoy it.
Just a small typo, but you’re missing the question mark here:
instance_variable_defined(“@food”)
You’re right! Thank you 🙂