Skip to content

Ruby error: undefined local variable or method

Sean Lerner edited this page Apr 5, 2017 · 9 revisions

If your error looks like ...

my_program.rb:2:in `display_greeting': 
undefined local variable or method `name' for main:Object
(NameError) from my_program.rb:6:in `<main>'

... then ruby needs a variable or method defined before you can use it.

When you type a word into ruby, and it's not a keyword (e.g. if, else, def, class, etc.), ruby will first try to treat the word as a variable if it was previously defined, and if not, try to call a method using that word.

How To Fix

Step 1: Determine if you made a typo

Double-check your spelling, and remember that variables and methods should be lowercase.

Step 2: Determine if you meant to type a string

Ruby treats text between single or double-quotes as strings. Did you forget to put the text between quotes and now ruby thinks it's a variable or method?

For example, if I have the following code:

name = sean

Ruby would think that sean is a method or variable. What I really need is quotes around 'sean':

name = 'sean'

Step 3: Determine if your variable has scope

Ruby is only aware of local variables in the methods they are defined.

For example, if I have the following code:

def display_greeting
  puts "Hello #{name}"
end

name = 'Sean'
display_greeting

Ruby would raise an error as name does not carry over into the display_greeting method.

One way to solve this is to pass the name variable as an argument into the method:

def display_greeting(name)
  puts "Hello #{name}"
end

seany = 'Sean'
display_greeting(seany)

Step 4: Determine if your method is a class or an instance method

Class methods begin with self. and instance methods do not.

For example, I'd like to display all my contacts nicely in a nicely formatted way, but here, I haven't properly defined display_all as a class method:

class Contact

  @@all = []

  attr_accessor :name, :phone

  def initialize(name, phone)
    @name = name
    @phone = phone
    @@all << self
  end

  def display_all
    puts 'Contacts'
    puts '--------'
    @@all.each do |contact|
      puts "Name: #{contact.name}"
      puts "Phone: #{contact.phone}"
    end
  end

end

Contact.new('Sean', '416-555-5555')
Contact.new('Sasha', '416-555-4444')
Contact.display_all

To fix this, I have to change display_all into a class method:

  def self.display_all
    puts 'Contacts'
    puts '--------'
    @@all.each do |contact|
      puts "Name: #{contact.name}"
      puts "Phone: #{contact.phone}"
    end
  end
Clone this wiki locally