class MGDMoney
Attributes
Public Class Methods
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
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
# 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
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
# 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
# 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
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 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 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
format the default output string format
# File lib/mgd_money.rb, line 120 def inspect "#{(convert_to_float(@amount)).to_s + " " + currency}" end