Question

How to Check if a Variable Is Defined in Ruby

rubyreflection

Question

How can I check whether a variable is defined in Ruby? Is there an isset-style method or built-in way to detect whether a variable currently exists?

Short Answer

By the end of this page, you will understand how Ruby checks whether variables are defined, why defined? is the usual tool for this job, and how it behaves with local, instance, class, and global variables. You will also see common patterns, mistakes, and practical examples you can use in real Ruby code.

Concept

Ruby does not use an isset() function like PHP. Instead, Ruby provides the defined? keyword to check whether something exists and is recognized by the current program context.

defined? can be used with:

  • local variables
  • instance variables
  • class variables
  • global variables
  • methods
  • constants
  • expressions

The important detail is that defined? does not simply return true or false. It returns:

  • a descriptive string when the thing is defined
  • nil when it is not defined

For example:

x = 10

p defined?(x)   # "local-variable"
p defined?(y)   # nil

This matters because Ruby treats nil as falsey, so defined? works naturally inside conditionals:

if defined?(x)
  puts "x exists"
end

Why this matters in real programming:

  • You may want to avoid errors when reading a variable that might not exist yet.
  • You may want lazy initialization, where a value is created only once.
  • You may need different behavior depending on whether a method, constant, or variable is available.
  • You may work with metaprogramming or optional configuration.

Also note an important Ruby-specific rule: some variable types behave differently when uninitialized.

For example:

  • Reading an undefined local variable usually raises an error.
  • Reading an uninitialized instance variable returns nil.

So checking whether something is defined is not always the same as checking whether its value is nil.

Mental Model

Think of defined? as asking Ruby:

"Do you recognize this name in the current scope, and what kind of thing is it?"

It is not asking:

"Does this variable contain a useful value?"

That distinction is important.

A variable can be:

  • defined and hold a value
  • defined and hold nil
  • not defined at all

Imagine labeled storage boxes:

  • If the box exists and contains 42, it is defined.
  • If the box exists and contains nothing (nil), it is still defined.
  • If the box was never created, it is not defined.

defined? checks whether the box exists, not whether the box is empty.

Take Quiz

Syntax and Examples

The basic syntax is:

defined?(expression)

Example: local variable

name = "Ruby"

p defined?(name)   # "local-variable"
p defined?(age)    # nil

Here:

  • name exists, so Ruby returns a descriptive string.
  • age does not exist, so Ruby returns nil.

Using it in a condition

if defined?(name)
  puts "name is defined"
else
  puts "name is not defined"
end

Because defined?(name) returns a non-nil value, the condition is treated as true.

Example: instance variable

class User
  def check_email
    p defined?(@email)
  end
end

User.new.check_email

This returns:

"instance-variable"

Even though @email was never assigned, instance variables are recognized by Ruby syntax and read as nil when uninitialized.

Example: method check

p defined?(puts)         # "method"
p defined?(missing_one)  # nil

Example: constant check

MY_APP_NAME = "Demo"

p defined?(MY_APP_NAME)  # "constant"
p defined?(UNKNOWN_NAME) # nil

A common lazy initialization pattern

@config ||= load_config

This is often enough when nil and false should both trigger initialization.

If you specifically care whether something was ever defined, use defined? instead:

unless defined?(@config)
  @config = load_config
end

Step by Step Execution

Consider this example:

x = nil

puts defined?(x)
puts defined?(y)

if defined?(x)
  puts "x exists"
end

Step by step:

  1. x = nil

    • A local variable named x is created.
    • Its value is nil.
    • Even though the value is nil, the variable is still defined.
  2. puts defined?(x)

    • Ruby checks whether x exists in the current scope.
    • It does.
    • Ruby returns "local-variable".
    • That string gets printed.
  3. puts defined?(y)

    • Ruby checks whether y exists.
    • It does not.
    • Ruby returns nil.
    • puts nil prints a blank line.
  4. if defined?(x)

    • Ruby evaluates defined?(x) again.
    • It returns "local-variable".
    • Since that is truthy, the if block runs.
  5. puts "x exists"

    • The message is printed.

Output:

local-variable

x exists

The blank line appears because defined?(y) returned nil.

Real World Use Cases

Here are common situations where checking whether something is defined is useful:

Optional configuration

if defined?(APP_TIMEOUT)
  timeout = APP_TIMEOUT
else
  timeout = 30
end

This is useful when a constant may or may not be loaded.

Lazy setup in objects

def cache
  unless defined?(@cache)
    @cache = {}
  end

  @cache
end

This creates the cache only when first needed.

Optional framework features

if defined?(Rails)
  puts "Running inside Rails"
end

This helps code adapt to different environments.

Defensive metaprogramming

if defined?(some_helper_method)
  some_helper_method
end

Useful when code may run in multiple contexts where helper methods are not always available.

Safe constant checks in libraries

if defined?(JSON)
  JSON.generate(data)
else
  require "json"
end

This avoids reloading or assuming a library is already present.

Take Quiz

Real Codebase Usage

In real Ruby projects, developers usually use defined? in a few focused patterns rather than everywhere.

1. Guarding optional dependencies

require "json" unless defined?(JSON)

This is common in scripts and libraries.

2. Lazy initialization when nil is a valid stored value

