class MGDMoney

Attributes

base_currency[RW]
conversion_factors[RW]
amount[R]
currency[R]

Public Class Methods

conversion_rates(base_currency, conversion_factors) click to toggle source

configure the currency rates on the singleton class with respect to a base currency @param [String] base_currency the currency used to determine conversion rates @param [Hash] conversion_factors the conversion rates for supported currencies @return [nil] @example MGDMoney.conversion_rates(“EUR”, {

    "USD" => 1.11,
    "Bitcoin" => 0.0047
})
# File lib/mgd_money.rb, line 45
def self.conversion_rates(base_currency, conversion_factors)
  unless base_currency.is_a?(String)                                                              # check the base currency is a string
      raise InvalidConversionDeclarationError, 'Currency must be a string'
  end
  
  unless conversion_factors.is_a?(Hash)                                                           # check the rates were specified as a hash
      raise InvalidConversionDeclarationError, 'Conversion rates not specified'
  end
  
  # check that the users supplied the currency as a string, and the conversion rate as a number
  conversion_factors.each do |key, value|
      unless key.is_a?(String) 
          raise InvalidConversionDeclarationError, 'Currency must be a string'
      end
      
      unless value.is_a?(Numeric)
          raise InvalidConversionDeclarationError, 'Conversion factor must be a number'
      end
  end
  
  self.base_currency = base_currency
  self.conversion_factors = conversion_factors
end
new(amount, currency) click to toggle source

instantiate new MGDMoney objects. @param [Numeric] amount the amount of the given currency @param [String] currency the user-defined currency string @return [MGDMoney] the resulting MGDMoney object @example fifty_eur = MGDMoney.new(50, 'EUR') => 50.00 EUR

# File lib/mgd_money.rb, line 20
def initialize(amount, currency)
  unless amount.is_a?(Numeric)                                                                    # the amount entered wasn't empty, but we still have to make sure it's a number
    raise InvalidDeclarationError, 'Amount must be a number'
  end
  
  unless currency.is_a?(String)                                                                   # the currency entered wasn't a string
    raise InvalidDeclarationError, 'Currency must be a string'
  end

  if currency.empty?
    raise InvalidDeclarationError, 'Currency must be specified'
  end

  @amount = amount                                                                                 # input is OK, so set the attributes
  @currency = currency
end

Public Instance Methods

*(val) click to toggle source
# File lib/mgd_money.rb, line 160
def *(val)
  if val.is_a?(Numeric)
    self.class.new(amount * val, currency)
  else
    raise UnsupportedOperationError, 'Can only multiply an MGDMoney object by a number'
  end
end
+(other_object) click to toggle source

perform arithmetic operations in two different currencies @param [MGDMoney] other_object the MGDMoney object we're doing the operation with @return [MGDMoney] @example fifty_eur + twenty_dollars = 68.02 EUR @example fifty_eur / 2 = 25 EUR

# File lib/mgd_money.rb, line 142
def +(other_object)
  if other_object.is_a?(MGDMoney)
    other_object = other_object.convert_to(currency)
    self.class.new(amount + other_object.amount, currency)
  else
    raise UnsupportedOperationError, '#{other_object} must be of type MGDMoney to compute a sum'
  end
end
-(other_object) click to toggle source
# File lib/mgd_money.rb, line 151
def -(other_object)
  if other_object.is_a?(MGDMoney)
    other_object = other_object.convert_to(currency)
    self.class.new(amount - other_object.amount, currency)
  else
    raise UnsupportedOperationError, '#{other_object} must be of type MGDMoney to compute a difference'
  end
end
/(val) click to toggle source
# File lib/mgd_money.rb, line 168
def /(val)
  if val.is_a?(Numeric)
    self.class.new(amount / val, currency)
  else
    raise UnsupportedOperationError, 'Can only divide an MGDMoney object by a number'
  end
end
<=>(other_object) click to toggle source

compare different currencies (using Comparable) in this case, we only care about comparing the amounts of each MGDMoney object @param [MGDMoney] other_object the object to compare to @return [FixNum] @example twenty_dollars == MGDMoney.new(20, 'USD') # => true @example twenty_dollars == MGDMoney.new(30, 'USD') # => false @example fifty_eur_in_usd = fifty_eur.convert_to('USD') @example fifty_eur_in_usd == fifty_eur => true

# File lib/mgd_money.rb, line 184
def <=>(other_object)
  if other_object.is_a?(MGDMoney)
    other_object = other_object.convert_to(currency)
    convert_to_float(amount) <=> convert_to_float(other_object.amount)                            # convert to float so we're only comparing up to 2 decimal places
  else
    raise UnknownObjectError, 'Unknown destination object type (must be type MGDMoney)'
  end
end
convert_to(currency) click to toggle source

convert to a different currency, returning a new MGDMoney object. requires both source and destination currency to be defined by MGDMoney.conversion_rates (otherwise rate not known) @param [String] currency the desired currency after conversion @return [MGDMoney] the new MGDMoney object representing the converted currency @example fifty_eur.convert_to('USD') # => 55.50 USD

# File lib/mgd_money.rb, line 75
def convert_to(currency)
  if currency == self.currency                                                                    # source and destination currencies match
    self                                                                                          # no conversion needed
  else
    factors = MGDMoney.conversion_factors                                                         # get the user-specified conversion rates

    if self.currency == MGDMoney.base_currency                                                    # user specified this currency as the base currency
      if factors.keys.include?(currency)                                                          # ensures user did actually specify this conversion
        conversion_factor = factors["#{currency}"]                                                # look up the conversion rate from the Hash
        MGDMoney.new(self.amount*conversion_factor, currency)                                     # return the converted value as a new MGDMoney object
      else                                                                                        # conversion rate wasn't specified, so raise an error
        raise UnknownConversionError, 'Conversion rate not specified for this currency'
      end
    elsif currency == MGDMoney.base_currency                                                      # user specified desired currency as the base currency
      if factors.keys.include?(self.currency)                                                     # look for the source currency in the user-specified Hash
        conversion_factor = 1 / factors["#{self.currency}"]                                       # if found, invert that b/c the Hash is specified in opposite way
        MGDMoney.new(self.amount*conversion_factor, currency)                                     # return the converted value as a new MGDMoney object
      else                                                                                        # conversion rate wasn't specified, so raise an error
        raise UnknownConversionError, 'Conversion rate not specified for this currency'
      end
    else
      if factors.keys.include?(currency)                                                          # neither source nor desired currency are the base currency
        conversion_factor = factors["#{self.currency}"] * factors["#{currency}"]                  # compare them to each other
        MGDMoney.new(self.amount*conversion_factor, currency)                                     # return the converted value as a new MGDMoney object
      else                                                                                        # conversion rate wasn't specified, so raise an error
        raise UnknownConversionError, 'Conversion rate not specified for this currency'
      end
    end
  end
end
convert_to_float(amount) click to toggle source

convert the given number to its float representation. this makes all the arithmetic possible @param [Numeric] amount the amount to convert @return [BigDecimal] @example convert_to_float(twenty_dollars.amount)

# File lib/mgd_money.rb, line 129
def convert_to_float(amount)
  if amount.to_s.empty?                                                                         # entered amount was "" (empty string), return 0
    0
  else
    '%.2f' % amount
  end
end
inspect() click to toggle source

format the default output string format

# File lib/mgd_money.rb, line 120
def inspect
  "#{(convert_to_float(@amount)).to_s + " " + currency}"
end