Class: Money::Bank::UniRate
- Inherits:
-
VariableExchange
- Object
- VariableExchange
- Money::Bank::UniRate
- Defined in:
- lib/money/bank/uni_rate.rb
Overview
A Money::Bank implementation backed by the UniRate API (unirateapi.com).
It fetches a single-base rate snapshot from ‘GET /api/rates` and derives every cross-rate from it on demand, so one HTTP call covers all currency pairs. Derived cross-rates are computed per call (not cached in the store) so a TTL refresh can never serve a stale pair.
require "money/bank/uni_rate"
Money.default_bank = Money::Bank::UniRate.new(api_key: ENV["UNIRATE_API_KEY"])
Money.new(100_00, "USD").exchange_to("EUR") # => #<Money fractional:9200 currency:EUR>
Rates are fetched lazily on the first conversion and re-fetched once ttl_in_seconds has elapsed. Leave ttl_in_seconds as nil to fetch exactly once and cache for the life of the object; call #flush_rates to force a refresh on the next conversion.
Constant Summary collapse
- DEFAULT_BASE_URL =
"https://api.unirateapi.com"- DEFAULT_BASE_CURRENCY =
"USD"- DEFAULT_TIMEOUT =
30
Instance Attribute Summary collapse
-
#base_currency ⇒ Object
readonly
Returns the value of attribute base_currency.
-
#rates_updated_at ⇒ Object
readonly
Returns the value of attribute rates_updated_at.
-
#ttl_in_seconds ⇒ Object
Returns the value of attribute ttl_in_seconds.
Instance Method Summary collapse
-
#expired? ⇒ Boolean
True when rates have never been fetched, or
ttl_in_secondselapsed. -
#flush_rates ⇒ Object
Force a refresh on the next conversion (does not hit the network now).
-
#get_rate(from, to, _opts = {}) ⇒ BigDecimal
Exchange rate from
fromtoto, deriving cross-rates from the single-base snapshot. -
#initialize(api_key: ENV.fetch("UNIRATE_API_KEY", nil), base_currency: DEFAULT_BASE_CURRENCY, ttl_in_seconds: nil, base_url: DEFAULT_BASE_URL, timeout: DEFAULT_TIMEOUT, store: Money::RatesStore::Memory.new, &block) ⇒ UniRate
constructor
A new instance of UniRate.
-
#update_rates ⇒ Object
Fetch the latest snapshot and store base->currency rates.
Constructor Details
#initialize(api_key: ENV.fetch("UNIRATE_API_KEY", nil), base_currency: DEFAULT_BASE_CURRENCY, ttl_in_seconds: nil, base_url: DEFAULT_BASE_URL, timeout: DEFAULT_TIMEOUT, store: Money::RatesStore::Memory.new, &block) ⇒ UniRate
Returns a new instance of UniRate.
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/money/bank/uni_rate.rb', line 48 def initialize(api_key: ENV.fetch("UNIRATE_API_KEY", nil), base_currency: DEFAULT_BASE_CURRENCY, ttl_in_seconds: nil, base_url: DEFAULT_BASE_URL, timeout: DEFAULT_TIMEOUT, store: Money::RatesStore::Memory.new, &block) if api_key.nil? || api_key.to_s.empty? raise ArgumentError, "api_key is required (pass api_key: or set UNIRATE_API_KEY)" end @api_key = api_key @base_currency = base_currency.to_s.upcase @ttl_in_seconds = ttl_in_seconds @base_url = base_url @timeout = timeout @rates_updated_at = nil super(store, &block) end |
Instance Attribute Details
#base_currency ⇒ Object (readonly)
Returns the value of attribute base_currency.
39 40 41 |
# File 'lib/money/bank/uni_rate.rb', line 39 def base_currency @base_currency end |
#rates_updated_at ⇒ Object (readonly)
Returns the value of attribute rates_updated_at.
39 40 41 |
# File 'lib/money/bank/uni_rate.rb', line 39 def rates_updated_at @rates_updated_at end |
#ttl_in_seconds ⇒ Object
Returns the value of attribute ttl_in_seconds.
40 41 42 |
# File 'lib/money/bank/uni_rate.rb', line 40 def ttl_in_seconds @ttl_in_seconds end |
Instance Method Details
#expired? ⇒ Boolean
True when rates have never been fetched, or ttl_in_seconds elapsed.
80 81 82 83 84 85 |
# File 'lib/money/bank/uni_rate.rb', line 80 def expired? return true if rates_updated_at.nil? return false if ttl_in_seconds.nil? Time.now - rates_updated_at > ttl_in_seconds end |
#flush_rates ⇒ Object
Force a refresh on the next conversion (does not hit the network now).
102 103 104 105 |
# File 'lib/money/bank/uni_rate.rb', line 102 def flush_rates @rates_updated_at = nil self end |
#get_rate(from, to, _opts = {}) ⇒ BigDecimal
Exchange rate from from to to, deriving cross-rates from the single-base snapshot. Auto-refreshes when #expired?.
91 92 93 94 95 96 97 98 99 |
# File 'lib/money/bank/uni_rate.rb', line 91 def get_rate(from, to, _opts = {}) from_iso = Money::Currency.wrap(from).iso_code to_iso = Money::Currency.wrap(to).iso_code update_rates if expired? return BigDecimal(1) if from_iso == to_iso base_rate(to_iso) / base_rate(from_iso) end |
#update_rates ⇒ Object
Fetch the latest snapshot and store base->currency rates. Returns the raw { “EUR” => BigDecimal, … } map. Called lazily on the first conversion; safe to call manually to warm the cache.
71 72 73 74 75 76 77 |
# File 'lib/money/bank/uni_rate.rb', line 71 def update_rates rates = fetch_rates add_rate(base_currency, base_currency, 1) rates.each { |code, value| add_rate(base_currency, code, value) } @rates_updated_at = Time.now rates end |