raphael-allard
raphael-allard

Reputation: 319

How can I write a method parameter when I'm calling another method?

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

Answers (3)

Schwern
Schwern

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

Amit Patel
Amit Patel

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

kgilpin
kgilpin

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

Related Questions