money-open-exchange-rates 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 49fa457e043bb1b5a72dfad8f43613bc2098cbf3
4
- data.tar.gz: 8ae046254ab9f8744f937a5220605e5947013a6a
3
+ metadata.gz: 41260f2f17ea64c1a2519d473a7c584225a4dd48
4
+ data.tar.gz: 06b22a394ddb683769ce63bfd487bc9a621c3941
5
5
  SHA512:
6
- metadata.gz: 47d4718451656dc368c7d034753f21e172875501470ae973425ccb1bcfbcf2b3694d0eb6e73ad50273b1b89330d89136cec5495d1cc37e700a049f355441e6f3
7
- data.tar.gz: 0aafaf01ae251afe65453cdb89c46031c063591ea589e0e0b1c383cf1d768dd71502fce4c53c9b04ca111fe32e558d98d26aef043d1e2df73dfe6473c3b413f1
6
+ metadata.gz: 83f5bc3cc460e263bcdc3cd691cdac931686239323aa26ebd274f1db89e46ffa8091116e18dee550c3c8da4568f052086559d69fb42a056ea220a13cdfe3ba54
7
+ data.tar.gz: f7535398b1e704cc7d65d09efb4595788521c0bd678ebed0ddb00d0fd00a0faba8123459c15d0bb94dd7280087f2add16068be80fbcfec5bd4726357c8b417c0
data/History.md CHANGED
@@ -1,4 +1,12 @@
1
1
 
2
+ v0.6.0 / 2016-09-13
3
+ ==================
4
+
5
+ * Merge pull request #29 from @xsve / pairrates
6
+ * Implemented rate calculation for any pair of currencies via base currency
7
+ * Update travis ruby list
8
+ * Fix usage of URI.join instead of File.join
9
+
2
10
  v0.5.0 / 2016-08-12
3
11
  ===================
4
12
 
data/README.md CHANGED
@@ -65,6 +65,9 @@ moe.cache = Proc.new do |v|
65
65
  end
66
66
  ~~~
67
67
 
68
+ Unknown pair rates are transparently calculated: using inverse rate (if known),
69
+ or using base currency rate to both currencies forming the pair.
70
+
68
71
  ## Tests
69
72
 
70
73
  ~~~
@@ -1,10 +1,12 @@
1
1
  # frozen_string_literal: true
2
+ require 'uri'
2
3
  require 'open-uri'
3
4
  require 'money'
4
5
  require 'json'
5
6
  require File.expand_path('../../../open_exchange_rates_bank/version', __FILE__)
6
7
 
7
8
  # Money gem class
9
+ # rubocop:disable ClassLength
8
10
  class Money
9
11
  # https://github.com/RubyMoney/money#exchange-rate-stores
10
12
  module Bank
@@ -19,11 +21,16 @@ class Money
19
21
  VERSION = ::OpenExchangeRatesBank::VERSION
20
22
  BASE_URL = 'http://openexchangerates.org/api'.freeze
21
23
  # OpenExchangeRates urls
22
- OER_URL = File.join(BASE_URL, 'latest.json')
23
- OER_HISTORICAL_URL = File.join(BASE_URL, 'historical', '%s.json')
24
+ OER_URL = URI.join(BASE_URL, 'latest.json')
25
+ OER_HISTORICAL_URL = URI.join(BASE_URL, '/historical/')
24
26
  # OpenExchangeRates secure url
25
- SECURE_OER_URL = OER_URL.gsub('http:', 'https:')
26
- SECURE_OER_HISTORICAL_URL = OER_HISTORICAL_URL.gsub('http:', 'https:')
27
+ SECURE_OER_URL = OER_URL.clone
28
+ SECURE_OER_URL.scheme = 'https'
29
+ SECURE_OER_HISTORICAL_URL = OER_HISTORICAL_URL.clone
30
+ SECURE_OER_HISTORICAL_URL.scheme = 'https'
31
+
32
+ # Default base currency "base": "USD"
33
+ OE_SOURCE = 'USD'.freeze
27
34
 
28
35
  # use https to fetch rates from Open Exchange Rates
29
36
  # disabled by default to support free-tier users
@@ -64,6 +71,28 @@ class Money
64
71
  @ttl_in_seconds
65
72
  end
66
73
 
74
+ # Set the base currency for all rates. By default, USD is used.
75
+ # OpenExchangeRates only allows USD as base currency
76
+ # for the free plan users.
77
+ #
78
+ # @example
79
+ # source = 'USD'
80
+ #
81
+ # @param value [String] Currency code, ISO 3166-1 alpha-3
82
+ #
83
+ # @return [String] chosen base currency
84
+ def source=(value)
85
+ @source = Money::Currency.find(value.to_s).iso_code
86
+ rescue
87
+ @source = OE_SOURCE
88
+ end
89
+
90
+ # Get the base currency for all rates. By default, USD is used.
91
+ # @return [String] base currency
92
+ def source
93
+ @source ||= OE_SOURCE
94
+ end
95
+
67
96
  # Update all rates from openexchangerates JSON
68
97
  # @return [Array] Array of exchange rates
69
98
  def update_rates
@@ -71,8 +100,8 @@ class Money
71
100
  rate = exchange_rate.last
72
101
  currency = exchange_rate.first
73
102
  next unless Money::Currency.find(currency)
74
- set_rate('USD', currency, rate)
75
- set_rate(currency, 'USD', 1.0 / rate)
103
+ set_rate(source, currency, rate)
104
+ set_rate(currency, source, 1.0 / rate)
76
105
  end
77
106
  end
78
107
 
@@ -88,14 +117,19 @@ class Money
88
117
  raise InvalidCache
89
118
  end
90
119
 
