Class: BigMoney::Exchange

Inherits:
Object
  • Object
show all
Defined in:
lib/big_money/exchange.rb,
lib/big_money/exchange/yahoo.rb

Overview

Find the exchange rate between two currencies.

Notes

No caching is done by default. You can set one though using anything that behaves like a Hash for example the moneta library.

Cache

require 'bigmoney/exchanage'
require 'moneta'
require 'moneta/memcache'

BigMoney::Exchange.cache = Moneta::Memcache.new(server: 'localhost', default_ttl: 3_600)

Direct Known Subclasses

Yahoo

Defined Under Namespace

Classes: ConversionError, Yahoo

Constant Summary collapse

@@services =
[]

Class Method Summary collapse

Class Method Details

.cacheObject



61
62
63
# File 'lib/big_money/exchange.rb', line 61

def cache
  @@cache ||= nil
end

.cache=(store) ⇒ Object



55
56
57
58
59
# File 'lib/big_money/exchange.rb', line 55

def cache=(store)
  raise "Cache object #{store.class} does not respond to [] and []=." \
    unless store.respond_to?(:'[]') and store.respond_to?(:'[]=')
  @@cache = store
end

.inherited(service) ⇒ Object

:nodoc:



66
67
68
# File 'lib/big_money/exchange.rb', line 66

def inherited(service) #:nodoc:
  @@services << service
end

.rate(from, to) ⇒ Object

Fetch the exchange rate between two currencies.

Parameters

from<BigMoney::Currency, .to_s>

Anything that BigMoney::Currency#find can find.

to<BigMoney::Currency, .to_s>

Anything that BigMoney::Currency#find can find.

Returns

BigDecimal



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/big_money/exchange.rb', line 78

def rate(from, to)
  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?
  rate = BigDecimal.new(service.read_rate(*exchange).to_s)

  cache[id] = rate if cache
  rate
end