FAQ: Banking on Ruby - Well Done!

So I am still confused on why it works when display_balance has
if pin_number == pin

and if all three are pin_number == @pin
it doesn’t work ?

All three methods that check the pin_number should be accessing it through the pin method for consistency.

But somehow leaving the two lower methods with if pin_number == @pin

when the first method has if pin_number == pin – works and all three methods run as if given the correct pin

The purpose of having a method to get @pin is to reduce exposure of the instance variable. The only place we should see @pin is in that method. This gives genuine consistency.

In case I may have called @pin a private variable, belay that. pin is a private method. @pin is not private. The fact that the method is private means it can only be invoked by methods, not instances.

This topic is one that needs extra literature to support it. One does not wish to mislead, but presently I lack the time to source out some good reading. Search for all the Ruby docs you can find that are officially sanctioned, including Wikis or Wikibooks.

Read the specs and study the demos. It’s good that you are still a little confused. That you are sticking with it will go a long way to reinforcing the concepts of class vs instance variables, and private vs public methods. Don’t leave this topic until you are really comfortable else it may trip you up down the road. Now is the time to take this opportunity to dig in for info, facts, demos, interpretations, &c.

1 Like

ruby private public class - Google Search

Hi guys ! I need your help please.

Here my code :

class Account
  attr_reader :name, :balance
  def initialize(name, balance=100)
    @name = name
    @balance = balance
  end

  def display_balance
    pin_check
    puts "Hello #{name} ! Your balance is $ #{balance}."
  end

  private
  def pin
    @pin = 1234
  end

  def pin_check(pin_number)
    if pin_number == @pin
      puts "Access authorized: pending transaction"
    else puts "Access denied: wrong PIN"
    end
  end
end

checking_account = Account.new("Saitama", 20_000)
checking_account.display_balance(1234)

What I’m trying to do is to automate the “pin check” in the other variables. My problem here is with the pin_check argument : of course, the program is expecting an argument from this method but on my last line of code, I don’t know how to give it the 1234 argument expected… As you can see, I’m giving it to the display_balance variable. Is there any way to write correctly this last line of code to link display_balance and pin_check so as to giving the good argument to pin_check ?

I hope my question makes sense ! Thanks for your help !

pin_check takes one positional argument so the call should have one.

The instance attribute, @pin is defined in the pin method.

if pin_number == pin

Something that arises as an issue is the fact that nothing prevents the balance from displaying (assuming it does) regardless the outcome of the pin check.

Hi mtf !

Thanks for your answer.

Ok that’s what I was thinking ! But how can I write that ? I can’t just write this, correct ?

  def display_balance
    pin_check(1234)
    puts "Hello #{name} ! Your balance is $ #{balance}."
  end

I need to write it when I’m doing my checking_account I guess. But how can I write that ? I know the following code won’t work but is something like this could work ?

checking_account.display_balance.pin_check(1234)

Yes you’re right ! I have to figure it out and find out how to do that :slight_smile:

1 Like

display_balance will need to take an argument so it has the pin_number to pass along.

When we look at the method call, it contains one argument, so this method needs to receive that argument with a parameter.

def display_balance(pin_number)

end
1 Like

How did you come up with this - pin_correct?

So, I have a problem, i do not see anything in the Console, so i have no idea what I’ve just gone through.
I mean , i pass the excercises but since there is no results i can check and verify what is happening behind, it is pretty hard to realize how this modules, class, public, private, @ , and that works.
I think there should be an update on this excercise, so users can check what is happening, and be able to understand how our code works, but if there is no output… pretty hard to learn sth.
*Maybe i have an issue with my console, but I tried also on Firefox and the output is equal: Blank, no response.

I keep getting incorrect pin when I try to deposit. I’m not sure how though…

class Account attr_reader :name attr_reader :balance def initialize(name, balance=100) @name = name @balance = balance end public def display_balance(pin_number) if pin_number == @pin puts "Balance: $#{@balance}." else puts pin_error end end public def deposit(pin_number, amount) if pin_number == @pin @balance += amount puts "Deposited: $#{amount}\n Your new balance: $#{@balance}" else puts pin_error end end def withdraw(pin_number, amount) if pin_number == @pin @balance -= amount puts "Withdrew #{amount}." else puts pin_error end end private def pin @pin = 1234 end def pin_error return "Access denied: incorrect PIN." end end checking_account = Account.new("Sam", 700) checking_account.deposit(1234, 800)

