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 ?
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.
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
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
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…
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!
The only puts
is in the display_balance
method, which we don’t see being called.