Class: EuCentralBank

Inherits:
Money::Bank::VariableExchange
  • Object
show all
Defined in:
lib/eu_central_bank.rb,
lib/eu_central_bank/version.rb,
lib/eu_central_bank/rates_document.rb

Defined Under Namespace

Classes: RatesDocument

Constant Summary collapse

SERIALIZER_DATE_SEPARATOR =
'_AT_'
DECIMAL_PRECISION =
5
CURRENCIES =
%w(USD JPY BGN CZK DKK GBP HUF ILS ISK PLN RON SEK CHF NOK TRY AUD BRL CAD CNY HKD IDR INR KRW MXN MYR NZD PHP SGD THB ZAR).map(&:freeze).freeze
ECB_RATES_URL =
'https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml'.freeze
ECB_90_DAY_URL =
'https://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist-90d.xml'.freeze
ECB_ALL_HIST_URL =
'https://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist.xml'.freeze
LEGACY_CURRENCIES =
%w(CYP HRK RUB SIT ROL TRL)
VERSION =
"2.0.0"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(st = Money::RatesStore::StoreWithHistoricalDataSupport.new, &block) ⇒ EuCentralBank

Returns a new instance of EuCentralBank.



28
29
30
31
# File 'lib/eu_central_bank.rb', line 28

def initialize(st = Money::RatesStore::StoreWithHistoricalDataSupport.new, &block)
  super
  @currency_string = nil
end

Instance Attribute Details

#historical_last_updatedObject

Returns the value of attribute historical_last_updated.



16
17
18
# File 'lib/eu_central_bank.rb', line 16

def historical_last_updated
  @historical_last_updated
end

#historical_rates_updated_atObject

Returns the value of attribute historical_rates_updated_at.



17
18
19
# File 'lib/eu_central_bank.rb', line 17

def historical_rates_updated_at
  @historical_rates_updated_at
end

#last_updatedObject

Returns the value of attribute last_updated.



14
15
16
# File 'lib/eu_central_bank.rb', line 14

def last_updated
  @last_updated
end

#rates_updated_atObject

Returns the value of attribute rates_updated_at.



15
16
17
# File 'lib/eu_central_bank.rb', line 15

def rates_updated_at
  @rates_updated_at
end

Instance Method Details

#check_currency_available(currency) ⇒ Object



171
172
173
174
175
176
# File 'lib/eu_central_bank.rb', line 171

def check_currency_available(currency)
  currency_string = currency.to_s
  return true if currency_string == "EUR"
  return true if CURRENCIES.include?(currency_string)
  raise CurrencyUnavailable, "No rates available for #{currency_string}"
end

#exchange(cents, from_currency, to_currency, date = nil) ⇒ Object



63
64
65
# File 'lib/eu_central_bank.rb', line 63

def exchange(cents, from_currency, to_currency, date=nil)
  exchange_with(Money.new(cents, from_currency), to_currency, date)
end

#exchange_with(from, to_currency, date = nil) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/eu_central_bank.rb', line 67

def exchange_with(from, to_currency, date=nil)
  from_base_rate, to_base_rate = nil, nil
  rate = get_rate(from.currency, to_currency, date)

  unless rate
    store.transaction true do
      from_base_rate = get_rate("EUR", from.currency.to_s, date)
      to_base_rate = get_rate("EUR", to_currency, date)
    end

    unless from_base_rate && to_base_rate
      message = "No conversion rate known for '#{from.currency.iso_code}' -> '#{to_currency}'"
      message << " on #{date.to_s}" if date

      raise Money::Bank::UnknownRate, message
    end

    rate = to_base_rate / from_base_rate
  end

  calculate_exchange(from, to_currency, rate)
end

#export_rates(format, file = nil, opts = {}) ⇒ Object

Raises:

  • (Money::Bank::UnknownRateFormat)


120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/eu_central_bank.rb', line 120

def export_rates(format, file = nil, opts = {})
  raise Money::Bank::UnknownRateFormat unless
    RATE_FORMATS.include? format

  store.transaction true do
    s = case format
    when :json
      JSON.dump(rates)
    when :ruby
      Marshal.dump(rates)
    when :yaml
      YAML.dump(rates)
    end

    unless file.nil?
      File.open(file, "w") {|f| f.write(s) }
    end

    s
  end
