money-open-exchange-rates 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/History.md +5 -0
- data/README.md +3 -3
- data/lib/money/bank/open_exchange_rates_bank.rb +1 -1
- data/lib/open_exchange_rates_bank/version.rb +1 -1
- metadata +1 -2
- data/test/open_exchange_rates_bank_test.rb.orig +0 -393
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9409fd168f31d0335f71e0713e1a014ff3d23ae9abe908d6a78b1d13d05b579f
|
4
|
+
data.tar.gz: e49b7cecf6992a5a5a08d4998ce5f060dd7dd0d286bbca34dbade198669f12ce
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5450e1dcb1f9e856d21efa06f02200bbf606b0299727a3c844f44e0709ae5efae2172128420eaaf8dec956793e589bdfb34a7103ba78708a25c24c2c112888c8
|
7
|
+
data.tar.gz: 5728bf847be03d84e0c2191cf4f9da05ba2c6b2219aacb11a55f957f14dd207b751258e99518c7a164b8ae91f10f951d9f2566807de4b2e61c8874cd0d03aea2
|
data/History.md
CHANGED
data/README.md
CHANGED
@@ -96,7 +96,7 @@ With `Rails` cache example:
|
|
96
96
|
|
97
97
|
~~~ ruby
|
98
98
|
OXR_CACHE_KEY = 'money:exchange_rates'.freeze
|
99
|
-
OXR_CACHE_TTL =
|
99
|
+
OXR_CACHE_TTL = 86400
|
100
100
|
# using same ttl with refreshing current rates and cache
|
101
101
|
oxr.ttl_in_seconds = OXR_CACHE_TTL
|
102
102
|
oxr.cache = Proc.new do |text|
|
@@ -113,11 +113,11 @@ or using base currency rate to both currencies forming the pair.
|
|
113
113
|
|
114
114
|
## Full example configuration initializer with Rails and cache
|
115
115
|
|
116
|
-
~~~
|
116
|
+
~~~ ruby
|
117
117
|
require 'money/bank/open_exchange_rates_bank'
|
118
118
|
|
119
119
|
OXR_CACHE_KEY = 'money:exchange_rates'.freeze
|
120
|
-
OXR_CACHE_TTL =
|
120
|
+
OXR_CACHE_TTL = 86400
|
121
121
|
oxr = Money::Bank::OpenExchangeRatesBank.new
|
122
122
|
oxr.ttl_in_seconds = OXR_CACHE_TTL
|
123
123
|
oxr.cache = Proc.new do |text|
|
@@ -326,7 +326,7 @@ class Money
|
|
326
326
|
from_base_rate = get_rate_or_calc_inverse(source, from_currency, opts)
|
327
327
|
to_base_rate = get_rate_or_calc_inverse(source, to_currency, opts)
|
328
328
|
if to_base_rate && from_base_rate
|
329
|
-
rate = to_base_rate
|
329
|
+
rate = BigDecimal(to_base_rate) / from_base_rate
|
330
330
|
add_rate(from_currency, to_currency, rate)
|
331
331
|
return rate
|
332
332
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: money-open-exchange-rates
|
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
|
- Laurent Arnoud
|
@@ -142,7 +142,6 @@ files:
|
|
142
142
|
- test/integration/Gemfile.lock
|
143
143
|
- test/integration/api.rb
|
144
144
|
- test/open_exchange_rates_bank_test.rb
|
145
|
-
- test/open_exchange_rates_bank_test.rb.orig
|
146
145
|
- test/test_helper.rb
|
147
146
|
homepage: http://github.com/spk/money-open-exchange-rates
|
148
147
|
licenses:
|
@@ -1,393 +0,0 @@
|
|
1
|
-
require File.expand_path(File.join(File.dirname(__FILE__), 'test_helper'))
|
2
|
-
|
3
|
-
# rubocop:disable Metrics/BlockLength
|
4
|
-
describe Money::Bank::OpenExchangeRatesBank do
|
5
|
-
subject { Money::Bank::OpenExchangeRatesBank.new }
|
6
|
-
let(:oer_url) { Money::Bank::OpenExchangeRatesBank::OER_URL }
|
7
|
-
let(:oer_historical_url) do
|
8
|
-
Money::Bank::OpenExchangeRatesBank::OER_HISTORICAL_URL
|
9
|
-
end
|
10
|
-
|
11
|
-
let(:temp_cache_path) do
|
12
|
-
data_file('tmp.json')
|
13
|
-
end
|
14
|
-
let(:oer_latest_path) do
|
15
|
-
data_file('latest.json')
|
16
|
-
end
|
17
|
-
let(:oer_historical_path) do
|
18
|
-
data_file('2015-01-01.json')
|
19
|
-
end
|
20
|
-
|
21
|
-
describe 'exchange' do
|
22
|
-
before do
|
23
|
-
add_to_webmock(subject)
|
24
|
-
subject.cache = temp_cache_path
|
25
|
-
subject.save_rates
|
26
|
-
end
|
27
|
-
|
28
|
-
after do
|
29
|
-
File.unlink(temp_cache_path)
|
30
|
-
end
|
31
|
-
|
32
|
-
describe 'without rates' do
|
33
|
-
it 'able to exchange a money to its own currency even without rates' do
|
34
|
-
money = Money.new(0, 'USD')
|
35
|
-
subject.exchange_with(money, 'USD').must_equal money
|
36
|
-
end
|
37
|
-
|
38
|
-
it "raise if it can't find an exchange rate" do
|
39
|
-
money = Money.new(0, 'USD')
|
40
|
-
proc { subject.exchange_with(money, 'SSP') }
|
41
|
-
.must_raise Money::Bank::UnknownRate
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
describe 'with rates' do
|
46
|
-
before do
|
47
|
-
subject.update_rates
|
48
|
-
end
|
49
|
-
|
50
|
-
it 'should be able to exchange money from USD to a known exchange rate' do
|
51
|
-
money = Money.new(100, 'USD')
|
52
|
-
subject.exchange_with(money, 'BBD').must_equal Money.new(200, 'BBD')
|
53
|
-
end
|
54
|
-
|
55
|
-
it 'should be able to exchange money from a known exchange rate to USD' do
|
56
|
-
money = Money.new(200, 'BBD')
|
57
|
-
subject.exchange_with(money, 'USD').must_equal Money.new(100, 'USD')
|
58
|
-
end
|
59
|
-
|
60
|
-
it 'should be able to exchange money when direct rate is unknown' do
|
61
|
-
money = Money.new(100, 'BBD')
|
62
|
-
subject.exchange_with(money, 'BMD').must_equal Money.new(50, 'BMD')
|
63
|
-
end
|
64
|
-
|
65
|
-
it "should raise if it can't find an exchange rate" do
|
66
|
-
money = Money.new(0, 'USD')
|
67
|
-
proc { subject.exchange_with(money, 'SSP') }
|
68
|
-
.must_raise Money::Bank::UnknownRate
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
describe 'update_rates' do
|
74
|
-
before do
|
75
|
-
subject.app_id = TEST_APP_ID
|
76
|
-
subject.cache = oer_latest_path
|
77
|
-
subject.update_rates
|
78
|
-
end
|
79
|
-
|
80
|
-
it 'should update itself with exchange rates from OpenExchangeRates' do
|
81
|
-
subject.oer_rates.keys.each do |currency|
|
82
|
-
next unless Money::Currency.find(currency)
|
83
|
-
subject.get_rate('USD', currency).must_be :>, 0
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
it 'should not return 0 with integer rate' do
|
88
|
-
wtf = {
|
89
|
-
priority: 1,
|
90
|
-
iso_code: 'WTF',
|
91
|
-
name: 'WTF',
|
92
|
-
symbol: 'WTF',
|
93
|
-
subunit: 'Cent',
|
94
|
-
subunit_to_unit: 1000,
|
95
|
-
separator: '.',
|
96
|
-
delimiter: ','
|
97
|
-
}
|
98
|
-
Money::Currency.register(wtf)
|
99
|
-
subject.add_rate('USD', 'WTF', 2)
|
100
|
-
subject.add_rate('WTF', 'USD', 2)
|
101
|
-
subject.exchange_with(5000.to_money('WTF'), 'USD').cents.wont_equal 0
|
102
|
-
end
|
103
|
-
|
104
|
-
# in response to #4
|
105
|
-
it 'should exchange btc' do
|
106
|
-
btc = {
|
107
|
-
priority: 1,
|
108
|
-
iso_code: 'BTC',
|
109
|
-
name: 'Bitcoin',
|
110
|
-
symbol: 'BTC',
|
111
|
-
subunit: 'Cent',
|
112
|
-
subunit_to_unit: 1000,
|
113
|
-
separator: '.',
|
114
|
-
delimiter: ','
|
115
|
-
}
|
116
|
-
Money::Currency.register(btc)
|
117
|
-
rate = 13.7603
|
118
|
-
subject.add_rate('USD', 'BTC', 1 / 13.7603)
|
119
|
-
subject.add_rate('BTC', 'USD', rate)
|
120
|
-
subject.exchange_with(100.to_money('BTC'), 'USD').cents.must_equal 137_603
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
describe 'App ID' do
|
125
|
-
before do
|
126
|
-
subject.cache = temp_cache_path
|
127
|
-
end
|
128
|
-
|
129
|
-
it 'should raise an error if no App ID is set' do
|
130
|
-
proc { subject.save_rates }.must_raise Money::Bank::NoAppId
|
131
|
-
end
|
132
|
-
|
133
|
-
# TODO: As App IDs are compulsory soon, need to add more tests handle
|
134
|
-
# app_id-specific errors from
|
135
|
-
# https://openexchangerates.org/documentation#errors
|
136
|
-
end
|
137
|
-
|
138
|
-
describe 'no cache' do
|
139
|
-
before do
|
140
|
-
subject.cache = nil
|
141
|
-
add_to_webmock(subject)
|
142
|
-
end
|
143
|
-
|
144
|
-
it 'should get from url' do
|
145
|
-
subject.update_rates
|
146
|
-
subject.oer_rates.wont_be_empty
|
147
|
-
end
|
148
|
-
|
149
|
-
it 'should raise an error if invalid path is given to save_rates' do
|
150
|
-
proc { subject.save_rates }.must_raise Money::Bank::InvalidCache
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
describe 'secure_connection' do
|
155
|
-
before do
|
156
|
-
subject.app_id = TEST_APP_ID
|
157
|
-
end
|
158
|
-
|
159
|
-
describe 'historical' do
|
160
|
-
before do
|
161
|
-
subject.date = '2015-01-01'
|
162
|
-
end
|
163
|
-
|
164
|
-
<<<<<<< HEAD
|
165
|
-
let(:historical_url) do
|
166
|
-
"#{oer_historical_url}#{subject.date}.json?app_id=#{TEST_APP_ID}&show_alternative=false"
|
167
|
-
end
|
168
|
-
|
169
|
-
it 'should use the secure https url' do
|
170
|
-
=======
|
171
|
-
def historical_url
|
172
|
-
"#{oer_historical_url}#{subject.date}.json?" \
|
173
|
-
"app_id=#{TEST_APP_ID}&show_alternative=false"
|
174
|
-
end
|
175
|
-
|
176
|
-
def historical_secure_url
|
177
|
-
"#{oer_historical_secure_url}#{subject.date}.json?" \
|
178
|
-
"app_id=#{TEST_APP_ID}&show_alternative=false"
|
179
|
-
end
|
180
|
-
|
181
|
-
it 'should use the non-secure http url if secure_connection is nil' do
|
182
|
-
subject.secure_connection = nil
|
183
|
-
subject.source_url.must_equal historical_url
|
184
|
-
subject.source_url.must_include 'http://'
|
185
|
-
subject.source_url.must_include "/api/historical/#{subject.date}.json"
|
186
|
-
end
|
187
|
-
|
188
|
-
it 'should use the non-secure http url if secure_connection is false' do
|
189
|
-
subject.secure_connection = false
|
190
|
-
>>>>>>> Fix offenses
|
191
|
-
subject.source_url.must_equal historical_url
|
192
|
-
subject.source_url.must_include 'https://'
|
193
|
-
subject.source_url.must_include "/api/historical/#{subject.date}.json"
|
194
|
-
end
|
195
|
-
end
|
196
|
-
|
197
|
-
describe 'latest' do
|
198
|
-
it 'should use the secure https url' do
|
199
|
-
subject.source_url.must_equal source_secure_url
|
200
|
-
subject.source_url.must_include 'https://'
|
201
|
-
subject.source_url.must_include '/api/latest.json'
|
202
|
-
end
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
describe 'no valid file for cache' do
|
207
|
-
before do
|
208
|
-
subject.cache = "space_dir#{rand(999_999_999)}/out_space_file.json"
|
209
|
-
add_to_webmock(subject)
|
210
|
-
end
|
211
|
-
|
212
|
-
it 'should get from url' do
|
213
|
-
subject.update_rates
|
214
|
-
subject.oer_rates.wont_be_empty
|
215
|
-
end
|
216
|
-
|
217
|
-
it 'should raise an error if invalid path is given to save_rates' do
|
218
|
-
proc { subject.save_rates }.must_raise Money::Bank::InvalidCache
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
|
-
describe 'using proc for cache' do
|
223
|
-
before do
|
224
|
-
@global_rates = nil
|
225
|
-
subject.cache = proc do |v|
|
226
|
-
if v
|
227
|
-
@global_rates = v
|
228
|
-
else
|
229
|
-
@global_rates
|
230
|
-
end
|
231
|
-
end
|
232
|
-
add_to_webmock(subject)
|
233
|
-
end
|
234
|
-
|
235
|
-
it 'should get from url normally' do
|
236
|
-
subject.update_rates
|
237
|
-
subject.oer_rates.wont_be_empty
|
238
|
-
end
|
239
|
-
|
240
|
-
it 'should save from url and get from cache' do
|
241
|
-
subject.save_rates
|
242
|
-
@global_rates.wont_be_empty
|
243
|
-
dont_allow(subject).source_url
|
244
|
-
subject.update_rates
|
245
|
-
subject.oer_rates.wont_be_empty
|
246
|
-
end
|
247
|
-
end
|
248
|
-
|
249
|
-
describe 'save rates' do
|
250
|
-
before do
|
251
|
-
add_to_webmock(subject)
|
252
|
-
subject.cache = temp_cache_path
|
253
|
-
subject.save_rates
|
254
|
-
end
|
255
|
-
|
256
|
-
after do
|
257
|
-
File.unlink(temp_cache_path)
|
258
|
-
end
|
259
|
-
|
260
|
-
it 'should allow update after save' do
|
261
|
-
begin
|
262
|
-
subject.update_rates
|
263
|
-
rescue
|
264
|
-
assert false, 'Should allow updating after saving'
|
265
|
-
end
|
266
|
-
end
|
267
|
-
|
268
|
-
it 'should not break an existing file if save fails to read' do
|
269
|
-
initial_size = File.read(temp_cache_path).size
|
270
|
-
stub(subject).read_from_url { '' }
|
271
|
-
subject.save_rates
|
272
|
-
File.open(temp_cache_path).read.size.must_equal initial_size
|
273
|
-
end
|
274
|
-
|
275
|
-
it 'should not break an existing file if save returns json without rates' do
|
276
|
-
initial_size = File.read(temp_cache_path).size
|
277
|
-
stub(subject).read_from_url { '{"error": "An error"}' }
|
278
|
-
subject.save_rates
|
279
|
-
File.open(temp_cache_path).read.size.must_equal initial_size
|
280
|
-
end
|
281
|
-
|
282
|
-
it 'should not break an existing file if save returns a invalid json' do
|
283
|
-
initial_size = File.read(temp_cache_path).size
|
284
|
-
stub(subject).read_from_url { '{invalid_json: "An error"}' }
|
285
|
-
subject.save_rates
|
286
|
-
File.open(temp_cache_path).read.size.must_equal initial_size
|
287
|
-
end
|
288
|
-
end
|
289
|
-
|
290
|
-
describe '#expire_rates' do
|
291
|
-
before do
|
292
|
-
add_to_webmock(subject)
|
293
|
-
subject.ttl_in_seconds = 1000
|
294
|
-
@old_usd_eur_rate = 0.655
|
295
|
-
# see test/latest.json +52
|
296
|
-
@new_usd_eur_rate = 0.79085
|
297
|
-
subject.add_rate('USD', 'EUR', @old_usd_eur_rate)
|
298
|
-
subject.cache = temp_cache_path
|
299
|
-
subject.save_rates
|
300
|
-
end
|
301
|
-
|
302
|
-
after do
|
303
|
-
File.unlink(temp_cache_path)
|
304
|
-
end
|
305
|
-
|
306
|
-
describe 'when the ttl has expired' do
|
307
|
-
it 'should update the rates' do
|
308
|
-
subject.get_rate('USD', 'EUR').must_equal @old_usd_eur_rate
|
309
|
-
Timecop.freeze(Time.now + 1001) do
|
310
|
-
subject.get_rate('USD', 'EUR').wont_equal @old_usd_eur_rate
|
311
|
-
subject.get_rate('USD', 'EUR').must_equal @new_usd_eur_rate
|
312
|
-
end
|
313
|
-
end
|
314
|
-
|
315
|
-
it 'updates the next expiration time' do
|
316
|
-
Timecop.freeze(Time.now + 1001) do
|
317
|
-
exp_time = Time.now + 1000
|
318
|
-
subject.expire_rates
|
319
|
-
subject.rates_expiration.must_equal exp_time
|
320
|
-
end
|
321
|
-
end
|
322
|
-
end
|
323
|
-
|
324
|
-
describe 'when the ttl has not expired' do
|
325
|
-
it 'not should update the rates' do
|
326
|
-
exp_time = subject.rates_expiration
|
327
|
-
subject.expire_rates
|
328
|
-
subject.rates_expiration.must_equal exp_time
|
329
|
-
end
|
330
|
-
end
|
331
|
-
end
|
332
|
-
|
333
|
-
describe 'historical' do
|
334
|
-
before do
|
335
|
-
add_to_webmock(subject)
|
336
|
-
# see test/latest.json +52
|
337
|
-
@latest_usd_eur_rate = 0.79085
|
338
|
-
# see test/2015-01-01.json +52
|
339
|
-
@old_usd_eur_rate = 0.830151
|
340
|
-
subject.update_rates
|
341
|
-
end
|
342
|
-
|
343
|
-
it 'should be different than the latest' do
|
344
|
-
subject.get_rate('USD', 'EUR').must_equal @latest_usd_eur_rate
|
345
|
-
subject.date = '2015-01-01'
|
346
|
-
add_to_webmock(subject, oer_historical_path)
|
347
|
-
subject.update_rates
|
348
|
-
subject.get_rate('USD', 'EUR').must_equal @old_usd_eur_rate
|
349
|
-
end
|
350
|
-
end
|
351
|
-
|
352
|
-
describe 'source currency' do
|
353
|
-
it 'should be changed when a known currency is given' do
|
354
|
-
subject.source = 'EUR'
|
355
|
-
subject.source.must_equal 'EUR'
|
356
|
-
end
|
357
|
-
|
358
|
-
it 'should use USD when given unknown currency' do
|
359
|
-
subject.source = 'invalid'
|
360
|
-
subject.source.must_equal 'USD'
|
361
|
-
end
|
362
|
-
end
|
363
|
-
|
364
|
-
describe 'show alternative' do
|
365
|
-
describe 'when no value given' do
|
366
|
-
before do
|
367
|
-
subject.show_alternative = nil
|
368
|
-
end
|
369
|
-
|
370
|
-
it 'should return the default value' do
|
371
|
-
subject.show_alternative.must_equal false
|
372
|
-
end
|
373
|
-
|
374
|
-
it 'should include show_alternative param as false' do
|
375
|
-
subject.source_url.must_include 'show_alternative=false'
|
376
|
-
end
|
377
|
-
end
|
378
|
-
|
379
|
-
describe 'when value is given' do
|
380
|
-
before do
|
381
|
-
subject.show_alternative = true
|
382
|
-
end
|
383
|
-
|
384
|
-
it 'should return the value' do
|
385
|
-
subject.show_alternative.must_equal true
|
386
|
-
end
|
387
|
-
|
388
|
-
it 'should include show_alternative param as true' do
|
389
|
-
subject.source_url.must_include 'show_alternative=true'
|
390
|
-
end
|
391
|
-
end
|
392
|
-
end
|
393
|
-
end
|