readonly
readonly

Reputation: 355444

Checking if a variable is defined?

How can I check whether a variable is defined in Ruby? Is there an isset-type method available?

Upvotes: 616

Views: 362687

Answers (15)

BenKoshy
BenKoshy

Reputation: 35575

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
  1. method2 always returns nil.
  2. The first time you call method1, the @x variable is not set - therefore method2 will be run. and
  3. method2 will set @x to nil.

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.

Upvotes: 12

stevec
stevec

Reputation: 52198

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"

Upvotes: 1

John Donner
John Donner

Reputation: 542

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

Upvotes: 1

leberknecht
leberknecht

Reputation: 1714

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')

Upvotes: 3

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.

Upvotes: 8

donnoman
donnoman

Reputation: 161

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

Upvotes: 5

Elliott
Elliott

Reputation: 335

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! :)

Upvotes: 0

Robert Klemme
Robert Klemme

Reputation: 2179

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!

Upvotes: 3

danmayer
danmayer

Reputation: 4326

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.

Upvotes: 95

Ricardo Acras
Ricardo Acras

Reputation: 36244

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"

Upvotes: 822

Saqib R.
Saqib R.

Reputation: 3069

Use defined? YourVariable
Keep it simple silly .. ;)

Upvotes: 10

Bruno Barros
Bruno Barros

Reputation: 61

You can try:

unless defined?(var)
  #ruby code goes here
end
=> true

Because it returns a boolean.

Upvotes: 6

user761856
user761856

Reputation: 171

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

Upvotes: 16

foomip
foomip

Reputation: 1395

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.

Upvotes: 71

digitalsanctum
digitalsanctum

Reputation: 3299

defined?(your_var) will work. Depending on what you're doing you can also do something like your_var.nil?

Upvotes: 20

Related Questions