lib/big_money/exchange.rb in big_money-1.1.0 vs lib/big_money/exchange.rb in big_money-1.2.0
- old
+ new
@@ -34,17 +34,35 @@
end # Exchangeable
include Exchangeable
# Find the exchange rate between two currencies.
#
- # Be aware no caching is done at all at the moment.
- #--
- # TODO: Moneta would be ideal for this.
+ # ==== Notes
+ #
+ # No caching is done by default. You can set one though using anything that behaves like a Hash for example the
+ # moneta library.
+ #
+ # ==== Example
+ #
+ # require 'bigmoney/exchanage'
+ # require 'moneta/memcache'
+ #
+ # BigMoney::Exchange.cache = Moneta::Memcache.new('localhost', default_ttl: 3_600)
class Exchange
class ConversionError < StandardError; end
class << self
+ def cache=(store)
+ raise "Cache object #{store.class} does not respond to [] and []=." \
+ unless store.respond_to?(:'[]') and store.respond_to?(:'[]=')
+ @@cache = store
+ end
+
+ def cache
+ @@cache ||= nil
+ end
+
@@services = []
def inherited(service) #:nodoc:
@@services << service
end
@@ -60,15 +78,23 @@
exchange = []
exchange << (Currency.find(from) or raise ArgumentError.new("Unknown +from+ currency #{from.inspect}."))
exchange << (Currency.find(to) or raise ArgumentError.new("Unknown +to+ currency #{to.inspect}."))
return BigDecimal.new(1.to_s) if exchange.uniq.size == 1 || exchange.find{|c| c == Currency::XXX}
+ id = exchange.map{|c| c.code}.join(':')
+ if cache && rate = cache[id]
+ return rate
+ end
+
service = @@services.reverse.find do |service|
!!exchange.reject{|c| service.currencies.include?(c)}
end
service or raise ConversionError # TODO: Message?
- BigDecimal.new(service.read_rate(*exchange).to_s)
+ rate = BigDecimal.new(service.read_rate(*exchange).to_s)
+
+ cache[id] = rate if cache
+ rate
end
protected
# Exchange rate from the first currency to the second.
#