Class: Exchanger::ExchangeRate
- Inherits:
-
ActiveRecord::Base
- Object
- ActiveRecord::Base
- Exchanger::ExchangeRate
- Defined in:
- lib/exchanger/exchange_rate.rb
Constant Summary collapse
- DATA_SOURCE =
"https://sdw.ecb.europa.eu/quickviewexport.do?SERIES_KEY=120.EXR.D.USD.EUR.SP00.A&type=csv".freeze
- DATE_NORMALIZER =
lambda { |date| Date.parse(date) rescue nil }
Class Method Summary collapse
- .exchange(amount:, dates:) ⇒ Object
-
.seed ⇒ Object
Seeds database with exchange rates from ECB.
Class Method Details
.exchange(amount:, dates:) ⇒ Object
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/exchanger/exchange_rate.rb', line 64 def self.exchange(amount:, dates:) amount = amount.to_f dates = [*dates].map(&DATE_NORMALIZER) dates.map do |date| if date if rate_record = ExchangeRate.where(date: date).first # Regular business day, we have all the data. (rate_record.rate * amount).to_f elsif date.on_weekend? && next_business_day = skip_weekends(date.in_time_zone('Berlin').to_date, 1) # Weekends. When you send exchange request on a weekend, it will be exchanges on the next business day. # Note that this is in CET timezone as per ECB rules. Sorry, no luck exchanging on Moday from Sydney. # I wish I knew but I really don't return nil if next_business_day.future? rate_record = ExchangeRate.where(date: next_business_day).first (rate_record.rate * amount).to_f else # Sorry, don't know why you couldn't exchange euros on 2012-05-01. Sometimes ECB doesn't have data. # Also handles dates that are in future. "No rate for this date" end else "Invalid date passed" end end end |
.seed ⇒ Object
Seeds database with exchange rates from ECB.
As per www.ecb.europa.eu/stats/exchange/eurofxref/html/index.en.html, the reference rates are usually updated around 16:00 CET on every working day, except on TARGET closing days (holidays like Christmas). They are based on a regular daily concertation procedure between central banks across Europe, which normally takes place at 14:15 CET(but updates arounf 16pm)
We implement simplest possible caching based on ECD data update rules mentioned above.
49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/exchanger/exchange_rate.rb', line 49 def self.seed last_available_record = ExchangeRate.order(:date).last if (last_available_record&.date == skip_weekends(Date.today.in_time_zone('Berlin').to_date, -1)) && Time.now.in_time_zone('Berlin').hour >= 16 return end encoded_url = URI.encode(DATA_SOURCE) data = open(URI.parse(encoded_url)).read CSV.parse(data)[5..-1].each do |date, rate| next if rate == '-' ExchangeRate.find_or_create_by(date: date, rate: rate.to_f) end end |