How can I check whether a variable is defined in Ruby? Is there an isset-type method available?
15 Answers
Use the defined? keyword (documentation). It will return a String with the kind of the item, or nil if it doesn’t exist.
>> a = 1
=> 1
>> defined? a
=> "local-variable"
>> defined? b
=> nil
>> defined? nil
=> "nil"
>> defined? String
=> "constant"
>> defined? 1
=> "expression"
As skalee commented: "It is worth noting that variable which is set to nil is initialized."
>> n = nil
>> defined? n
=> "local-variable"
5 Comments
||= operator) below.defined? still returns true for a variable defined within that block!defined? that returns boolean?!!defined?(object_name)nil or false, defeating the purpose of caching value in instance variable, and doing all reassigning again, with god-knows-what will be executed..This is useful if you want to do nothing if it does exist but create it if it doesn't exist.
def get_var
@var ||= SomeClass.new()
end
This only creates the new instance once. After that it just keeps returning the var.
9 Comments
||= with boolean values, lest you feel the pain of confusion.nil as well unless you really want to evaluate the expression every time it's called when it does return nilvar = (var or var.nil?)The correct syntax for the above statement is:
if (defined?(var)).nil? # will now return true or false
print "var is not defined\n".color(:red)
else
print "var is defined\n".color(:green)
end
substituting (var) with your variable. This syntax will return a true/false value for evaluation in the if statement.
4 Comments
defined?(var) == nil ?.nil? is more idiomatic, as they say. It's more "object-oriented" to ask an object if it nil than to use a comparison operator. Neither is difficult to read, so use whichever one helps you ship more product.defined?(your_var) will work. Depending on what you're doing you can also do something like your_var.nil?
Try "unless" instead of "if"
a = "apple"
# Note that b is not declared
c = nil
unless defined? a
puts "a is not defined"
end
unless defined? b
puts "b is not defined"
end
unless defined? c
puts "c is not defined"
end
3 Comments
WARNING Re: A Common Ruby Pattern
the defined? method is the answer. See the accepted answer above.
But watch out... consider this common ruby pattern:
def method1
@x ||= method2
end
def method2
nil
end
method2always returnsnil.- The first time you call
method1, the@xvariable is not set - thereforemethod2will be run. and method2will set@xtonil.
But what happens the second time you call method1?
Remember @x has already been set to nil. But method2 will still be run again!! If method2 is a costly undertaking this might not be something that you want.
Let the defined? method come to the rescue:
def method1
return @x if defined? @x
@x = method2
end
As with most things, the devil is in the implementation details.
1 Comment
Here is some code, nothing rocket science but it works well enough
require 'rubygems'
require 'rainbow'
if defined?(var).nil? # .nil? is optional but might make for clearer intent.
print "var is not defined\n".color(:red)
else
print "car is defined\n".color(:green)
end
Clearly, the colouring code is not necessary, just a nice visualation in this toy example.
1 Comment
nil? is optional.You can try:
unless defined?(var)
#ruby code goes here
end
=> true
Because it returns a boolean.
3 Comments
SyntaxError: compile error (irb):2: syntax error, unexpected $end, expecting kENDunless statement seems overly complicateddefined? does NOT return a boolean, but the type of what comes afterwards. This type can be truthy or falsy, but you should pay attention. The => true is misleading at best unless your "#ruby code " that "goes here" returns true.As many other examples show you don't actually need a boolean from a method to make logical choices in ruby. It would be a poor form to coerce everything to a boolean unless you actually need a boolean.
But if you absolutely need a boolean. Use !! (bang bang) or "falsy falsy reveals the truth".
› irb
>> a = nil
=> nil
>> defined?(a)
=> "local-variable"
>> defined?(b)
=> nil
>> !!defined?(a)
=> true
>> !!defined?(b)
=> false
Why it doesn't usually pay to coerce:
>> (!!defined?(a) ? "var is defined".colorize(:green) : "var is not defined".colorize(:red)) == (defined?(a) ? "var is defined".colorize(:green) : "var is not defined".colorize(:red))
=> true
Here's an example where it matters because it relies on the implicit coercion of the boolean value to its string representation.
>> puts "var is defined? #{!!defined?(a)} vs #{defined?(a)}"
var is defined? true vs local-variable
=> nil
Comments
Please note the distinction between "defined" and "assigned".
$ ruby -e 'def f; if 1>2; x=99; end;p x, defined? x; end;f'
nil
"local-variable"
x is defined even though it is never assigned!
1 Comment
NameError Exception: undefined local variable or method, and was confused when the only assignment/mention of the variable was in an if block that wasn't getting hit.It should be mentioned that using defined to check if a specific field is set in a hash might behave unexpected:
var = {}
if defined? var['unknown']
puts 'this is unexpected'
end
# will output "this is unexpected"
The syntax is correct here, but defined? var['unknown'] will be evaluated to the string "method", so the if block will be executed
edit: The correct notation for checking if a key exists in a hash would be:
if var.key?('unknown')
Comments
defined? is great, but if you are in a Rails environment you can also use try, especially in cases where you want to check a dynamic variable name:
foo = 1
my_foo = "foo"
my_bar = "bar"
try(:foo) # => 1
try(:bar) # => nil
try(my_foo) # => 1
try(my_bar) # => nil
2 Comments
rails 7.1 console, all these "try"s result in nilAlso, you can check if it's defined while in a string via interpolation, if you code:
puts "Is array1 defined and what type is it? #{defined?(@array1)}"
The system will tell you the type if it is defined. If it is not defined it will just return a warning saying the variable is not initialized.
Hope this helps! :)