class Danconia::Exchanges::BNA

The BNA does not provide an API to pull the rates, so this implementation scrapes the home HTML directly. Returns rates of both types, “Billetes” and “Divisas”, and only the “tipo de cambio vendedor” ones. See `examples/bna.rb` for a complete usage example.

Attributes

store[R]

Public Class Methods

new(store: Stores::InMemory.new) click to toggle source
# File lib/danconia/exchanges/bna.rb, line 13
def initialize store: Stores::InMemory.new
  @store = store
end

Public Instance Methods

fetch_rates() click to toggle source
# File lib/danconia/exchanges/bna.rb, line 17
def fetch_rates
  response = Net::HTTP.get URI 'https://www.bna.com.ar/Personas'
  scrape_rates(response, 'billetes') + scrape_rates(response, 'divisas')
end
rates(rate_type:, date: nil) click to toggle source
# File lib/danconia/exchanges/bna.rb, line 26
def rates rate_type:, date: nil
  array_of_rates_to_hash @store.rates(rate_type: rate_type, date: date)
end
update_rates!() click to toggle source
# File lib/danconia/exchanges/bna.rb, line 22
def update_rates!
  @store.save_rates fetch_rates
end

Private Instance Methods

parse_pair(cur_name) click to toggle source
# File lib/danconia/exchanges/bna.rb, line 47
def parse_pair cur_name
  case cur_name
  when 'Dolar U.S.A' then 'USDARS'
  when 'Euro' then 'EURARS'
  when 'Real *' then 'BRLARS'
  end
end
parse_rate(str, pair) click to toggle source
# File lib/danconia/exchanges/bna.rb, line 55
def parse_rate str, pair
  val = Float(str.tr(',', '.'))
  pair == 'BRLARS' ? val / 100.0 : val
end
scrape_rates(response, type) click to toggle source
# File lib/danconia/exchanges/bna.rb, line 32
def scrape_rates response, type
  doc = Nokogiri::XML(response).css("##{type}")

  if doc.css('thead th:last-child').text != 'Venta'
    raise Errors::APIError, "Could not scrape '#{type}' rates. Maybe the format changed?"
  end

  doc.css('tbody tr').map do |row|
    pair = parse_pair(row.css('td:first-child').text) or next
    rate = parse_rate(row.css('td:last-child').text, pair)
    date = Date.parse(doc.css('.fechaCot').text)
    {pair: pair, rate: rate, date: date, rate_type: type}
  end.compact.presence or raise Errors::APIError, "Could not scrape '#{type}' rates. Maybe the format changed?"
end