Reputation: 319
Sorry I'm a big beginner in Ruby and I don't know if my title and my question makes sense...
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
What I’m trying to do is to automate the “pin check” in the other methods. My problem here is with the pin_check parameter : 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… 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 was thinking maybe write something like that but I know it doesn't work :
checking_account.display_balance.pin_check(1234)
How can I link both ? Thank you so much for your help !
Upvotes: 0
Views: 63
Reputation: 165536
You can pass the pin into display_balance
and pass it through to pin_check
.
def display_balance(pin:)
pin_check(pin)
puts "Hello #{name} ! Your balance is $ #{balance}."
end
checking_account = Account.new("Saitama", 20_000)
checking_account.display_balance(pin: 1234)
Note that because pin_check
only prints, the balance will always be displayed. You probably want it to raise an exception.
def pin_check(pin_number)
raise "Access denied: wrong PIN" unless pin_number == pin
end
Note that it's pin_number
and not @pin_number
. pin_number
is the variable containing what was passed into pin_check
. @pin_number
is an "instance variable" stored on the object.
Update: Also note that it's pin
and not @pin
. @pin
will not be set unless pin
is called.
It's probably better to pass the pin in once during object initialization and raise an error if it does not match. This guarantees no operations can happen without a pin check.
attr_reader :name, :balance
def initialize(name:, balance: 100, pin:)
@name = name
@balance = balance
pin_check(pin)
end
private def pin_check(pin_try)
raise "Access denied: wrong PIN" unless pin_try == @pin
end
checking_account = Account.new(name: "Saitama", balance: 20_000, pin: 1234)
checking_account.display_balance
Note that I'm using named arguments. This lets you add arguments, even optional ones, without having to remember what argument 3 was.
Upvotes: 1
Reputation: 15985
You basically need to pass around pin wherever needs. You can pass pin to following method
def display_balance(pin)
pin_check(pin)
puts "Hello #{name} ! Your balance is $ #{balance}."
end
Now you can call checking_account.display_balance(1234)
Upvotes: 0
Reputation: 2226
I think the simplest thing to do would be to perform pin_check
in the constructor, and then you don't have to worry about doing it for all methods. pin_number
would be a constructor argument.
Another option would be to use something like ActiveModel::Validations
, and add a validator that checks the PIN. Any client of your class would need to know to validate
before performing any of the actions. That is the pattern used by Rails facilities such as ActiveRecord.
Upvotes: 1