FAQ: Banking on Ruby - Well Done!

This community-built FAQ covers the “Well Done!” exercise from the lesson “Banking on Ruby”.

Paths and Courses
This exercise can be found in the following Codecademy content:

Learn Ruby

FAQs on the exercise Well Done!

There are currently no frequently asked questions associated with this exercise – that’s where you come in! You can contribute to this section by offering your own questions, answers, or clarifications on this exercise. Ask or answer a question by clicking reply (reply) below.

If you’ve had an “aha” moment about the concepts, formatting, syntax, or anything else with this exercise, consider sharing those insights! Teaching others and answering their questions is one of the best ways to learn and stay sharp.

Join the Discussion. Help a fellow learner on their journey.

Ask or answer a question about this exercise by clicking reply (reply) below!

Agree with a comment or answer? Like (like) to up-vote the contribution!

Need broader help or resources? Head here.

Looking for motivation to keep learning? Join our wider discussions.

Learn more about how to use this guide.

Found a bug? Report it!

Have a question about your account or billing? Reach out to our customer support team!

None of the above? Find out where to ask other questions here!

This is how I did it. Would like to see how everyone else did it! :star_struck:

class Account
  attr_reader :name, :balance
  def initialize(name, balance= 100)
    @name = name
    @balance = balance
  end
  def display_balance(pin_number)
    puts pin_number == @pin ? "Balance:$#{@balance}." : pin_error
  end
  def withdraw(pin_number, amount)
    if pin_number == pin
      @balance -= amount
      puts amount <= @balance ? "Withdrew #{amount}. New balance: $#{@balance}." : overdraw
    else
      pin_error
    end
  end
    def overdraw
      "You're overdrawing"
    end
  def deposit(added)
    @balance += added
    puts "You added $#{added}. Your new balance is $#{@balance}"
  end 
  private
  def pin
    @pin = 1234
  end
  def pin_error
    "Access denied: incorrect PIN."
  end
end

checking_account = Account.new("Hanseo", 1000_000)
checking_account.withdraw(1234, 500)
checking_account.deposit(300)
class SavingsAccount < Account; end
1 Like

I did mine so that it doesn’t allow you to withdraw if the amount is more than the balance :slight_smile:

I’m confused by something though - why is it that on line 11 (going by your code) we have to refer to pin as “pin” and not “@pin”?, it seems inconsistent to me since on line 8 we used “@pin”. I may be being stupid, but I really can’t get my head around it, since surely just putting “pin” is just the method name and doesn’t actually return the value of @pin?

I hope that makes sense, I just don’t understand because it was the same on the code I wrote and if I changed it it wouldn’t work!!

  def pin
    @pin = 1234
  end

Yeah I see that but I’m confused as to why on one statement it has to be referred to as “@pin” when the other is just referred to as “pin”, but neither of them work if you change it to the other way?

(See lines 8 and 11)

We’ll need to see your complete code to see where the problem is. In this example only the pin method is used…

class Account
  attr_reader :name, :balance
  def initialize(name, balance=100)
    @name = name
    @balance = balance
  end
  public
  def display_balance(pin_number)
    puts pin_number == pin ?
      "Balance: $#{balance}." : pin_error
  end
  def withdraw(pin_number, amount)
    if pin_number == pin
      if @balance >= amount
        @balance -= amount
        puts "Withdrew #{amount}. New balance: $#{@balance}."
      else
        puts "Insufficient funds to cover withdrawal."
      end
    else
      puts pin_error
    end
  end
  def deposit(pin_number, amount)
    if pin_number == pin
      @balance += amount
      puts "Deposit #{amount}. New balance: $#{@balance}."
    else
      puts pin_error
    end
  end
  private
  def pin
    @pin = 1234
  end
  def pin_error
    "Access denied: incorrect PIN."
  end
end
checking_account = Account.new("Wee Gillis", 1_000_000)
checking_account.display_balance(1234)
checking_account.withdraw(1234,1_000)
checking_account.withdraw(1234,1_000_000)
checking_account.deposit(1234, 100_000)
Balance: $1000000.
Withdrew 1000. New balance: $999000.
Insufficient funds to cover withdrawal.
Deposit 100000. New balance: $1099000.
1 Like

This is the part I’m referring to (from the first comment)

Your highlighter is covering some code. Is that a ternary expression like in my earlier example? Please post your actual code, not a screenshot.

As I said, I’m talking about the code that has been posted in this thread. The post I replied to initially. The full code is there if you want to look at it. Don’t worry if you’re not sure what I’m asking, it doesn’t matter, I can get along fine without knowing :slight_smile:

If you are asking ‘why?’ then I can’t answer. Ask ‘how?’ and my post above shows that we can use the methd, exclusively, anytime we need to reference the pin.

Consider the first time this method is called on an instance. Where in that instance is @pin defined? It’s not. It gets defined by the pin method.

