class Money::Bank::CurrencylayerHistoricalBank
CurrencylayerBank base class rubocop:disable Metrics/ClassLength
Constants
- CL_HISTORICAL_URL
CurrencylayerBank historical url
- CL_SECURE_URL
CurrencylayerBank secure url
- CL_SOURCE
Default base currency
- CL_URL
CurrencylayerBank url
Attributes
API must have a valid access_key
Cache accessor, can be a String or a Proc
Fetch historical rates on selected date
Parsed CurrencylayerBank result as Hash
Rates expiration Time
Use https to fetch rates from CurrencylayerBank CurrencylayerBank only allows http as connection for the free plan users.
Seconds after than the current rates are automatically expired
Public Instance Methods
Fetch new rates if cached rates are expired @return [Boolean] true if rates are expired and updated from remote
# File lib/money/bank/currencylayer_historical_bank.rb, line 137 def expire_rates! if expired? update_rates(true) true else false end end
Check if rates are expired @return [Boolean] true if rates are expired
# File lib/money/bank/currencylayer_historical_bank.rb, line 148 def expired? return true if historical_date rates_expiration ? rates_expiration <= Time.now : true end
Override Money
`get_rate` method for caching @param [String] from_currency Currency ISO code. ex. 'USD' @param [String] to_currency Currency ISO code. ex. 'CAD'
@return [Numeric] rate.
# File lib/money/bank/currencylayer_historical_bank.rb, line 103 def get_rate(from_currency, to_currency, opts = {}) # rubocop:disable all @historical_date = Date.parse(opts[:date].to_s).strftime("%Y-%m-%d") if opts[:date] expire_rates! rate = super unless rate # Tries to calculate an inverse rate inverse_rate = super(to_currency, from_currency, opts) if inverse_rate rate = 1.0 / inverse_rate add_rate(from_currency, to_currency, rate) end end unless rate # Tries to calculate a pair rate using base currency rate from_base_rate = super(source, from_currency, opts) unless from_base_rate from_inverse_rate = super(from_currency, source, opts) from_base_rate = 1.0 / from_inverse_rate if from_inverse_rate end to_base_rate = super(source, to_currency, opts) unless to_base_rate to_inverse_rate = super(to_currency, source, opts) to_base_rate = 1.0 / to_inverse_rate if to_inverse_rate end if to_base_rate && from_base_rate rate = to_base_rate / from_base_rate add_rate(from_currency, to_currency, rate) end end rate end
Get the timestamp of rates @return [Time] time object or nil
# File lib/money/bank/currencylayer_historical_bank.rb, line 172 def rates_timestamp @rates_timestamp ||= init_rates_timestamp end
Get the base currency for all rates. By default, USD is used. @return [String] base currency
# File lib/money/bank/currencylayer_historical_bank.rb, line 67 def source @source ||= CL_SOURCE end
Set the base currency for all rates. By default, USD is used. CurrencylayerBank only allows USD as base currency for the free plan users.
@example
source = 'USD'
@param value [String] Currency code, ISO 3166-1 alpha-3
@return [String] chosen base currency
# File lib/money/bank/currencylayer_historical_bank.rb, line 61 def source=(value) @source = Money::Currency.find(value.to_s).try(:iso_code) || CL_SOURCE end
Source url of CurrencylayerBank defined with access_key
and secure_connection
@return [String] the remote API url
# File lib/money/bank/currencylayer_historical_bank.rb, line 156 def source_url raise NoAccessKey if access_key.nil? || access_key.empty? cl_url = historical_date ? CL_HISTORICAL_URL : CL_URL cl_url = CL_SECURE_URL if secure_connection base_url = "#{cl_url}?source=#{source}&access_key=#{access_key}" if historical_date date_url = "&date=#{historical_date}" base_url = base_url + date_url end base_url end
Set the seconds after than the current rates are automatically expired by default, they never expire.
@example
ttl_in_seconds = 86400 # will expire the rates in one day
@param value [Integer] time to live in seconds
@return [Integer] chosen time to live in seconds
# File lib/money/bank/currencylayer_historical_bank.rb, line 80 def ttl_in_seconds=(value) @ttl_in_seconds = value refresh_rates_expiration! @ttl_in_seconds end
Update all rates from CurrencylayerBank JSON @return [Array] array of exchange rates
# File lib/money/bank/currencylayer_historical_bank.rb, line 88 def update_rates(straight = false) exchange_rates(straight).each do |exchange_rate| currency = exchange_rate.first[3..-1] rate = exchange_rate.last next unless Money::Currency.find(currency) add_rate(source, currency, rate) add_rate(currency, source, 1.0 / rate) end end
Protected Instance Methods
Get exchange rates with different strategies
@example
exchange_rates(true) exchange_rates
@param straight [Boolean] true for straight, default is careful @return [Hash] key is country code (ISO 3166-1 alpha-3) value Float
# File lib/money/bank/currencylayer_historical_bank.rb, line 268 def exchange_rates(straight = false) @rates = if straight raw_rates_straight['quotes'] else raw_rates_careful['quotes'] end end
Sets the rates timestamp from parsed JSON content
@example
set_rates_timestamp("{\"timestamp\": 1441049528, \"quotes\": {\"USDAED\": 3.67304}}")
@param raw_rates [String] parsed JSON content, default is nil @return [Time] time object with rates timestamp
# File lib/money/bank/currencylayer_historical_bank.rb, line 186 def init_rates_timestamp(raw_rates = nil) raw = raw_rates || raw_rates_careful @rates_timestamp = Time.at(raw['timestamp']) if raw.key?('timestamp') end
Opens an url and reads the content @return [String] unparsed JSON content
# File lib/money/bank/currencylayer_historical_bank.rb, line 242 def open_url open(source_url).read end
Get raw exchange rates from cache and then from url @return [String] JSON content
# File lib/money/bank/currencylayer_historical_bank.rb, line 278 def raw_rates_careful JSON.parse(read_from_cache.to_s) rescue JSON::ParserError raw_rates_straight end
Get raw exchange rates from url @return [String] JSON content
# File lib/money/bank/currencylayer_historical_bank.rb, line 286 def raw_rates_straight raw_rates = JSON.parse(read_from_url) init_rates_timestamp(raw_rates) raw_rates rescue JSON::ParserError { 'quotes' => {} } end
Read from cache when exist @return [Proc,String] parsed JSON content
# File lib/money/bank/currencylayer_historical_bank.rb, line 220 def read_from_cache if cache.is_a?(Proc) cache.call(nil) elsif (cache.is_a?(String) || cache.is_a?(Pathname)) && File.exist?(cache) open(cache).read end end
Get remote content and store in cache @return [String] unparsed JSON content
# File lib/money/bank/currencylayer_historical_bank.rb, line 231 def read_from_url text = open_url if valid_rates?(text) refresh_rates_expiration! store_in_cache(text) if cache end text end
Refresh expiration from now return [Time] new expiration time
# File lib/money/bank/currencylayer_historical_bank.rb, line 296 def refresh_rates_expiration! @rates_expiration = Time.now + ttl_in_seconds unless ttl_in_seconds.nil? end
Store the provided text data by calling the proc method provided for the cache, or write to the cache file.
@example
store_in_cache("{\"quotes\": {\"USDAED\": 3.67304}}")
@param text [String] parsed JSON content @return [String,Integer]
# File lib/money/bank/currencylayer_historical_bank.rb, line 199 def store_in_cache(text) if cache.is_a?(Proc) cache.call(text) elsif cache.is_a?(String) || cache.is_a?(Pathname) write_to_file(text) end end
Check validity of rates response only for store in cache
@example
valid_rates?("{\"quotes\": {\"USDAED\": 3.67304}}")
@param [String] text is JSON content @return [Boolean] valid or not
# File lib/money/bank/currencylayer_historical_bank.rb, line 253 def valid_rates?(text) parsed = JSON.parse(text) parsed && parsed.key?('quotes') rescue JSON::ParserError false end
Writes content to file cache @param text [String] parsed JSON content @return [String,Integer]
# File lib/money/bank/currencylayer_historical_bank.rb, line 210 def write_to_file(text) open(cache, 'w') do |f| f.write(text) end rescue Errno::ENOENT raise InvalidCache end