Станислав обнови решението на 11.01.2013 11:05 (преди около 12 години)
+require 'bigdecimal'
+require 'bigdecimal/util'
+
+class ExchangeRate
+
+ class Unknown < RuntimeError
+ end
+
+ def initialize
+ @exchange_rates = {}
+ end
+
+ def set(from_currency, to_currency, rate)
+ @exchange_rates[hash from_currency, to_currency] = rate
+ @exchange_rates[hash to_currency, from_currency] = 1.to_d / rate
+ end
+
+ def get(from_currency, to_currency)
+ @exchange_rates[hash from_currency, to_currency]
+ end
+
+ def convert(from_currency, to_currency, amount)
+ 1.to_d if from_currency == to_currency
+ amount * get(from_currency, to_currency)
+ end
+
+ private
+
+ def hash(from_currency, to_currency)
+ "#{from_currency} -> #{to_currency}"
+ end
+
+end
+
+class Money
+ include Comparable
+
+ class IncompatibleCurrencies < RuntimeError
+ end
+
+ attr_reader :amount, :currency
+
+ def initialize(amount, currency)
+ @amount, @currency = amount, currency
+ end
+
+ def to_s
+ "%.2f %.3s" % [amount.round(2).to_s('F'), currency]
+ end
+
+ def in(currency, exchange_rate)
+ new_amount = exchange_rate.convert @currency, currency, amount
+ Money.new new_amount, currency
+ end
+
+ def *(number)
+ raise ArgumentError unless number.kind_of? Numeric
+ Money.new amount * number, currency
+ end
+
+ def /(number)
+ raise ArgumentError unless number.kind_of? Numeric
+ Money.new amount / number, currency
+ end
+
+ def +(money)
+ raise ArgumentError unless money.kind_of? Money
+ raise IncompatibleCurrencies unless currency == money.currency
+ Money.new amount + money.amount, currency
+ end
+
+ def -(money)
+ raise ArgumentError unless money.kind_of? Money
+ raise IncompatibleCurrencies unless currency == money.currency
+ Money.new amount - money.amount, currency
+ end
+
+ def <=>(money)
+ raise ArgumentError unless money.kind_of? Money
+ raise IncompatibleCurrencies unless currency == money.currency
+ amount - money.amount
+ end
+
+end