120
+ # Alias super method
121
+ alias super_get_rate get_rate
122
+
91
123
  # Override Money `get_rate` method for caching
92
124
  # @param [String] from_currency Currency ISO code. ex. 'USD'
93
125
  # @param [String] to_currency Currency ISO code. ex. 'CAD'
94
126
  #
95
127
  # @return [Numeric] rate.
96
128
  def get_rate(from_currency, to_currency, opts = {})
129
+ super if opts[:call_super]
97
130
  expire_rates
98
- super
131
+ rate = get_rate_or_calc_inverse(from_currency, to_currency, opts)
132
+ rate || calc_pair_rate_using_base(from_currency, to_currency, opts)
99
133
  end
100
134
 
101
135
  # Expire rates when expired
@@ -110,7 +144,11 @@ class Money
110
144
  # defined with app_id and secure_connection
111
145
  # @return [String] URL
112
146
  def source_url
113
- "#{oer_url}?app_id=#{app_id}"
147
+ if source == OE_SOURCE
148
+ "#{oer_url}?app_id=#{app_id}"
149
+ else
150
+ "#{oer_url}?app_id=#{app_id}&base=#{source}"
151
+ end
114
152
  end
115
153
 
116
154
  protected
@@ -130,7 +168,7 @@ class Money
130
168
  def historical_url
131
169
  url = OER_HISTORICAL_URL
132
170
  url = SECURE_OER_HISTORICAL_URL if secure_connection
133
- url % date
171
+ URI.join(url, "#{date}.json")
134
172
  end
135
173
 
136
174
  # Latest url
@@ -200,6 +238,40 @@ class Money
200
238
  def refresh_rates_expiration
201
239
  @rates_expiration = Time.now + ttl_in_seconds
202
240
  end
241
+
242
+ # Get rate or calculate it as inverse rate
243
+ # @param [String] from_currency Currency ISO code. ex. 'USD'
244
+ # @param [String] to_currency Currency ISO code. ex. 'CAD'
245
+ #
246
+ # @return [Numeric] rate or rate calculated as inverse rate.
247
+ def get_rate_or_calc_inverse(from_currency, to_currency, opts = {})
248
+ rate = super_get_rate(from_currency, to_currency, opts)
249
+ unless rate
250
+ # Tries to calculate an inverse rate
251
+ inverse_rate = super_get_rate(to_currency, from_currency, opts)
252
+ if inverse_rate
253
+ rate = 1.0 / inverse_rate
254
+ add_rate(from_currency, to_currency, rate)
255
+ end
256
+ end
257
+ rate
258
+ end
259
+
260
+ # Tries to calculate a pair rate using base currency rate
261
+ # @param [String] from_currency Currency ISO code. ex. 'USD'
262
+ # @param [String] to_currency Currency ISO code. ex. 'CAD'
263
+ #
264
+ # @return [Numeric] rate or nil if cannot calculate rate.
265
+ def calc_pair_rate_using_base(from_currency, to_currency, opts)
266
+ from_base_rate = get_rate_or_calc_inverse(source, from_currency, opts)
267
+ to_base_rate = get_rate_or_calc_inverse(source, to_currency, opts)
268
+ if to_base_rate && from_base_rate
269
+ rate = to_base_rate.to_f / from_base_rate
270
+ add_rate(from_currency, to_currency, rate)
271
+ return rate
272
+ end
273
+ nil
274
+ end
203
275
  end
204
276
  end
205
277
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  # Module for version constant
4
4
  module OpenExchangeRatesBank
5
- VERSION = '0.5.0'.freeze
5
+ VERSION = '0.6.0'.freeze
6
6
  end
@@ -60,6 +60,11 @@ describe Money::Bank::OpenExchangeRatesBank do
60
60
  subject.exchange_with(money, 'USD').must_equal Money.new(100, 'USD')
61
61
  end
62
62
 
63
+ it 'should be able to exchange money when direct rate is unknown' do
64
+ money = Money.new(100, 'BBD')
65
+ subject.exchange_with(money, 'BMD').must_equal Money.new(50, 'BMD')
66
+ end
67
+
63
68
  it "should raise if it can't find an exchange rate" do
64
69
  money = Money.new(0, 'USD')
65
70
  proc { subject.exchange_with(money, 'SSP') }
@@ -160,13 +165,11 @@ describe Money::Bank::OpenExchangeRatesBank do
160
165
  end
161
166
 
162
167
  def historical_url
163
- format("#{oer_historical_url}?app_id=#{TEST_APP_ID}",
164
- subject.date)
168
+ "#{oer_historical_url}#{subject.date}.json?app_id=#{TEST_APP_ID}"
165
169
  end
166
170
 
167
171
  def historical_secure_url
168
- format("#{oer_historical_secure_url}?app_id=#{TEST_APP_ID}",
169
- subject.date)
172
+ "#{oer_historical_secure_url}#{subject.date}.json?app_id=#{TEST_APP_ID}"
170
173
  end
171
174
 
172
175
  it 'should use the non-secure http url if secure_connection is nil' do
@@ -368,4 +371,16 @@ describe Money::Bank::OpenExchangeRatesBank do
368
371
  subject.get_rate('USD', 'EUR').must_equal @old_usd_eur_rate
369
372
  end
370
373
  end
374
+
375
+ describe 'source currency' do
376
+ it 'should be changed when a known currency is given' do
377
+ subject.source = 'EUR'
378
+ subject.source.must_equal 'EUR'
379
+ end
380
+
381
+ it 'should use USD when given unknown currency' do
382
+ subject.source = 'invalid'
383
+ subject.source.must_equal 'USD'
384
+ end
385
+ end
371
386
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: money-open-exchange-rates
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Laurent Arnoud
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-12 00:00:00.000000000 Z
11
+ date: 2016-09-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: money