2 comments
Just a small typo, but you’re missing the question mark here:
instance_variable_defined(“@food”)
You’re right! Thank you 🙂
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 either true
or false
defined?
can tell the difference between a nil value & a variable that has never been set beforeThese special attributes make this keyword worth learning about.
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.
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
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
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 🙂