money-historical-bank 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +3 -0
- data/LICENSE +22 -0
- data/README.markdown +43 -0
- data/lib/money/bank/historical_bank.rb +264 -0
- data/lib/money/bank/open_exchange_rates_loader.rb +35 -0
- data/test/historical_bank_test.rb +63 -0
- data/test/test.json +129 -0
- data/test/test_helper.rb +5 -0
- metadata +105 -0
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2011 Laurent Arnoud <laurent@spkdev.net>
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
'Software'), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
19
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
20
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
21
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
22
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# Money Historical Bank
|
2
|
+
|
3
|
+
A gem that add a `Money::Bank` able to handle historical rates, and infer rates from limited rates.
|
4
|
+
|
5
|
+
* You can add rates for any currency pair, at a special date. Use `home_run` gem if you need fast date handling in ruby.
|
6
|
+
* If no rates exist for a given date, the gem will try to download historical rates from [open-exchange-rates](http://josscrowcroft.github.com/open-exchange-rates/)
|
7
|
+
* The gem is able to guess inverse rates (EURUSD rate when only USDEUR is present), and go through USD when using other pairs. For example, GBPEUR will be calculated using USDGBP and USDEUR. This strategy isn't used if said rate (GBPEUR) is already set.
|
8
|
+
* No caching exists, but you can use `import_data` and `export_data` the same way `Money::Bank::VariableExchange` works.
|
9
|
+
|
10
|
+
## Usage
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
require 'money/bank/historical_bank'
|
14
|
+
mh = Money::Bank::HistoricalBank.new
|
15
|
+
|
16
|
+
# Exchanges 1000 EUR to USD using Date.today (default if no date has been entered).
|
17
|
+
# Will download today's rates if none have been entered
|
18
|
+
mh.exchange_with(1000.to_money('EUR'), 'USD')
|
19
|
+
|
20
|
+
# Exchanges 1000 EUR to USD using historical rates
|
21
|
+
date = Date.new(2009,9,9)
|
22
|
+
mh.set_rate(date, 'USD', 'EUR', 0.7634)
|
23
|
+
mh.exchange_with(date, 1000.to_money('USD'), 'EUR') # => 763.4 EUR
|
24
|
+
|
25
|
+
Money.default_bank = mh
|
26
|
+
```
|
27
|
+
|
28
|
+
## Refs
|
29
|
+
Created using mainly the base `VariableExchange` implementation, OpenExchangeRates implementation and idea based on `money-open-exchange-rates` gem.
|
30
|
+
|
31
|
+
* https://github.com/currencybot/open-exchange-rates
|
32
|
+
* https://github.com/RubyMoney/money
|
33
|
+
* https://github.com/spk/money-open-exchange-rates
|
34
|
+
|
35
|
+
## Extension
|
36
|
+
|
37
|
+
Feel free to create a new loader (cf `OpenExchangeRatesLoader`) if you know a source for more historical data.
|
38
|
+
Feel free to suggest refactoring.
|
39
|
+
|
40
|
+
## License
|
41
|
+
The MIT License
|
42
|
+
|
43
|
+
Copyright © 2011 Damien Couture <wam@atwam.com>
|
@@ -0,0 +1,264 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'money'
|
3
|
+
require 'date'
|
4
|
+
|
5
|
+
require File.expand_path(File.dirname(__FILE__)) + "/open_exchange_rates_loader"
|
6
|
+
|
7
|
+
class Money
|
8
|
+
module Bank
|
9
|
+
class InvalidCache < StandardError ; end
|
10
|
+
|
11
|
+
class HistoricalBank < Base
|
12
|
+
include Money::Bank::OpenExchangeRatesLoader
|
13
|
+
|
14
|
+
attr_reader :rates
|
15
|
+
# Available formats for importing/exporting rates.
|
16
|
+
RATE_FORMATS = [:json, :ruby, :yaml]
|
17
|
+
|
18
|
+
def setup
|
19
|
+
@rates = {}
|
20
|
+
@mutex = Mutex.new
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
# Set the rate for the given currency pair at a given date.
|
25
|
+
# Uses +Mutex+ to synchronize data access.
|
26
|
+
#
|
27
|
+
# @param [Date] date Date for which the rate is valid.
|
28
|
+
# @param [Currency, String, Symbol] from Currency to exchange from.
|
29
|
+
# @param [Currency, String, Symbol] to Currency to exchange to.
|
30
|
+
# @param [Numeric] rate Rate to use when exchanging currencies.
|
31
|
+
#
|
32
|
+
# @return [Numeric]
|
33
|
+
# @example
|
34
|
+
# bank = Money::Bank::HistoricalBank.new
|
35
|
+
# bank.set_rate(Date.new(2001, 1, 1), "USD", "CAD", 1.24514)
|
36
|
+
def set_rate(date, from, to, rate)
|
37
|
+
@mutex.synchronize do
|
38
|
+
internal_set_rate(date, from, to, rate)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Retrieve the rate for the given currencies. Uses +Mutex+ to synchronize
|
43
|
+
# data access. If no rates have been set for +date+, will try to load them
|
44
|
+
# using #load_data.
|
45
|
+
#
|
46
|
+
# @param [Date] date Date to retrieve the exchange rate at.
|
47
|
+
# @param [Currency, String, Symbol] from Currency to exchange from.
|
48
|
+
# @param [Currency, String, Symbol] to Currency to exchange to.
|
49
|
+
#
|
50
|
+
# @return [Numeric]
|
51
|
+
#
|
52
|
+
# @example
|
53
|
+
# bank = Money::Bank::HistoricalBank.new
|
54
|
+
# d1 = Date.new(2001, 1, 1)
|
55
|
+
# d2 = Date.new(2002, 1, 1)
|
56
|
+
# bank.set_rate(d1, "USD", "CAD", 1.24515)
|
57
|
+
# bank.set_rate(d2, "CAD", "USD", 0.803115)
|
58
|
+
#
|
59
|
+
# bank.get_rate(d1, "USD", "CAD") #=> 1.24515
|
60
|
+
# bank.get_rate(d2, "CAD", "USD") #=> 0.803115
|
61
|
+
def get_rate(date, from, to)
|
62
|
+
@mutex.synchronize do
|
63
|
+
unless existing_rates = @rates[date]
|
64
|
+
load_data(date)
|
65
|
+
existing_rates = @rates[date]
|
66
|
+
end
|
67
|
+
rate = nil
|
68
|
+
if existing_rates
|
69
|
+
rate = existing_rates[rate_key_for(from, to)]
|
70
|
+
unless rate
|
71
|
+
# Tries to calculate an inverse rate
|
72
|
+
inverse_rate = existing_rates[rate_key_for(to, from)]
|
73
|
+
rate = 1.0 / inverse_rate if inverse_rate
|
74
|
+
end
|
75
|
+
unless rate
|
76
|
+
# Tries to calculate a pair rate using USD rate
|
77
|
+
unless from_base_rate = existing_rates[rate_key_for("USD", from)]
|
78
|
+
from_inverse_rate = existing_rates[rate_key_for(from, "USD")]
|
79
|
+
from_base_rate = 1.0 / from_inverse_rate if from_inverse_rate
|
80
|
+
end
|
81
|
+
unless to_base_rate = existing_rates[rate_key_for("USD", to)]
|
82
|
+
to_inverse_rate = existing_rates[rate_key_for(to, "USD")]
|
83
|
+
to_base_rate = 1.0 / to_inverse_rate if to_inverse_rate
|
84
|
+
end
|
85
|
+
if to_base_rate && from_base_rate
|
86
|
+
rate = to_base_rate / from_base_rate
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
rate
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
#
|
95
|
+
# @overload exchange_with(from, to_currency)
|
96
|
+
# Exchanges the given +Money+ object to a new +Money+ object in
|
97
|
+
# +to_currency+. The exchange rate used will be for Date.today.
|
98
|
+
# If no rates are here for Date.today, it will try to load them.
|
99
|
+
# @param [Money] from
|
100
|
+
# The +Money+ object to exchange.
|
101
|
+
# @param [Currency, String, Symbol] to_currency
|
102
|
+
# The currency to exchange to.
|
103
|
+
#
|
104
|
+
# @overload exchange_with(date, from, to_currency)
|
105
|
+
# Exchanges the +Money+ object +from+ to a new +Money+ object in +to_currency+, using
|
106
|
+
# the exchange rate available on +date+.
|
107
|
+
# @param [Date] date The +Date+ at which you want to calculate the rate.
|
108
|
+
# @param [Money] from
|
109
|
+
# The +Money+ object to exchange.
|
110
|
+
# @param [Currency, String, Symbol] to_currency
|
111
|
+
# The currency to exchange to.
|
112
|
+
#
|
113
|
+
# @yield [n] Optional block to use when rounding after exchanging one
|
114
|
+
# currency for another.
|
115
|
+
# @yieldparam [Float] n The resulting float after exchanging one currency
|
116
|
+
# for another.
|
117
|
+
# @yieldreturn [Integer]
|
118
|
+
#
|
119
|
+
# @return [Money]
|
120
|
+
#
|
121
|
+
# @raise +Money::Bank::UnknownRate+ if the conversion rate is unknown.
|
122
|
+
#
|
123
|
+
# @example
|
124
|
+
# bank = Money::Bank::VariableExchange.new
|
125
|
+
# bank.add_rate(Date.today, "USD", "CAD", 1.24515)
|
126
|
+
# bank.add_rate(Date.new(2011,1,1), "CAD", "USD", 0.803115)
|
127
|
+
#
|
128
|
+
# c1 = 100_00.to_money("USD")
|
129
|
+
# c2 = 100_00.to_money("CAD")
|
130
|
+
#
|
131
|
+
# # Exchange 100 USD to CAD:
|
132
|
+
# bank.exchange_with(c1, "CAD") #=> #<Money @cents=1245150>
|
133
|
+
#
|
134
|
+
# # Exchange 100 CAD to USD:
|
135
|
+
# bank.exchange_with(Date.new(2011,1,1), c2, "USD") #=> #<Money @cents=803115>
|
136
|
+
def exchange_with(*args)
|
137
|
+
date, from, to_currency = args.length == 2 ? [Date.today] + args : args
|
138
|
+
|
139
|
+
return from if same_currency?(from.currency, to_currency)
|
140
|
+
|
141
|
+
rate = get_rate(date, from.currency, to_currency)
|
142
|
+
unless rate
|
143
|
+
raise UnknownRate, "No conversion rate available for #{date} '#{from.currency.iso_code}' -> '#{to_currency}'"
|
144
|
+
end
|
145
|
+
_to_currency_ = Currency.wrap(to_currency)
|
146
|
+
|
147
|
+
cents = BigDecimal.new(from.cents.to_s) / (BigDecimal.new(from.currency.subunit_to_unit.to_s) / BigDecimal.new(_to_currency_.subunit_to_unit.to_s))
|
148
|
+
|
149
|
+
ex = cents * BigDecimal.new(rate.to_s)
|
150
|
+
ex = ex.to_f
|
151
|
+
ex = if block_given?
|
152
|
+
yield ex
|
153
|
+
elsif @rounding_method
|
154
|
+
@rounding_method.call(ex)
|
155
|
+
else
|
156
|
+
ex.to_s.to_i
|
157
|
+
end
|
158
|
+
Money.new(ex, _to_currency_)
|
159
|
+
end
|
160
|
+
|
161
|
+
# Return the known rates as a string in the format specified. If +file+
|
162
|
+
# is given will also write the string out to the file specified.
|
163
|
+
# Available formats are +:json+, +:ruby+ and +:yaml+.
|
164
|
+
#
|
165
|
+
# @param [Symbol] format Request format for the resulting string.
|
166
|
+
# @param [String] file Optional file location to write the rates to.
|
167
|
+
#
|
168
|
+
# @return [String]
|
169
|
+
#
|
170
|
+
# @raise +Money::Bank::UnknownRateFormat+ if format is unknown.
|
171
|
+
#
|
172
|
+
# @example
|
173
|
+
# bank = Money::Bank::VariableExchange.new
|
174
|
+
# bank.set_rate("USD", "CAD", 1.24515)
|
175
|
+
# bank.set_rate("CAD", "USD", 0.803115)
|
176
|
+
#
|
177
|
+
# s = bank.export_rates(:json)
|
178
|
+
# s #=> "{\"USD_TO_CAD\":1.24515,\"CAD_TO_USD\":0.803115}"
|
179
|
+
def export_rates(format, file=nil)
|
180
|
+
raise Money::Bank::UnknownRateFormat unless
|
181
|
+
RATE_FORMATS.include? format
|
182
|
+
|
183
|
+
s = ""
|
184
|
+
@mutex.synchronize {
|
185
|
+
s = case format
|
186
|
+
when :json
|
187
|
+
JSON.dump(@rates)
|
188
|
+
when :ruby
|
189
|
+
Marshal.dump(@rates)
|
190
|
+
when :yaml
|
191
|
+
YAML.dump(@rates)
|
192
|
+
end
|
193
|
+
|
194
|
+
unless file.nil?
|
195
|
+
File.open(file, "w").write(s)
|
196
|
+
end
|
197
|
+
}
|
198
|
+
s
|
199
|
+
end
|
200
|
+
|
201
|
+
# Loads rates provided in +s+ given the specified format. Available
|
202
|
+
# formats are +:json+, +:ruby+ and +:yaml+.
|
203
|
+
#
|
204
|
+
# @param [Symbol] format The format of +s+.
|
205
|
+
# @param [String] s The rates string.
|
206
|
+
#
|
207
|
+
# @return [self]
|
208
|
+
#
|
209
|
+
# @raise +Money::Bank::UnknownRateFormat+ if format is unknown.
|
210
|
+
#
|
211
|
+
# @example
|
212
|
+
# s = "{\"USD_TO_CAD\":1.24515,\"CAD_TO_USD\":0.803115}"
|
213
|
+
# bank = Money::Bank::VariableExchange.new
|
214
|
+
# bank.import_rates(:json, s)
|
215
|
+
#
|
216
|
+
# bank.get_rate("USD", "CAD") #=> 1.24515
|
217
|
+
# bank.get_rate("CAD", "USD") #=> 0.803115
|
218
|
+
def import_rates(format, s)
|
219
|
+
raise Money::Bank::UnknownRateFormat unless
|
220
|
+
RATE_FORMATS.include? format
|
221
|
+
|
222
|
+
@mutex.synchronize {
|
223
|
+
@rates = case format
|
224
|
+
when :json
|
225
|
+
JSON.load(s)
|
226
|
+
when :ruby
|
227
|
+
Marshal.load(s)
|
228
|
+
when :yaml
|
229
|
+
YAML.load(s)
|
230
|
+
end
|
231
|
+
}
|
232
|
+
self
|
233
|
+
end
|
234
|
+
|
235
|
+
private
|
236
|
+
# Return the rate hashkey for the given currencies.
|
237
|
+
#
|
238
|
+
# @param [Currency, String, Symbol] from The currency to exchange from.
|
239
|
+
# @param [Currency, String, Symbol] to The currency to exchange to.
|
240
|
+
#
|
241
|
+
# @return [String]
|
242
|
+
#
|
243
|
+
# @example
|
244
|
+
# rate_key_for("USD", "CAD") #=> "USD_TO_CAD"
|
245
|
+
def rate_key_for(from, to)
|
246
|
+
"#{Currency.wrap(from).iso_code}_TO_#{Currency.wrap(to).iso_code}".upcase
|
247
|
+
end
|
248
|
+
|
249
|
+
# Set the rate for the given currency pair at a given date.
|
250
|
+
# Doesn't use any mutex.
|
251
|
+
#
|
252
|
+
# @param [Date] date Date for which the rate is valid.
|
253
|
+
# @param [Currency, String, Symbol] from Currency to exchange from.
|
254
|
+
# @param [Currency, String, Symbol] to Currency to exchange to.
|
255
|
+
# @param [Numeric] rate Rate to use when exchanging currencies.
|
256
|
+
#
|
257
|
+
# @return [Numeric]
|
258
|
+
def internal_set_rate(date, from, to, rate)
|
259
|
+
date_rates = @rates[date] ||= {}
|
260
|
+
date_rates[rate_key_for(from, to)] = rate
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'money'
|
3
|
+
require 'date'
|
4
|
+
require 'yajl'
|
5
|
+
require 'open-uri'
|
6
|
+
|
7
|
+
class Money
|
8
|
+
module Bank
|
9
|
+
module OpenExchangeRatesLoader
|
10
|
+
HIST_URL = 'https://raw.github.com/currencybot/open-exchange-rates/master/historical/'
|
11
|
+
OER_URL = 'http://openexchangerates.org/latest.php'
|
12
|
+
|
13
|
+
# Tries to load data from OpenExchangeRates for the given rate.
|
14
|
+
# Won't do anything if there's no data available for that date
|
15
|
+
# in OpenExchangeRates (short) history.
|
16
|
+
def load_data(date)
|
17
|
+
rates_source = if date == Date.today
|
18
|
+
OER_URL
|
19
|
+
else
|
20
|
+
# Should we use strftime, does to_s have better performance ? Or is it localized accross systems ?
|
21
|
+
HIST_URL + date.to_s + '.json'
|
22
|
+
end
|
23
|
+
doc = Yajl::Parser.parse(open(rates_source).read)
|
24
|
+
|
25
|
+
base_currency = doc['base'] || 'USD'
|
26
|
+
|
27
|
+
doc['rates'].each do |currency, rate|
|
28
|
+
# Don't use set_rate here, since this method can only be called from
|
29
|
+
# get_rate, which already aquired a mutex.
|
30
|
+
internal_set_rate(date, base_currency, currency, rate)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'test_helper'))
|
4
|
+
|
5
|
+
describe Money::Bank::HistoricalBank do
|
6
|
+
|
7
|
+
describe 'update_rates' do
|
8
|
+
before do
|
9
|
+
@bank = Money::Bank::HistoricalBank.new
|
10
|
+
#@bank.cache = @cache_path
|
11
|
+
#@bank.update_rates
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should store any rate stored for a date, and retrieve it when asked" do
|
15
|
+
d1 = Date.new(2001,1,1)
|
16
|
+
d2 = Date.new(2002,1,1)
|
17
|
+
@bank.set_rate(d1, "USD", "EUR", 1.234)
|
18
|
+
@bank.set_rate(d2, "GBP", "USD", 1.456)
|
19
|
+
|
20
|
+
@bank.get_rate(d1, "USD", "EUR").must_equal 1.234
|
21
|
+
@bank.get_rate(d2, "GBP", "USD").must_equal 1.456
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should return the correct rate interpolated from existing pairs when asked" do
|
25
|
+
d1 = Date.new(2001,1,1)
|
26
|
+
@bank.set_rate(d1, "USD", "EUR", 1.234)
|
27
|
+
@bank.set_rate(d1, "GBP", "USD", 1.456)
|
28
|
+
|
29
|
+
@bank.get_rate(d1, "EUR", "USD").must_be_within_epsilon 1.0 / 1.234
|
30
|
+
@bank.get_rate(d1, "GBP", "EUR").must_be_within_epsilon 1.456 * 1.234
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should return the correct rates using exchange_with a date" do
|
34
|
+
d1 = Date.new(2001,1,1)
|
35
|
+
@bank.set_rate(d1, "USD", "EUR", 0.73062465)
|
36
|
+
@bank.exchange_with(d1, 5000.to_money('EUR'), 'USD').cents.must_equal 684345
|
37
|
+
end
|
38
|
+
it "should return the correct rates using exchange_with no date (today)" do
|
39
|
+
d1 = Date.today
|
40
|
+
@bank.set_rate(d1, "USD", "EUR", 0.8)
|
41
|
+
@bank.exchange_with(5000.to_money('EUR'), 'USD').cents.must_equal 625000
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
describe 'no rates available yet' do
|
47
|
+
include RR::Adapters::TestUnit
|
48
|
+
before do
|
49
|
+
@bank = Money::Bank::HistoricalBank.new
|
50
|
+
@cache_path = "#{File.dirname(__FILE__)}/test.json"
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should download new rates from url' do
|
54
|
+
source = Money::Bank::OpenExchangeRatesLoader::HIST_URL + '2009-09-09.json'
|
55
|
+
stub(@bank).open(source) { File.open @cache_path }
|
56
|
+
d1 = Date.new(2009,9,9)
|
57
|
+
|
58
|
+
rate = @bank.get_rate(d1, 'USD', 'EUR')
|
59
|
+
rate.must_equal 0.73062465
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
data/test/test.json
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
{
|
2
|
+
"disclaimer": "This data is collected from various providers and provided free of charge for informational purposes only, with no guarantee whatsoever of accuracy, validity, availability or fitness for any purpose; use at your own risk. Other than that - have fun, and please share/watch/fork if you think data like this should be free!",
|
3
|
+
"license": "all code open-source under GPL v3 [http://www.opensource.org/licenses/GPL-3.0]. all data made available by various providers; copyright may apply; not for resale; no warranties given.",
|
4
|
+
"timestamp": 1318931535,
|
5
|
+
"base": "USD",
|
6
|
+
"rates": {
|
7
|
+
"AED": 3.67000274,
|
8
|
+
"ALL": 103.01253573,
|
9
|
+
"ANG": 1.79614315,
|
10
|
+
"ARS": 4.22279733,
|
11
|
+
"AUD": 0.985166,
|
12
|
+
"AWG": 1.788773,
|
13
|
+
"BBD": 1.99964999,
|
14
|
+
"BDT": 76.15338649,
|
15
|
+
"BGN": 1.41994959,
|
16
|
+
"BHD": 0.37704772,
|
17
|
+
"BIF": 1218.55496226,
|
18
|
+
"BMD": 0.99949722,
|
19
|
+
"BND": 1.27225861,
|
20
|
+
"BOB": 6.91736836,
|
21
|
+
"BRL": 1.77381475,
|
22
|
+
"BSD": 0.99954175,
|
23
|
+
"BTN": 49.05028406,
|
24
|
+
"BYR": 7308.49243258,
|
25
|
+
"BZD": 1.98384726,
|
26
|
+
"CAD": 1.02336071,
|
27
|
+
"CHF": 0.90167657,
|
28
|
+
"CLP": 487.11197257,
|
29
|
+
"CNY": 6.38085304,
|
30
|
+
"COP": 1826.6698892,
|
31
|
+
"CRC": 521.8990447,
|
32
|
+
"CZK": 18.0694024,
|
33
|
+
"DKK": 5.44049406,
|
34
|
+
"DOP": 38.25438217,
|
35
|
+
"DZD": 73.81094439,
|
36
|
+
"EEK": 12.07815511,
|
37
|
+
"EGP": 5.97000248,
|
38
|
+
"ETB": 17.19251636,
|
39
|
+
"EUR": 0.73062465,
|
40
|
+
"FJD": 1.83036833,
|
41
|
+
"GBP": 0.63603926,
|
42
|
+
"GMD": 28.76426182,
|
43
|
+
"GNF": 7306.12192981,
|
44
|
+
"GTQ": 7.83918646,
|
45
|
+
"HKD": 7.77640265,
|
46
|
+
"HNL": 18.87502384,
|
47
|
+
"HRK": 5.45529344,
|
48
|
+
"HTG": 40.35709926,
|
49
|
+
"HUF": 214.84221403,
|
50
|
+
"IDR": 7306.81897687,
|
51
|
+
"ILS": 3.64949785,
|
52
|
+
"INR": 49.37039746,
|
53
|
+
"IQD": 1217.80316493,
|
54
|
+
"IRR": 7307.93452885,
|
55
|
+
"ISK": 115.9989631,
|
56
|
+
"JMD": 85.97569959,
|
57
|
+
"JOD": 0.70868135,
|
58
|
+
"JPY": 76.72400038,
|
59
|
+
"KES": 98.76466584,
|
60
|
+
"KMF": 365.42927124,
|
61
|
+
"KRW": 1218.09757292,
|
62
|
+
"KWD": 0.27560788,
|
63
|
+
"KYD": 0.81903871,
|
64
|
+
"KZT": 149.11496117,
|
65
|
+
"LBP": 1461.32661693,
|
66
|
+
"LKR": 110.70093173,
|
67
|
+
"LSL": 8.0465418,
|
68
|
+
"LTL": 2.52287977,
|
69
|
+
"LVL": 0.51543231,
|
70
|
+
"MAD": 8.21085207,
|
71
|
+
"MDL": 11.61789383,
|
72
|
+
"MKD": 44.55887535,
|
73
|
+
"MNT": 1217.94260361,
|
74
|
+
"MOP": 8.00333931,
|
75
|
+
"MRO": 292.28205422,
|
76
|
+
"MUR": 28.88162297,
|
77
|
+
"MVR": 15.31876757,
|
78
|
+
"MWK": 166.11689667,
|
79
|
+
"MXN": 13.51340243,
|
80
|
+
"MYR": 3.13293632,
|
81
|
+
"NAD": 8.04971592,
|
82
|
+
"NGN": 162.42231002,
|
83
|
+
"NIO": 22.76948135,
|
84
|
+
"NOK": 5.65814755,
|
85
|
+
"NPR": 78.5914389,
|
86
|
+
"NZD": 1.26937516,
|
87
|
+
"OMR": 0.38491346,
|
88
|
+
"PAB": 0.99933189,
|
89
|
+
"PEN": 2.72220031,
|
90
|
+
"PGK": 2.17003989,
|
91
|
+
"PHP": 43.24670259,
|
92
|
+
"PKR": 87.00825226,
|
93
|
+
"PLN": 3.17724869,
|
94
|
+
"PYG": 3655.78872997,
|
95
|
+
"QAR": 3.64122541,
|
96
|
+
"RON": 3.18309814,
|
97
|
+
"RUB": 31.24605524,
|
98
|
+
"RWF": 609.18567356,
|
99
|
+
"SAR": 3.7488354,
|
100
|
+
"SBD": 7.38406858,
|
101
|
+
"SCR": 12.62561094,
|
102
|
+
"SEK": 6.69630223,
|
103
|
+
"SGD": 1.27495292,
|
104
|
+
"SKK": 22.07966229,
|
105
|
+
"SLL": 3654.18384486,
|
106
|
+
"SVC": 8.74162128,
|
107
|
+
"SZL": 8.05732772,
|
108
|
+
"THB": 30.70586701,
|
109
|
+
"TND": 1.42622659,
|
110
|
+
"TOP": 1.70695633,
|
111
|
+
"TRY": 1.86605172,
|
112
|
+
"TTD": 6.40445307,
|
113
|
+
"TWD": 30.07194885,
|
114
|
+
"TZS": 1826.90594941,
|
115
|
+
"UAH": 8.00396967,
|
116
|
+
"UGX": 2435.87459922,
|
117
|
+
"USD": 1,
|
118
|
+
"UYU": 19.97292206,
|
119
|
+
"VUV": 92.53276399,
|
120
|
+
"WST": 2.28297876,
|
121
|
+
"XAF": 487.33923469,
|
122
|
+
"XCD": 2.69810192,
|
123
|
+
"XOF": 487.27721607,
|
124
|
+
"XPF": 85.9900992,
|
125
|
+
"YER": 214.97524163,
|
126
|
+
"ZAR": 8.05499975,
|
127
|
+
"ZMK": 3636.84384705
|
128
|
+
}
|
129
|
+
}
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: money-historical-bank
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.1
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Damien Couture
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-12-04 00:00:00 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: yajl-ruby
|
17
|
+
prerelease: false
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.8.3
|
24
|
+
type: :runtime
|
25
|
+
version_requirements: *id001
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: money
|
28
|
+
prerelease: false
|
29
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 3.7.1
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id002
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: minitest
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: "2.0"
|
46
|
+
type: :development
|
47
|
+
version_requirements: *id003
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: rr
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: 1.0.4
|
57
|
+
type: :development
|
58
|
+
version_requirements: *id004
|
59
|
+
description: A gem that provides rates for the money gem. Able to handle history (rates varying in time), and auto download rates from open-exchange-rates. Highly inspired by money-open-exchange-rates gem.
|
60
|
+
email: wam@atwam.com
|
61
|
+
executables: []
|
62
|
+
|
63
|
+
extensions: []
|
64
|
+
|
65
|
+
extra_rdoc_files:
|
66
|
+
- README.markdown
|
67
|
+
files:
|
68
|
+
- LICENSE
|
69
|
+
- README.markdown
|
70
|
+
- Gemfile
|
71
|
+
- lib/money/bank/open_exchange_rates_loader.rb
|
72
|
+
- lib/money/bank/historical_bank.rb
|
73
|
+
- test/test_helper.rb
|
74
|
+
- test/test.json
|
75
|
+
- test/historical_bank_test.rb
|
76
|
+
homepage: http://github.com/coutud/money-historical-bank
|
77
|
+
licenses: []
|
78
|
+
|
79
|
+
post_install_message:
|
80
|
+
rdoc_options: []
|
81
|
+
|
82
|
+
require_paths:
|
83
|
+
- lib
|
84
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: "0"
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
+
none: false
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: "0"
|
96
|
+
requirements: []
|
97
|
+
|
98
|
+
rubyforge_project:
|
99
|
+
rubygems_version: 1.8.11
|
100
|
+
signing_key:
|
101
|
+
specification_version: 3
|
102
|
+
summary: A gem that offers exchange rates varying in time.
|
103
|
+
test_files:
|
104
|
+
- test/historical_bank_test.rb
|
105
|
+
has_rdoc:
|