0

I am reading the money gem source code and I can't seem to understand the constructor:

def initialize(obj, currency = Money.default_currency, bank = Money.default_bank)
    @fractional = obj.respond_to?(:fractional) ? obj.fractional : as_d(obj)
    @currency   = obj.respond_to?(:currency) ? obj.currency : Currency.wrap(currency)
    @currency ||= Money.default_currency
    @bank       = obj.respond_to?(:bank) ? obj.bank : bank
  end

Why are we testing if obj has a "fractional" method? When does that return true and when does it return false? Same questions for currency in the next line.

Thanks

Ahmad Al-kheat
  • 1,805
  • 2
  • 16
  • 25

1 Answers1

1

These checks are to allow passing various kinds of things as the obj and act intelligently. It's an example of using "duck typing"--we don't care what it actually is, but if it quacks like a duck, treat it like one for quacking purposes. From the source comments:

# @param [Object] obj Either the fractional value of the money,
# a Money object, or a currency. (If passed a currency as the first
# argument, a Money will be created in that currency with fractional value
# = 0.
# @param [Currency, String, Symbol] currency The currency format.
# @param [Money::Bank::*] bank The exchange bank to use.
#
# @example
# Money.new(100) #=> #<Money @fractional=100 @currency="USD">
# Money.new(100, "USD") #=> #<Money @fractional=100 @currency="USD">
# Money.new(100, "EUR") #=> #<Money @fractional=100 @currency="EUR">

The intent seems to be that you may want to pass a Money object: if so, you want to use the same fractional and currency. If it doesn't have those methods, treat it like a number.

Eric Hughes
  • 831
  • 6
  • 19