end

#get_rate(from, to, date = nil) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/eu_central_bank.rb', line 90

def get_rate(from, to, date = nil)
  return 1 if from == to

  check_currency_available(from)
  check_currency_available(to)

  if date.is_a?(Hash)
    # Backwards compatibility for the opts hash
    date = date[:date]
  end

  store.get_rate(::Money::Currency.wrap(from).iso_code, ::Money::Currency.wrap(to).iso_code, date)
end

#import_rates(format, s, opts = {}) ⇒ Object

Raises:

  • (Money::Bank::UnknownRateFormat)


142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/eu_central_bank.rb', line 142

def import_rates(format, s, opts = {})
  raise Money::Bank::UnknownRateFormat unless
    RATE_FORMATS.include? format

  store.transaction true do
    data = case format
     when :json
       JSON.load(s)
     when :ruby
       Marshal.load(s)
     when :yaml
       if Gem::Version.new(Psych::VERSION) >= Gem::Version.new('3.1.0')
         YAML.safe_load(s, permitted_classes: [ BigDecimal ])
       else
         YAML.safe_load(s, [ BigDecimal ], [], true)
       end
     end

    data.each do |key, rate|
      from, to = key.split(SERIALIZER_SEPARATOR)
      to, date = to.split(SERIALIZER_DATE_SEPARATOR)

      store.add_rate from, to, BigDecimal(rate, DECIMAL_PRECISION), date
    end
  end

  self
end

#ratesObject



112
113
114
115
116
117
118
# File 'lib/eu_central_bank.rb', line 112

def rates
  store.each_rate.each_with_object({}) do |(from,to,rate,date),hash|
    key = [from, to].join(SERIALIZER_SEPARATOR)
    key = [key, date.to_s].join(SERIALIZER_DATE_SEPARATOR) if date
    hash[key] = rate
  end
end

#save_historical_rates(cache, all = false) ⇒ Object



50
51
52
53
# File 'lib/eu_central_bank.rb', line 50

def save_historical_rates(cache, all=false)
  url = all ? ECB_ALL_HIST_URL : ECB_90_DAY_URL
  save_rates(cache, url)
end

#save_rates(cache, url = ECB_RATES_URL) ⇒ Object

Raises:



42
43
44
45
46
47
48
# File 'lib/eu_central_bank.rb', line 42

def save_rates(cache, url=ECB_RATES_URL)
  raise InvalidCache unless cache
  File.open(cache, "w") do |file|
    io = URI.open(url)
    io.each_line { |line| file.puts line }
  end
end

#save_rates_to_s(url = ECB_RATES_URL) ⇒ Object



59
60
61
# File 'lib/eu_central_bank.rb', line 59

def save_rates_to_s(url=ECB_RATES_URL)
  URI.open(url).read
end

#set_rate(from, to, rate, date = nil) ⇒ Object



104
105
106
107
108
109
110
# File 'lib/eu_central_bank.rb', line 104

def set_rate(from, to, rate, date = nil)
  if date.is_a?(Hash)
    # Backwards compatibility for the opts hash
    date = date[:date]
  end
  store.add_rate(::Money::Currency.wrap(from).iso_code, ::Money::Currency.wrap(to).iso_code, rate, date)
end

#update_historical_rates(cache = nil, all = false) ⇒ Object



37
38
39
40
# File 'lib/eu_central_bank.rb', line 37

def update_historical_rates(cache=nil, all=false)
  url = all ? ECB_ALL_HIST_URL : ECB_90_DAY_URL
  update_parsed_historical_rates(doc(cache, url))
end

#update_rates(cache = nil, url = ECB_RATES_URL) ⇒ Object



33
34
35
# File 'lib/eu_central_bank.rb', line 33

def update_rates(cache=nil, url=ECB_RATES_URL)
  update_parsed_rates(doc(cache, url))
end

#update_rates_from_s(content) ⇒ Object



55
56
57
# File 'lib/eu_central_bank.rb', line 55

def update_rates_from_s(content)
  update_parsed_rates(parse_rates(content))
end