class NbuCurrency

Constants

CURRENCIES
NBU_RATES_URL
VERSION

Attributes

last_updated[RW]
rates_updated_at[RW]

Public Instance Methods

exchange(cents, from_currency, to_currency) click to toggle source
# File lib/nbu_currency.rb, line 36
def exchange(cents, from_currency, to_currency)
  exchange_with(Money.new(cents, from_currency), to_currency)
end
exchange_with(from, to_currency) click to toggle source
# File lib/nbu_currency.rb, line 40
def exchange_with(from, to_currency)
  from_base_rate, to_base_rate = nil, nil
  rate = get_rate(from, to_currency)

  unless rate
    @mutex.synchronize do
      opts = { without_mutex: true }
      from_base_rate = get_rate("UAH", from.currency.to_s, opts)
      to_base_rate = get_rate("UAH", to_currency, opts)
    end
    rate = to_base_rate / from_base_rate
  end

  calculate_exchange(from, to_currency, rate)
end
get_rate(from, to, opts = {}) click to toggle source
# File lib/nbu_currency.rb, line 56
def get_rate(from, to, opts = {})
  fn = -> { @rates[rate_key_for(from, to, opts)] }

  if opts[:without_mutex]
    fn.call
  else
    @mutex.synchronize { fn.call }
  end
end
save_rates(cache, url=NBU_RATES_URL) click to toggle source
# File lib/nbu_currency.rb, line 20
def save_rates(cache, url=NBU_RATES_URL)
  raise InvalidCache unless cache
  File.open(cache, "w") do |file|
    io = open(url);
    io.each_line { |line| file.puts line }
  end
end
save_rates_to_s(url=NBU_RATES_URL) click to toggle source
# File lib/nbu_currency.rb, line 32
def save_rates_to_s(url=NBU_RATES_URL)
  open(url).read
end
set_rate(from, to, rate, opts = {}) click to toggle source
# File lib/nbu_currency.rb, line 66
def set_rate(from, to, rate, opts = {})
  fn = -> { @rates[rate_key_for(from, to, opts)] = rate }

  if opts[:without_mutex]
    fn.call
  else
    @mutex.synchronize { fn.call }
  end
end
update_rates(cache=nil) click to toggle source
# File lib/nbu_currency.rb, line 16
def update_rates(cache=nil)
  update_parsed_rates(doc(cache))
end
update_rates_from_s(content) click to toggle source
# File lib/nbu_currency.rb, line 28
def update_rates_from_s(content)
  update_parsed_rates(doc_from_s(content))
end

Protected Instance Methods

doc(cache, url=NBU_RATES_URL) click to toggle source
# File lib/nbu_currency.rb, line 78
def doc(cache, url=NBU_RATES_URL)
  rates_source = !!cache ? cache : url
  begin
    Nokogiri::XML(open(rates_source)).tap do |doc|
      if doc.xpath('exchangerate/exchangerate/@date').any?
        doc.xpath('exchangerate/exchangerate')
      else
        raise Nokogiri::XML::XPath::SyntaxError
      end
    end
  rescue Nokogiri::XML::XPath::SyntaxError
    Nokogiri::XML(open(url))
  end
end
doc_from_s(content) click to toggle source
# File lib/nbu_currency.rb, line 93
def doc_from_s(content)
  Nokogiri::XML(content)
end
update_parsed_rates(doc) click to toggle source
# File lib/nbu_currency.rb, line 97
def update_parsed_rates(doc)
  rates = doc.xpath('exchangerate/exchangerate')

  @mutex.synchronize do
    rates.each do |exchange_rate|
      rate = BigDecimal(exchange_rate.attribute("buy").value.to_i) / exchange_rate.attribute("unit").value.to_f / 10000.0
      currency = exchange_rate.attribute("ccy").value
      set_rate("UAH", currency, rate, :without_mutex => true)
    end
    set_rate("UAH", "UAH", 1, :without_mutex => true)
  end

  rates_updated_at = doc.xpath('exchangerate/exchangerate/@date').first.value
  @rates_updated_at = Time.parse(rates_updated_at)

  @last_updated = Time.now
end

Private Instance Methods

calculate_exchange(from, to_currency, rate) click to toggle source
# File lib/nbu_currency.rb, line 117
def calculate_exchange(from, to_currency, rate)
  to_currency_money = Money::Currency.wrap(to_currency).subunit_to_unit
  from_currency_money = from.currency.subunit_to_unit
  decimal_money = BigDecimal(to_currency_money) / BigDecimal(from_currency_money)
  money = (decimal_money * from.cents * rate).round
  Money.new(money, to_currency)
end
rate_key_for(from, to, opts) click to toggle source
# File lib/nbu_currency.rb, line 125
def rate_key_for(from, to, opts)
  key = "#{from}_TO_#{to}"
  key.upcase
end