Красимир обнови решението на 12.01.2013 19:53 (преди около 12 години)
+require 'bigdecimal'
+require 'bigdecimal/util'
+
+class ExchangeRate
+ class Unknown < RuntimeError
+ end
+
+ def initialize
+ @rates = {}
+ end
+
+ def set(from_currency, to_currency, rate)
+ @rates[[from_currency, to_currency]] = rate
+ @rates[[to_currency, from_currency]] = 1 / rate
+ end
+
+ def get(from_currency, to_currency)
+ if (from_currency == to_currency)
+ 1
+ else
+ @rates[[from_currency, to_currency]]
+ end
+ end
+
+ def convert(from_currency, to_currency, amount)
+ rate = get(from_currency, to_currency)
+ if rate.nil?
+ raise Unknown, "Unknown exchange rate requested"
+ end
+ amount * rate
+ end
+end
+
+class Money
+ include Comparable
+
+ class IncompatibleCurrencies < RuntimeError
+ end
+
+ attr_reader :amount, :currency
+
+ def initialize(amount, currency)
+ @amount = amount.round(2)
+ @currency = currency
+ end
+
+ def to_s
+ "#{"%.2f" % @amount} #@currency"
+ end
+
+ def in(currency, exchange_rate)
+ converted_amount = exchange_rate.convert(@currency, currency, @amount)
+ Money.new(converted_amount, currency)
+ end
+
+ def *(other)
+ if other.is_a?(Numeric)
+ Money.new(@amount * other, @currency)
+ else
+ raise ArgumentError, "Money can be multiplied only by numbers."
+ end
+ end
+
+ def /(other)
+ if other.is_a?(Numeric)
+ Money.new(@amount / other, @currency)
+ else
+ raise ArgumentError, "Money can be divided only by numbers."
+ end
+ end
+
+ def +(other)
+ if other.is_a?(Money)
+ if compatible?(other)
+ Money.new(amount + other.amount, currency)
+ else
+ raise IncompatibleCurrencies, "Money can be added only if the currencies match"
+ end
+ else
+ raise ArgumentError, "Money can only be added to another money"
+ end
+ end
+
+ def -(other)
+ if other.is_a?(Money)
+ if compatible?(other)
+ Money.new(amount - other.amount, currency)
+ else
+ raise IncompatibleCurrencies, "Money can be subtracted only if the currencies match"
+ end
+ else
+ raise ArgumentError, "Money can only be subtracted from another money"
+ end
+ end
+
+ def compatible?(other)
+ other.is_a?(Money) and currency == other.currency
+ end
+
+ def <=>(other)
+ if other.is_a?(Money)
+ if compatible?(other)
+ amount <=> other.amount
+ else
+ raise IncompatibleCurrencies, "For money comparision the currencies should match"
+ end
+ else
+ raise ArgumentError, "Money can only be compared with other money"
+ end
+ end
+end