Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialHeather Stone
5,784 Pointsundefined local variable for main :Object in Ruby program
Attached is a simple, silly "budget" program to test out some of what I've learned so far. It's needlessly complicated, as I can run this program with just an if statement, but I wanted to work on my understanding of classes. When I run it, it accepts and stores my input, but then returns an error about the last line saying "beginnerbudget.rb:19:in <main>': undefined local variable or method
checking_amount' for main:Object (NameError)". How could this be, since the variable checking_amount is specified as an attr_accessor? Shouldn't the variable be available, since it's both an attr_accessor and also defined outside of the method in the first place?
I know I could specify an amount as an argument when I call the method but I want this to be based on user input, rather than a specified amount given when I call the method and run it.
class Beginnerbudget
attr_accessor :checking_amount
puts "How much money do you have in your checking account?"
checking_amount = gets.chomp.to_i
def rate_savings(checking_amount)
@checking_amount = checking_amount
if checking_amount >= 501
puts "You have $#{checking_amount} in your account. Keep up the good work!"
elsif checking_amount <= 500 && checking_amount >= 101
puts "You only have $#{checking_amount} in your account. Try and save a little more this month."
else checking_amount < 100
puts "Yikes, you only have $#{checking_amount} in your account! Sell a kidney quick!"
end
end
end
beginner_budget = Beginnerbudget.new
beginner_budget.rate_savings(checking_amount)
2 Answers
Taylor Boudreau
7,285 PointsHi there Heather,
Two things I see here. When you create the initialize method, you will want to update the checking_amount variable to be defined as an instance variable when you get the user input. (@checking_amount = gets.chomp.to_i
)
Also when instantiating the class, you won't have to call the initialize method as it's automatically run when you create the instance of Beginnerbudget. If you remove beginner_budget.initialize
as well you should see that run properly. This is explained in greater detail (http://www.rubyist.net/~slagell/ruby/objinitialization.html):
"Whenever Ruby creates a new object, it looks for a method named initialize and executes it. So one simple thing we can do is use an initialize method to put default values into all the instance variables, so the inspect method will have something to say."
My code:
class Beginnerbudget
attr_accessor :checking_amount
def initialize
puts "How much money do you have in your checking account?"
@checking_amount = gets.chomp.to_i
end
def rate_savings
if checking_amount >= 501
puts "You have $#{checking_amount} in your account. Keep up the good work!"
elsif checking_amount <= 500 && checking_amount >= 101
puts "You only have $#{checking_amount} in your account. Try and save a little more this month."
else checking_amount < 100
puts "Yikes, you only have $#{checking_amount} in your account! Sell a kidney quick!"
end
end
end
beginner_budget = Beginnerbudget.new
beginner_budget.rate_savings
Taylor Boudreau
7,285 PointsHi there Heather!
It looks like you may be running into issues because where you're passing the checking_amount
a value from user input, you're not using setting checking_amount as an instance variable. One way we're taught to fix this is by moving some of your code that's run when the class is instantiated into an initialize method. For your program, this may look something like this:
def initialize
puts "How much money do you have in your checking account?"
@checking_amount = gets.chomp.to_i
end
The @checking_amount gives you access to this variable when you call your rate_savings methods, but this needs to be done when the variable is first set, and only once. This also means you don't need to pass checking_amount as an argument into your rate_savings method, so it'd need to look something like this:
def rate_savings
if checking_amount >= 501
I love the program and I hope this helps!
Taylor
Heather Stone
5,784 PointsHi Taylor, thanks for your comment! I implemented the changes you recommended, and I got another error, saying "beginnerbudget.rb:22:in <main>': private method
initialize' called for #<Beginnerbudget:0x608da8> (NoMethodError)".
Why would this be a private method? How can I fix it?
class Beginnerbudget
attr_accessor :checking_amount
def initialize
puts "How much money do you have in your checking account?"
@checking_amount = checking_amount
checking_amount = gets.chomp.to_i
end
def rate_savings
if checking_amount >= 501
puts "You have $#{checking_amount} in your account. Keep up the good work!"
elsif checking_amount <= 500 && checking_amount >= 101
puts "You only have $#{checking_amount} in your account. Try and save a little more this month."
else checking_amount < 100
puts "Yikes, you only have $#{checking_amount} in your account! Sell a kidney quick!"
end
end
end
beginner_budget = Beginnerbudget.new
beginner_budget.initialize
beginner_budget.rate_savings
Heather Stone
5,784 PointsHeather Stone
5,784 PointsThanks very much!