Actually, if you test your class, you will see that you get the incorrect pin error for all of your withdraw, deposit and display_balance methods even though the entered pin may be correct.
The problem lies in the condition pin_number == @pin
This condition checks whether the provided pin number is the same as the instance variable @pin. But, we have not initialized this instance variable. Instead, @pin is given a value in the method pin.
If you edit the condition for all your methods to be pin_number == pin, then your code will work fine. The pin on the right side of the equality comparison is actually calling the method pin (not the variable). Within the pin method, first @pin is given the value 1234 and then since it is the only line in the method, this value is implicitly returned, so the condition pin_number == pin will actually receive the correct value.
Incidentally, the “Get UnStuck” solutions provided by Codecademy for the withdraw and display_balance method exercises are incorrect currently as they too use @pin in the condition. If you test out their code, you will see that correct pins are rejected. If we wish to use @pin in the condition, then we must make sure that the instance variable is initialized before the condition is executed.

I managed to do it with three different class and a module, if you wanna have a look at it :

module CheckEqual
  def checkEqual(first_value, second_value)
    first_value == second_value
  end
end

class Account
  include CheckEqual
  attr_reader :name, :balance
  def initialize(name, balance=100)
    @name = name
    @balance = balance
  end

  private
  def pin
    @pin = 1234
  end
  def pin_error
    "Access denied: incorrect PIN."
  end
end

class SavingsAccount < Account
    def initialize(name, balance=100)
      super
    end
    def withdraw(pin_number, amount)
      if checkEqual(pin_number, pin)
        if @balance - amount < 0
          puts "You don't have enough on your account."
        else
          @balance -= amount
        end
      else
        puts pin_error
      end
  end

  def deposit(pin_number, amount)
    if checkEqual(pin_number, pin)
      @balance += amount
    else
      puts pin_error
    end
  end
end

class CheckingAccount < SavingsAccount
    def initialize(name, balance)
      super
    end
  def display_balance(pin_number)
    puts checkEqual(pin_number, pin) ? "Balance: $#{@balance}." : pin_error
  end
end

creating_account = Account.new("Anouchka", 500)

savings_account = SavingsAccount.new(creating_account.name, creating_account.balance)
savings_account.deposit(1023, 10000)
# => Access denied: incorrect PIN
savings_account.withdraw(1234, 10)
savings_account.withdraw(1234, 500)
# => You don't have enough on your acount.

checking_account = CheckingAccount.new(savings_account.name, savings_account.balance)
checking_account.display_balance(1234)
# => Balance: $490.

I added functions with balance, deposit and withdraw using gets.chomp to enter commands (like selecting options on the ATM screen)

The PIN comparison took some getting used to - language I’m used to would do something like:

private PIN = 1234

function deposit( pin_number ){
 if this.PIN == pin_number {
 blah, blah
} else
 blah, blah
}
}

Here’s my Ruby code anywho:

class Account

  attr_reader :name
  attr_reader :balance

  def initialize name, balance=100
    @name = name
    @balance = balance
  end

  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 @balance < amount.to_i
        puts "Insufficient funds."
      else
        @balance -= amount.to_i
        puts "Withdrew $#{amount}. New balance: $#{@balance}."
      end
    else
      puts pin_error
    end
  end

  def deposit pin_number, amount
    if pin_number == pin
      @balance += amount.to_i
      puts "Deposit successful. Your new balance is $#{@balance}."
    else
      puts pin_error
    end
  end

  private

  def pin
    @pin = 1234
  end

  def pin_error
    return "Access denied: incorrect PIN."
  end

end

class CheckingAccount < Account; end
class SavingsAccount < Account; end

checking_account = CheckingAccount.new("Lewis",1_000_000_000)

puts "Enter an instruction (eg, 'add' or 'balance')"
cmd = gets.chomp

case cmd
  when "add"
    puts "Enter an ammount to deposit"
    deposit = gets.chomp
    checking_account.deposit(1234,deposit)
  when "balance"
    checking_account.display_balance(1234)
  when "withdraw"
    puts "Enter the amount to withdraw"
    withdraw = gets.chomp
    checking_account.withdraw(1234,withdraw)
  else
    puts "Unknown command"
end

I thought about refactoring all the PIN checks - if pin_number == pin business but, if you extracted that out into another method, you only end up passing the PIN to it anyway so don’t really gain much!

Hi!

Does anyone know why my code doesn’t puts anything to the console?

Thanks

The only puts is in the display_balance method, which we don’t see being called.

2 Likes