Ruby Ruby Loops Ruby Loops Ruby Loops

Christopher Phillips
Christopher Phillips
10,045 Points

How would I do this:

Suppose I have 2 methods. The first method is like this video. It creates a hash with name and then items which are stored in an array.

How would I add items to that array from inside another, separate method? I'm getting the undefined local variable or method error because I don't think I can access the array inside a different method.

2 Answers

Anthony Moreno
Anthony Moreno
iOS Development with Swift Techdegree Student 4,362 Points

Can you type an example of how you’re trying to add to the array in method 1 from method 2?

Jay McGavren
STAFF
Jay McGavren
Treehouse Teacher

This is an issue with variable scoping. Suppose you have two different methods:

def one
  myvar = 1
  puts myvar
end

def two
  myvar = 2
  puts myvar
end

The above code contains two completely separate variables, both of which happen to be named myvar. They are local variables, meaning they are can only be read or modified inside the method where they are declared. This is a good thing; if both methods ran at the same time (which could happen using threads), you wouldn't want one method changing the other method's value for myvar.

If you want to update a local variable using a different method, you'll need to pass it to the other method as an argument, like this:

def make_burger
  contents = ["beef patty", "cheese"]
  add_ketchup(contents)
  p contents
end

def add_ketchup(my_array)
  my_array << "ketchup"
end

make_burger # prints: ["beef patty", "cheese", "ketchup"]
Christopher Phillips
Christopher Phillips
10,045 Points

Thank you for the answers. Perhaps it would be easier if I pasted in my code.

It's supposed to add 3 items to the "debts" array (contained in the debt_list method) via the "add_debt_item" method. Would this be easier if I made a class and made instance variables? What would that look like? I've tried but I'm running into more errors. Currently reviewing the videos again to see if i missed something.

def debt_list
  print "What is the name of your Debt List? "
  name = gets.chomp.capitalize

  hash = {"name"=>  name, "debts" => Array.new}

end

def ask
  loop do
    print "Would you like to add a debt to your snowball? (y/n) "
    answer = gets.chomp.downcase.to_s
    if answer == "n"
      break
    elsif answer == "y"
      add_debt_item
    else answer != "y" || answer != "n"
      puts "Please type y or n"
    end
  end
end

def add_debt_item
  print "What is the name of your first source of debt? "
  institution = gets.chomp.capitalize
  print "What is the balance of #{institution}? "
  balance = gets.chomp.to_i
  print "What is your current minimum payment for #{institution}? "
  min_payment = gets.chomp.to_i

  hash = {"institution" => institution, "balance" => balance, "min_payment" => min_payment}
  debt["debts"].push(hash)
end

# Runs first
debt = debt_list
# Runs second
ask
Jay McGavren
Jay McGavren
Treehouse Teacher

Christopher Phillips yes, your issue is with variable scoping.

def add_debt_item
  # code omitted
  # There is no variable named "debt" within the add_debt_item method!
  debt["debts"].push(hash) 
end

# This variable only exists at the top level; it will not be accessible within any methods!
debt = debt_list

You are definitely designing these methods and variables in a way that is better suited for a class. Here's my attempt at redesigning your code as a class.

class DebtList

  # Called when DebtList.new is called
  def initialize
    print "What is the name of your Debt List? "
    @name = gets.chomp.capitalize
    @debts = Array.new
  end

  def ask
    loop do
      print "Would you like to add a debt to your snowball? (y/n) "
      answer = gets.chomp.downcase.to_s
      if answer == "n"
        break
      elsif answer == "y"
        add_debt_item
      else answer != "y" || answer != "n"
        puts "Please type y or n"
      end
    end
  end

  def add_debt_item
    print "What is the name of your first source of debt? "
    institution = gets.chomp.capitalize
    print "What is the balance of #{institution}? "
    balance = gets.chomp.to_i
    print "What is your current minimum payment for #{institution}? "
    min_payment = gets.chomp.to_i

    hash = {"institution" => institution, "balance" => balance, "min_payment" => min_payment}
    # @debts is an instance variable. Unlike a local variable, it lives as long as the instance does.
    # This is the SAME @debts that is referenced in "initialize".
    @debts.push(hash)
  end

end

list = DebtList.new
list.ask