Money
Open Exchange Rates¶ ↑
A gem that calculates the exchange rate using published rates from open-exchange-rates. Compatible with Money currency exchange.
Check api documentation
-
Live and historical exchange rates for 180 currencies.
-
Free plan hourly updates, with USD base and up to 1,000 requests/month.
-
Automatically caches API results to file or Rails cache.
-
Calculate pair rates.
-
Automatically fetches new data from API if data becomes stale when
ttl_in_seconds
option is provided. -
Support for black market and digital currency rates with
show_alternative
option.
Installation¶ ↑
Add this line to your application’s Gemfile:
gem 'money-open-exchange-rates'
And then execute:
bundle
Or install it yourself as:
gem install money-open-exchange-rates
Usage¶ ↑
require 'money/bank/open_exchange_rates_bank' # Memory store per default; for others just pass as argument a class like # explained in https://github.com/RubyMoney/money#exchange-rate-stores oxr = Money::Bank::OpenExchangeRatesBank.new(Money::RatesStore::Memory.new) oxr.app_id = 'your app id from https://openexchangerates.org/signup' # Update the rates for the current rates storage # If the storage is memory you will have to restart the server to be taken into # account. # If the storage is a database, file, this can be added to # crontab/worker/scheduler `Money.default_bank.update_rates` oxr.update_rates # (optional) # See https://github.com/spk/money-open-exchange-rates#cache for more info # Updated only when `refresh_rates` is called oxr.cache = 'path/to/file/cache.json' # (optional) # Set the seconds after than the current rates are automatically expired # by default, they never expire, in this example 1 day. # This ttl is about money store (memory, database ...) passed though # `Money::Bank::OpenExchangeRatesBank` as argument not about `cache` option. # The base time is the timestamp fetched from API. oxr.ttl_in_seconds = 86400 # (optional) # Set historical date of the rate # see https://openexchangerates.org/documentation#historical-data oxr.date = '2015-01-01' # (optional) # Set the base currency for all rates. By default, USD is used. # OpenExchangeRates only allows USD as base currency # for the free plan users. oxr.source = 'USD' # (optional) # Extend returned values with alternative, black market and digital currency # rates. By default, false is used # see: https://docs.openexchangerates.org/docs/alternative-currencies oxr.show_alternative = true # (optional) # Minified Response ('prettyprint') # see https://docs.openexchangerates.org/docs/prettyprint oxr.prettyprint = false # (optional) # Refresh rates, store in cache and update rates # Should be used on crontab/worker/scheduler `Money.default_bank.refresh_rates` # If you are using unicorn-worker-killer gem or on Heroku like platform, # you should avoid to put this on the initializer of your Rails application, # because will increase your OXR API usage. oxr.refresh_rates # (optional) # Force refresh rates cache and store on the fly when ttl is expired # This will slow down request on get_rate, so use at your on risk, if you don't # want to setup crontab/worker/scheduler for your application. # Again this is not safe with multiple servers and could increase API usage. oxr.force_refresh_rate_on_expire = true Money.default_bank = oxr Money.default_bank.get_rate('USD', 'CAD')
Refresh rates¶ ↑
With whenever¶ ↑
every :hour do runner "Money.default_bank.refresh_rates" # you will have to restart the server if you are using memory rate store runner "Money.default_bank.update_rates" end
With rake task¶ ↑
namespace :open_exchange_rates do desc "Refresh rates from cache and update rates" task :refresh_rates => :environment do Money.default_bank.refresh_rates # you will have to restart the server if you are using memory rate store Money.default_bank.update_rates end end
Cache¶ ↑
You can also provide a Proc
as a cache to provide your own caching mechanism perhaps with Redis or just a thread safe Hash
(global). For example:
oxr.cache = Proc.new do |v| key = 'money:exchange_rates' if v Thread.current[key] = v else Thread.current[key] end end
With Rails
cache example:
OXR_CACHE_KEY = "#{Rails.env}:money:exchange_rates".freeze oxr.ttl_in_seconds = 86400 oxr.cache = Proc.new do |text| if text Rails.cache.write(OXR_CACHE_KEY, text) else Rails.cache.read(OXR_CACHE_KEY) end end
To update the cache call Money.default_bank.refresh_rates
on crontab/worker/scheduler. This have to be done this way because the fetch can take some time (HTTP call) and can fail.
Full example configuration initializer with Rails and cache¶ ↑
require 'money/bank/open_exchange_rates_bank' OXR_CACHE_KEY = "#{Rails.env}:money:exchange_rates".freeze # ExchangeRate is an ActiveRecord model # more info at https://github.com/RubyMoney/money#exchange-rate-stores oxr = Money::Bank::OpenExchangeRatesBank.new(ExchangeRate) oxr.ttl_in_seconds = 86400 oxr.cache = Proc.new do |text| if text # only expire when refresh_rates is called or `force_refresh_rate_on_expire` # option is enabled # you can also set `expires_in` option on write to force fetch new rates Rails.cache.write(OXR_CACHE_KEY, text) else Rails.cache.read(OXR_CACHE_KEY) end end oxr.app_id = ENV['OXR_API_KEY'] oxr.show_alternative = true oxr.prettyprint = false # This can be removed if you have data to avoid http call on boot for production oxr.update_rates Money.default_bank = oxr
See also how to refresh and update rates
Tests¶ ↑
To avoid to hit the API we can use the cache option with a saved file like this:
OXR_CACHE_KEY = "#{Rails.env}:money:exchange_rates".freeze if Rails.env.test? oxr.cache = Rails.root.join("test/fixtures/currency-rates.json").to_s else oxr.ttl_in_seconds = 5.minutes.to_i oxr.cache = Proc.new do |text| if text Rails.cache.write(OXR_CACHE_KEY, text) else Rails.cache.read(OXR_CACHE_KEY) end end end
Pair rates¶ ↑
Unknown pair rates are transparently calculated: using inverse rate (if known), or using base currency rate to both currencies forming the pair.
Tests¶ ↑
bundle exec rake
Refs¶ ↑
Contributors¶ ↑
See GitHub.
License¶ ↑
The MIT License
Copyright © 2011-2023 Laurent Arnoud laurent@spkdev.net