eu_central_bank 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -2
- data/lib/eu_central_bank.rb +80 -31
- data/lib/money/rates_store/eu_central_bank_historical_data_support.rb +70 -0
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4dbcc0a2aa33d3b41142677ca45615eeb9345633
|
4
|
+
data.tar.gz: cc9c0d602fcdbb84f904964cd3c6a5cd5d5bd0b4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 096495025aa42d1e675990694465f4980a00e81622efa05d93ffc6d8b24fb24beb8b9f2db9a6aaed295bc4f9a741b5842d1761a72eb41dc1ab95275670c1bc0a
|
7
|
+
data.tar.gz: 2d484be4e3aa08ac418a0d2f7d0c7f3a51fa126a8269c49057df19906a237437ed2aea27641c8cb9fc2e28180eae597d732c50a1353f6b28eb98c70848b83bc3
|
data/CHANGELOG.md
CHANGED
@@ -1,10 +1,13 @@
|
|
1
1
|
# eu_central_bank changelog
|
2
2
|
|
3
|
-
## 1.0.
|
3
|
+
## 1.0.1 (May 20 2016)
|
4
|
+
|
5
|
+
* Fixed compatibility with recent Money gem
|
6
|
+
|
7
|
+
## 1.0.0 (Jan 15 2016)
|
4
8
|
|
5
9
|
* Update to Money 6.7.0
|
6
10
|
* Not Support for LTL
|
7
|
-
* Update money version
|
8
11
|
* Fix a couple of Ruby warnings found in specs
|
9
12
|
|
10
13
|
## 0.3.8 (Feb 12 2014)
|
data/lib/eu_central_bank.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'open-uri'
|
2
2
|
require 'nokogiri'
|
3
3
|
require 'money'
|
4
|
+
require 'money/rates_store/eu_central_bank_historical_data_support'
|
4
5
|
|
5
6
|
class InvalidCache < StandardError ; end
|
6
7
|
|
@@ -11,10 +12,17 @@ class EuCentralBank < Money::Bank::VariableExchange
|
|
11
12
|
attr_accessor :historical_last_updated
|
12
13
|
attr_accessor :historical_rates_updated_at
|
13
14
|
|
15
|
+
SERIALIZER_DATE_SEPARATOR = '_AT_'
|
16
|
+
|
14
17
|
CURRENCIES = %w(USD JPY BGN CZK DKK GBP HUF ILS PLN RON SEK CHF NOK HRK RUB TRY AUD BRL CAD CNY HKD IDR INR KRW MXN MYR NZD PHP SGD THB ZAR).map(&:freeze).freeze
|
15
18
|
ECB_RATES_URL = 'http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml'.freeze
|
16
19
|
ECB_90_DAY_URL = 'http://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist-90d.xml'.freeze
|
17
20
|
|
21
|
+
def initialize(*)
|
22
|
+
super
|
23
|
+
@store.extend Money::RatesStore::EuCentralBankHistoricalDataSupport
|
24
|
+
end
|
25
|
+
|
18
26
|
def update_rates(cache=nil)
|
19
27
|
update_parsed_rates(doc(cache))
|
20
28
|
end
|
@@ -45,13 +53,12 @@ class EuCentralBank < Money::Bank::VariableExchange
|
|
45
53
|
|
46
54
|
def exchange_with(from, to_currency, date=nil)
|
47
55
|
from_base_rate, to_base_rate = nil, nil
|
48
|
-
rate = get_rate(from, to_currency,
|
56
|
+
rate = get_rate(from.currency, to_currency, date)
|
49
57
|
|
50
58
|
unless rate
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
to_base_rate = get_rate("EUR", to_currency, opts)
|
59
|
+
store.transaction true do
|
60
|
+
from_base_rate = get_rate("EUR", from.currency.to_s, date)
|
61
|
+
to_base_rate = get_rate("EUR", to_currency, date)
|
55
62
|
end
|
56
63
|
rate = to_base_rate / from_base_rate
|
57
64
|
end
|
@@ -59,26 +66,76 @@ class EuCentralBank < Money::Bank::VariableExchange
|
|
59
66
|
calculate_exchange(from, to_currency, rate)
|
60
67
|
end
|
61
68
|
|
62
|
-
def get_rate(from, to,
|
63
|
-
|
69
|
+
def get_rate(from, to, date = nil)
|
70
|
+
if date.is_a?(Hash)
|
71
|
+
# Backwards compatibility for the opts hash
|
72
|
+
date = date[:date]
|
73
|
+
end
|
74
|
+
store.get_rate(::Money::Currency.wrap(from).iso_code, ::Money::Currency.wrap(to).iso_code, date)
|
75
|
+
end
|
64
76
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
77
|
+
def set_rate(from, to, rate, date = nil)
|
78
|
+
if date.is_a?(Hash)
|
79
|
+
# Backwards compatibility for the opts hash
|
80
|
+
date = date[:date]
|
69
81
|
end
|
82
|
+
store.add_rate(::Money::Currency.wrap(from).iso_code, ::Money::Currency.wrap(to).iso_code, rate, date)
|
70
83
|
end
|
71
84
|
|
72
|
-
def
|
73
|
-
|
85
|
+
def rates
|
86
|
+
store.each_rate.each_with_object({}) do |(from,to,rate,date),hash|
|
87
|
+
key = [from, to].join(SERIALIZER_SEPARATOR)
|
88
|
+
key = [key, date.to_s].join(SERIALIZER_DATE_SEPARATOR) if date
|
89
|
+
hash[key] = rate
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def export_rates(format, file = nil, opts = {})
|
94
|
+
raise Money::Bank::UnknownRateFormat unless
|
95
|
+
RATE_FORMATS.include? format
|
96
|
+
|
97
|
+
store.transaction true do
|
98
|
+
s = case format
|
99
|
+
when :json
|
100
|
+
JSON.dump(rates)
|
101
|
+
when :ruby
|
102
|
+
Marshal.dump(rates)
|
103
|
+
when :yaml
|
104
|
+
YAML.dump(rates)
|
105
|
+
end
|
106
|
+
|
107
|
+
unless file.nil?
|
108
|
+
File.open(file, "w") {|f| f.write(s) }
|
109
|
+
end
|
74
110
|
|
75
|
-
|
76
|
-
fn.call
|
77
|
-
else
|
78
|
-
@mutex.synchronize { fn.call }
|
111
|
+
s
|
79
112
|
end
|
80
113
|
end
|
81
114
|
|
115
|
+
def import_rates(format, s, opts = {})
|
116
|
+
raise Money::Bank::UnknownRateFormat unless
|
117
|
+
RATE_FORMATS.include? format
|
118
|
+
|
119
|
+
store.transaction true do
|
120
|
+
data = case format
|
121
|
+
when :json
|
122
|
+
JSON.load(s)
|
123
|
+
when :ruby
|
124
|
+
Marshal.load(s)
|
125
|
+
when :yaml
|
126
|
+
YAML.load(s)
|
127
|
+
end
|
128
|
+
|
129
|
+
data.each do |key, rate|
|
130
|
+
from, to = key.split(SERIALIZER_SEPARATOR)
|
131
|
+
to, date = to.split(SERIALIZER_DATE_SEPARATOR)
|
132
|
+
store.add_rate from, to, rate, date
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
self
|
137
|
+
end
|
138
|
+
|
82
139
|
protected
|
83
140
|
|
84
141
|
def doc(cache, url=ECB_RATES_URL)
|
@@ -95,13 +152,13 @@ class EuCentralBank < Money::Bank::VariableExchange
|
|
95
152
|
def update_parsed_rates(doc)
|
96
153
|
rates = doc.xpath('gesmes:Envelope/xmlns:Cube/xmlns:Cube//xmlns:Cube')
|
97
154
|
|
98
|
-
|
155
|
+
store.transaction true do
|
99
156
|
rates.each do |exchange_rate|
|
100
157
|
rate = BigDecimal(exchange_rate.attribute("rate").value)
|
101
158
|
currency = exchange_rate.attribute("currency").value
|
102
|
-
set_rate("EUR", currency, rate
|
159
|
+
set_rate("EUR", currency, rate)
|
103
160
|
end
|
104
|
-
set_rate("EUR", "EUR", 1
|
161
|
+
set_rate("EUR", "EUR", 1)
|
105
162
|
end
|
106
163
|
|
107
164
|
rates_updated_at = doc.xpath('gesmes:Envelope/xmlns:Cube/xmlns:Cube/@time').first.value
|
@@ -113,14 +170,12 @@ class EuCentralBank < Money::Bank::VariableExchange
|
|
113
170
|
def update_parsed_historical_rates(doc)
|
114
171
|
rates = doc.xpath('gesmes:Envelope/xmlns:Cube/xmlns:Cube//xmlns:Cube')
|
115
172
|
|
116
|
-
|
173
|
+
store.transaction true do
|
117
174
|
rates.each do |exchange_rate|
|
118
175
|
rate = BigDecimal(exchange_rate.attribute("rate").value)
|
119
176
|
currency = exchange_rate.attribute("currency").value
|
120
|
-
|
121
|
-
|
122
|
-
set_rate("EUR", currency, rate, opts)
|
123
|
-
set_rate("EUR", "EUR", 1, opts)
|
177
|
+
date = exchange_rate.parent.attribute("time").value
|
178
|
+
set_rate("EUR", currency, rate, date)
|
124
179
|
end
|
125
180
|
end
|
126
181
|
|
@@ -139,10 +194,4 @@ class EuCentralBank < Money::Bank::VariableExchange
|
|
139
194
|
money = (decimal_money * from.cents * rate).round
|
140
195
|
Money.new(money, to_currency)
|
141
196
|
end
|
142
|
-
|
143
|
-
def rate_key_for(from, to, opts)
|
144
|
-
key = "#{from}_TO_#{to}"
|
145
|
-
key << "_#{opts[:date].to_s}" if opts[:date]
|
146
|
-
key.upcase
|
147
|
-
end
|
148
197
|
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Money::RatesStore
|
2
|
+
module EuCentralBankHistoricalDataSupport
|
3
|
+
INDEX_DATE_SEPARATOR = '_AT_'.freeze
|
4
|
+
|
5
|
+
def add_rate(currency_iso_from, currency_iso_to, rate, date = nil)
|
6
|
+
transaction { index[rate_key_for(currency_iso_from, currency_iso_to, date)] = rate }
|
7
|
+
end
|
8
|
+
|
9
|
+
def get_rate(currency_iso_from, currency_iso_to, date = nil)
|
10
|
+
transaction { index[rate_key_for(currency_iso_from, currency_iso_to, date)] }
|
11
|
+
end
|
12
|
+
|
13
|
+
# Wraps block execution in a thread-safe transaction
|
14
|
+
def transaction(force_sync = false, &block)
|
15
|
+
# Ruby 1.9.3 does not support @mutex.owned?
|
16
|
+
if @mutex.respond_to?(:owned?)
|
17
|
+
force_sync = false if @mutex.locked? && @mutex.owned?
|
18
|
+
else
|
19
|
+
# If we allowed this in Ruby 1.9.3, it might possibly cause recursive
|
20
|
+
# locking within the same thread.
|
21
|
+
force_sync = false
|
22
|
+
end
|
23
|
+
if !force_sync && (@in_transaction || options[:without_mutex])
|
24
|
+
block.call self
|
25
|
+
else
|
26
|
+
@mutex.synchronize do
|
27
|
+
@in_transaction = true
|
28
|
+
result = block.call
|
29
|
+
@in_transaction = false
|
30
|
+
result
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Iterate over rate tuples (iso_from, iso_to, rate)
|
36
|
+
#
|
37
|
+
# @yieldparam iso_from [String] Currency ISO string.
|
38
|
+
# @yieldparam iso_to [String] Currency ISO string.
|
39
|
+
# @yieldparam rate [Numeric] Exchange rate.
|
40
|
+
# @yieldparam date [Date] Historical date for the exchange rate. Nil if the rate is not historical rate.
|
41
|
+
#
|
42
|
+
# @return [Enumerator]
|
43
|
+
#
|
44
|
+
# @example
|
45
|
+
# store.each_rate do |iso_from, iso_to, rate, date|
|
46
|
+
# puts [iso_from, iso_to, rate, date].join
|
47
|
+
# end
|
48
|
+
def each_rate(&block)
|
49
|
+
enum = Enumerator.new do |yielder|
|
50
|
+
index.each do |key, rate|
|
51
|
+
iso_from, iso_to = key.split(Memory::INDEX_KEY_SEPARATOR)
|
52
|
+
iso_to, date = iso_to.split(INDEX_DATE_SEPARATOR)
|
53
|
+
date = Date.parse(date) if date
|
54
|
+
yielder.yield iso_from, iso_to, rate, date
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
block_given? ? enum.each(&block) : enum
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def rate_key_for(currency_iso_from, currency_iso_to, date = nil)
|
64
|
+
key = [currency_iso_from, currency_iso_to].join(Memory::INDEX_KEY_SEPARATOR)
|
65
|
+
key = [key, date.to_s].join(INDEX_DATE_SEPARATOR) if date
|
66
|
+
key.upcase
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: eu_central_bank
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shane Emmons
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-05-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 3.
|
47
|
+
version: 3.4.0
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 3.
|
54
|
+
version: 3.4.0
|
55
55
|
description: This gem reads exchange rates from the european central bank website.
|
56
56
|
It uses it to calculates exchange rates. It is compatible with the money gem
|
57
57
|
email:
|
@@ -64,6 +64,7 @@ files:
|
|
64
64
|
- LICENSE
|
65
65
|
- README.md
|
66
66
|
- lib/eu_central_bank.rb
|
67
|
+
- lib/money/rates_store/eu_central_bank_historical_data_support.rb
|
67
68
|
homepage: https://github.com/RubyMoney/eu_central_bank
|
68
69
|
licenses: []
|
69
70
|
metadata: {}
|
@@ -83,10 +84,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
83
84
|
version: '0'
|
84
85
|
requirements: []
|
85
86
|
rubyforge_project:
|
86
|
-
rubygems_version: 2.
|
87
|
+
rubygems_version: 2.5.1
|
87
88
|
signing_key:
|
88
89
|
specification_version: 4
|
89
90
|
summary: Calculates exchange rates based on rates from european central bank. Money
|
90
91
|
gem compatible.
|
91
92
|
test_files: []
|
92
|
-
has_rdoc:
|