How can I check whether a variable is defined in Ruby? Is there an isset
-type method available?
This question is related to
ruby
reflection
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.
defined?(your_var)
will work. Depending on what you're doing you can also do something like your_var.nil?
This is the key answer: the defined?
method. The accepted answer above illustrates this perfectly.
But there is a shark, lurking beneath the waves...
Consider this type of common ruby pattern:
def method1
@x ||= method2
end
def method2
nil
end
method2
always returns nil
. The first time you call method1
, the @x
variable is not set - therefore method2
will be run.
and method2
will set @x
to nil
. That is fine, and all well and good. 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 - with this solution, that particular case is handled - use the following:
def method1
return @x if defined? @x
@x = method2
end
The devil is in the details: but you can evade that lurking shark with the defined?
method.
Leaving an incredibly simple example in case it helps.
When variable doesn't exist:
if defined? a then "hi" end
# => nil
When variable does exist:
a = 2
if defined? a then "hi" end
# => "hi"
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.
You can try:
unless defined?(var)
#ruby code goes here
end
=> true
Because it returns a boolean.
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
You can try:
unless defined?(var)
#ruby code goes here
end
=> true
Because it returns a boolean.
Leaving an incredibly simple example in case it helps.
When variable doesn't exist:
if defined? a then "hi" end
# => nil
When variable does exist:
a = 2
if defined? a then "hi" end
# => "hi"
Use defined? YourVariable
Keep it simple silly .. ;)
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
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.
Also, 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! :)
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.
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
defined?(your_var)
will work. Depending on what you're doing you can also do something like your_var.nil?
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.
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
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
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.
Use defined? YourVariable
Keep it simple silly .. ;)
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.
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
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!
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')
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!
defined?(your_var)
will work. Depending on what you're doing you can also do something like your_var.nil?
Also, 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! :)
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.
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')
This is the key answer: the defined?
method. The accepted answer above illustrates this perfectly.
But there is a shark, lurking beneath the waves...
Consider this type of common ruby pattern:
def method1
@x ||= method2
end
def method2
nil
end
method2
always returns nil
. The first time you call method1
, the @x
variable is not set - therefore method2
will be run.
and method2
will set @x
to nil
. That is fine, and all well and good. 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 - with this solution, that particular case is handled - use the following:
def method1
return @x if defined? @x
@x = method2
end
The devil is in the details: but you can evade that lurking shark with the defined?
method.
Source: Stackoverflow.com