money-open-exchange-rates 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/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
|