That’s fine, I can see why “pin” alone works. In which case, I don’t see why “@pin” worked. I was basically just wondering why/how it seemed to work different ways in each method. You seem to be misunderstanding my query, but as I said, it’s not that important, so I’ll leave it and find out for myself later down the line. No matter, thank you anyway.

It would work if the method was called previous to it being referenced. The order of instance calls would affect this.

Flush your cache and call for the balance before anything else on a new instance. Will @pin work then? I’m suspecting not since it is not yet defined. There is no attribute, @pin.

1 Like

after issues when using @pin to compare with pin_number variables and some issues with complicated if/else conditions in withdraw. this is what I did.

class Account
  attr_reader :name
  attr_reader :balance
  def initialize(name, balance=100)
    @name = name
    @balance = balance
  end
  
  public
  
  def deposit(pin_number, amount)
    if pin_number == pin 
      @balance += amount 
      puts "You have deposited $#{amount}. New balance $#{@balance}." 
      else 
      pin_error
    end 
  end
  
  def display_balance(pin_number)
    puts pin_number == pin ? "Balance: $#{@balance}." : pin_error
  end
  
  def withdraw(pin_number,amount)
		if pin_number == pin 
      if  @balance > amount 
        @balance -= amount
      puts "Withdrew #{amount}." 
      else 
        overdraw
      end
   else
      pin_error
    end
  end

  private
  def pin
    @pin = 1234
  end
  
  def pin_error
   "Access denied: incorrect PIN."
  end
  
  def overdraw
    "You are overdrawing!"
  end 
    
  
end

class SavingsAccount < Account
  private
  def pin
    @pin = 2345
  end
end

checking_account = Account.new("Zoe", 200)
checking_account.withdraw(1234, 50)
checking_account.display_balance(1234)

savings = SavingsAccount.new("Carlos", 300)

savings.display_balance(2345)
savings.withdraw(2345, 600)

I went further to refactor my code and make it more DRY by outsources certain jobs to methods e.g. checking if pin is correct.

class Account
  attr_reader :name
  
  def initialize(name, pin, balance=100,)
    @name = name
    @pin = pin
    @balance = balance
  end
  
  def deposit(pin_number, amount)
    if pin_correct?(pin_number)
      @balance += amount 
      display_deposit  
    else 
     display_pin_error
    end 
  end
  
  def display(pin_number)
   if pin_correct?(pin_number)
     display_balance
   else
     display_pin_error
   end 
  end
  
  def withdraw(pin_number,amount)
    if pin_correct?(pin_number)
      if  @balance > amount 
        @balance -= amount
      	puts "Withdrew #{amount}." 
      else 
        display_overdraw_error
      end
    else
       display_pin_error
    end
  end

  private
  
  def display_pin_error
   puts "Access denied: incorrect PIN."
  end
  
  def display_overdraw_error
    puts "You are overdrawing!"
  end 
  
  def display_withdraw
    puts "You withdrew #{amount}. Your new balance is #{@balance}"
  end
  
  def display_balance
    puts "Your balance is #{@balance}."
  end 
  
  def display_deposit
    puts "You have deposited #{amount}.  Your new balance is #{@balance}."
  end 
  
  def pin_correct?(pin_number)
    pin_number == @pin
  end 
end

class SavingsAccount < Account

end

checking_account = Account.new("Zoe", 1234, 200)
checking_account.withdraw(1234, 50)
checking_account.display(1234)
checking_account.deposit(134, 60)

savings = SavingsAccount.new("Carlos", 1234, 300)

savings.display(1234)
savings.withdraw(2345, 600)

#not full code

private
def pin
@pin = 1234
end
def pin_error
return “Access denied: incorrect PIN.”
end

public
def display_balance(pin_number)
if pin_number == @pin
puts “Balance: $#{@balance}”
else
puts pin_error
end
end

def withdraw(pin_number,amount)
if pin_number == @pin
if amount > balance
puts “Warning: Overwithdrawal. Try again.”
else
@balance -= amount
puts “Withdrew #{amount}. New balance: #{@balance}.”
end
else
puts pin_error
end
end

def deposit(pin_number,amount)
if pin_number == pin
@balance += amount
puts “Deposited #{amount}. New balance: #{@balance}”
else
puts pin_error
end
end

checking_account = Account.new(“Account”,4000)

checking_account.display_balance(1234)
checking_account.withdraw(1234,500)
checking_account.deposit(1234,600)

I understand why you need to reference the pin method to access “1234”

And I see if I use ==@pin for display_balance I get pin_error for all three method calls

However if I use ==pin for display_balance and leave the withdrawal and deposit methods with ==@pin, all three work

So I am curious how the code stores/remembers pin from the first method when all three call to check pin_number?

if pin_number == pin

refers to the method, which returns the value of @pin.

so if an earlier method calls pin method, how does that let the other methods access it?

They are accessing the instance variable directly, rather than getting it with the method.

Shouldn’t they not be able to because it’s private?

Private variables can still be accessed by methods, just not from the outside.