||= is common, but it reassigns when the current value is nil or false. If you need to know whether the variable was ever initialized, defined? is safer.

def setting
  return @setting if defined?(@setting)

  @setting = compute_setting
end

3. Environment-specific behavior

if defined?(Rails)
  logger.info("Rails mode")
else
  puts "Standalone mode"
end

4. Guard clauses

return default_value unless defined?(input)

This is useful when code may be evaluated dynamically.

5. Checking constants before use

if defined?(Redis)
  client = Redis.new
end

In larger codebases, constant checks are often clearer than rescuing a NameError.

Practical advice

  • Use defined? when you truly need to know whether something exists.
  • Use nil? when you know the variable exists and only want to inspect its value.
  • Use ||= for simple memoization when false and nil should both mean “not ready yet.”

Common Mistakes

Mistake 1: Confusing defined? with checking for nil

Broken idea:

x = nil

p defined?(x) == nil

Why it is wrong:

  • x is defined.
  • Its value is nil, but defined?(x) returns "local-variable".

Correct thinking:

x = nil

p defined?(x)   # "local-variable"
p x.nil?        # true

Mistake 2: Expecting defined? to return true or false

Broken assumption:

x = 1
p defined?(x) == true   # false

Why it happens:

  • defined? returns a string or nil, not a boolean.

Better approach:

if defined?(x)
  puts "x is defined"
end

Mistake 3: Reading an undefined local variable directly

Broken code:

p y

This raises an error because y does not exist.

Safer approach:

p defined?(y)

Mistake 4: Using ||= when false is a meaningful value

Broken pattern:

@enabled ||= expensive_check

If expensive_check returns false, this will run again next time.

Better pattern:

unless defined?(@enabled)
  @enabled = expensive_check
end

Mistake 5: Assuming all variable types behave the same

Example:

class Example
  def test
    p @value   # nil
    p value    # may be interpreted as a method call or raise an error depending on context
  end
end

Remember:

  • uninitialized instance variables return nil
  • undefined local variables are different
  • bare identifiers may also be parsed as method calls

Comparisons

ConceptWhat it checksReturn valueBest use
defined?(x)Whether Ruby recognizes xDescriptive string or nilExistence checks
x.nil?Whether x has value niltrue or falseValue checks
`x= value`Assign if current value is nil or false
respond_to?(:name)Whether an object has a methodtrue or falseMethod availability on objects
const_defined?(:Name)Whether a module/class defines a constanttrue or falseConstant checks in modules/classes

defined? vs nil?

x = nil

p defined?(x)  # "local-variable"
p x.nil?       # true

These answer different questions:

  • defined? = does the variable exist?
  • nil? = does the value equal nil?

defined? vs ||=

unless defined?(@result)
  @result = compute
end

vs.

@result ||= compute

Use defined? when false or nil are valid final values you want to keep. Use ||= when you want to recompute if the current value is falsey.

Take Quiz

Cheat Sheet

# Basic syntax
defined?(expression)

Returns

  • descriptive string if defined
  • nil if not defined

Common results

defined?(x)        # "local-variable"
defined?(@x)       # "instance-variable"
defined?(@@x)      # "class variable"
defined?($x)       # "global-variable"
defined?(MyConst)  # "constant"
defined?(puts)     # "method"

Typical conditional use

if defined?(x)
  puts "x exists"
end

Important rule

defined? checks existence, not value.

x = nil

defined?(x)  # "local-variable"
x.nil?       # true

Memoization edge case

@value ||= compute
  • recomputes if @value is nil or false
unless defined?(@value)
  @value = compute
end
  • computes only once, even if result is nil or false

Good fits for defined?

  • optional constants
  • lazy initialization
  • environment checks
  • metaprogramming
  • avoiding NameError for missing names

FAQ

How do I check if a variable exists in Ruby?

Use defined?(variable_name). It returns a descriptive string if the variable exists, or nil if it does not.

Is there an isset() equivalent in Ruby?

Ruby does not use isset(). The closest built-in tool is defined?.

Does defined? return true or false?

No. It returns a string such as "local-variable" or "method", or nil when not defined.

What is the difference between defined? and nil? in Ruby?

defined? checks whether something exists. nil? checks whether a value is nil.

Can a variable be defined and still be nil?

Yes.

x = nil

Here, x is defined, but its value is nil.

Should I use defined? for memoization?

Sometimes. Use it when false or nil are valid cached values. Otherwise, ||= is usually shorter.

Can defined? check methods and constants too?

Yes. It can check variables, methods, constants, and more.

Does reading an undefined variable always raise an error in Ruby?

Not always. Undefined local variables usually cause errors, but uninitialized instance variables return nil.

Take Quiz

Mini Project

Description

Build a small Ruby class that lazily loads configuration values only when needed. This demonstrates the difference between a variable being defined and a variable merely having a truthy value.

Goal

Create a class that initializes a setting only once and safely checks whether an instance variable has already been set.

Requirements

  • Create a class named AppConfig.
  • Add a method that returns a cached configuration value.
  • Use defined? to ensure the value is only initialized once.
  • Make the computed value able to be false without being recomputed.
  • Print the returned value multiple times to show the caching behavior.
Take Quiz

Keep learning

Related questions

View more