class Money::Bank::OpenexchangeratesBank
CurrencylayerBank base class
Constants
- CL_SECURE_URL
CurrencylayerBank secure url
- CL_SOURCE
Default base currency
- CL_URL
CurrencylayerBank url
Attributes
API must have a valid access_key
@param value [String] API access key @return [String] chosen API access key
Cache accessor, can be a String or a Proc
@param value [String,Pathname,Proc] cache system @return [String,Pathname,Proc] chosen cache system
Parsed CurrencylayerBank result as Hash
Get the timestamp of rates in memory @return [Time] time object or nil
Use https to fetch rates from CurrencylayerBank CurrencylayerBank only allows http as connection for the free plan users.
@param value [Boolean] true for secure connection @return [Boolean] chosen secure connection
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
Public Instance Methods
Override Money
`add_rate` method for caching @param [String] from_currency Currency ISO code. ex. 'USD' @param [String] to_currency Currency ISO code. ex. 'CAD' @param [Numeric] rate Rate to use when exchanging currencies. @return [Numeric] rate.
# File lib/money/bank/openexchangerates_bank.rb, line 147 def add_rate(from_currency, to_currency, rate) super end
Get alternative system. Default is nil @return [String,nil] chosen alternative system
# File lib/money/bank/openexchangerates_bank.rb, line 116 def alternatives @alternatives || nil end
Set alternative system, to request alternative rates
@example
alternatives = :all alternatives = :only alternatives = nil
@param value [String,Symbol] alternatives @return [String,nil] chosen alternative system
# File lib/money/bank/openexchangerates_bank.rb, line 105 def alternatives=(system) @alternatives = case system.to_sym when :all 'show_alternative' when :only 'only_alternative' end end
Fetch new rates if cached rates are expired or stale @return [Boolean] true if rates are expired and updated from remote
# File lib/money/bank/openexchangerates_bank.rb, line 167 def expire_rates! if expired? update_rates(true) true elsif stale? update_rates true else false end end
Check if rates are expired @return [Boolean] true if rates are expired
# File lib/money/bank/openexchangerates_bank.rb, line 181 def expired? Time.now > rates_expiration 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' @param [Hash] opts Options hash to set special parameters. @return [Numeric] rate.
# File lib/money/bank/openexchangerates_bank.rb, line 159 def get_rate(from_currency, to_currency, opts = {}) expire_rates! rate = get_rate_or_calc_inverse(from_currency, to_currency, opts) rate || calc_pair_rate_using_base(from_currency, to_currency, opts) end
Get rates expiration time based on ttl @return [Time] rates expiration time
# File lib/money/bank/openexchangerates_bank.rb, line 207 def rates_expiration rates_timestamp + ttl_in_seconds end
Get the timestamp of rates @return [Time] time object or nil
# File lib/money/bank/openexchangerates_bank.rb, line 213 def rates_timestamp raw = raw_rates_careful raw.key?('timestamp') ? Time.at(raw['timestamp']) : Time.at(0) end
Get the base currency for all rates. By default, USD is used. @return [String] base currency
# File lib/money/bank/openexchangerates_bank.rb, line 92 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/openexchangerates_bank.rb, line 86 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/openexchangerates_bank.rb, line 196 def source_url raise NoAccessKey if access_key.nil? || access_key.empty? cl_url = CL_URL cl_url = CL_SECURE_URL if secure_connection params = "#{cl_url}?base=#{source}&app_id=#{access_key}&prettyprint=0" params += "&#{alternatives}=1" unless alternatives.nil? params end
Check if rates are stale Stale is true if rates are updated straight by another thread. The actual thread has always old rates in memory store. @return [Boolean] true if rates are stale
# File lib/money/bank/openexchangerates_bank.rb, line 189 def stale? rates_timestamp != rates_mem_timestamp end
Get the seconds after than the current rates are automatically expired by default, they never expire. @return [Integer] chosen time to live in seconds
# File lib/money/bank/openexchangerates_bank.rb, line 123 def ttl_in_seconds @ttl_in_seconds ||= 0 end
Update all rates from CurrencylayerBank JSON @return [Array] array of exchange rates
# File lib/money/bank/openexchangerates_bank.rb, line 129 def update_rates(straight = false) store.reset! rates = exchange_rates(straight).each do |exchange_rate| currency = exchange_rate.first rate = exchange_rate.last next unless Money::Currency.find(currency) add_rate(source, currency, rate) add_rate(currency, source, 1.0 / rate) end @rates_mem_timestamp = rates_timestamp rates end
Protected Instance Methods
Tries to calculate a pair rate using base currency rate @param [String] from_currency Currency ISO code. ex. 'USD' @param [String] to_currency Currency ISO code. ex. 'CAD' @return [Numeric] rate or nil if cannot calculate rate.
# File lib/money/bank/openexchangerates_bank.rb, line 342 def calc_pair_rate_using_base(from_currency, to_currency, opts = {}) from_base_rate = get_rate_or_calc_inverse(source, from_currency, opts) to_base_rate = get_rate_or_calc_inverse(source, to_currency, opts) if to_base_rate && from_base_rate rate = to_base_rate / from_base_rate add_rate(from_currency, to_currency, rate) return rate end nil end
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/openexchangerates_bank.rb, line 296 def exchange_rates(straight = false) @rates = if straight raw_rates_straight['rates'] else raw_rates_careful['rates'] end end
Get rate or calculate it as inverse rate @param [String] from_currency Currency ISO code. ex. 'USD' @param [String] to_currency Currency ISO code. ex. 'CAD' @return [Numeric] rate or rate calculated as inverse rate.
# File lib/money/bank/openexchangerates_bank.rb, line 325 def get_rate_or_calc_inverse(from_currency, to_currency, opts = {}) rate = super_get_rate(from_currency, to_currency, opts) unless rate # Tries to calculate an inverse rate inverse_rate = super_get_rate(to_currency, from_currency, opts) if inverse_rate rate = 1.0 / inverse_rate add_rate(from_currency, to_currency, rate) end end rate end
Opens an url and reads the content @return [String] unparsed JSON content
# File lib/money/bank/openexchangerates_bank.rb, line 268 def open_url URI.open(source_url).read rescue OpenURI::HTTPError '' end
Get raw exchange rates from cache and then from url @param rescue_straight [Boolean] true for rescue straight, default true @return [String] JSON content
# File lib/money/bank/openexchangerates_bank.rb, line 307 def raw_rates_careful(rescue_straight = true) JSON.parse(read_from_cache.to_s) rescue JSON::ParserError rescue_straight ? raw_rates_straight : { 'rates' => {} } end
Get raw exchange rates from url @return [String] JSON content
# File lib/money/bank/openexchangerates_bank.rb, line 315 def raw_rates_straight JSON.parse(read_from_url) rescue JSON::ParserError raw_rates_careful(false) end
Read from cache when exist @return [Proc,String] parsed JSON content
# File lib/money/bank/openexchangerates_bank.rb, line 249 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/openexchangerates_bank.rb, line 260 def read_from_url text = open_url store_in_cache(text) if valid_rates?(text) && cache text 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("{\"rates\": {\"AED\": 3.67304}}")
@param text [String] parsed JSON content @return [String,Integer]
# File lib/money/bank/openexchangerates_bank.rb, line 228 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?("{\"rates\": {\"AED\": 3.67304}}")
@param [String] text is JSON content @return [Boolean] valid or not
# File lib/money/bank/openexchangerates_bank.rb, line 281 def valid_rates?(text) parsed = JSON.parse(text) parsed && parsed.key?('rates') rescue JSON::ParserError false end
Writes content to file cache @param text [String] parsed JSON content @return [String,Integer]
# File lib/money/bank/openexchangerates_bank.rb, line 239 def write_to_file(text) open(cache, 'w') do |f| f.write(text) end rescue Errno::ENOENT raise InvalidCache end