exchange 0.8.0 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/.rspec +1 -1
- data/Gemfile.lock +3 -3
- data/README.rdoc +115 -47
- data/benchmark/benchmark.rb +49 -0
- data/changelog.rdoc +8 -1
- data/lib/exchange.rb +4 -4
- data/lib/exchange/base.rb +1 -1
- data/lib/exchange/cache.rb +2 -0
- data/lib/exchange/cache/base.rb +20 -6
- data/lib/exchange/cache/configuration.rb +24 -0
- data/lib/exchange/cache/file.rb +24 -9
- data/lib/exchange/cache/memcached.rb +3 -3
- data/lib/exchange/cache/memory.rb +89 -0
- data/lib/exchange/cache/rails.rb +1 -1
- data/lib/exchange/cache/redis.rb +4 -4
- data/lib/exchange/configurable.rb +53 -0
- data/lib/exchange/configuration.rb +32 -26
- data/lib/exchange/core_extensions.rb +3 -0
- data/lib/exchange/core_extensions/cachify.rb +25 -0
- data/lib/exchange/core_extensions/float/error_safe.rb +25 -0
- data/lib/{core_extensions → exchange/core_extensions/numeric}/conversability.rb +12 -12
- data/lib/exchange/external_api.rb +2 -1
- data/lib/exchange/external_api/base.rb +34 -9
- data/lib/exchange/external_api/call.rb +6 -8
- data/lib/exchange/external_api/configuration.rb +25 -0
- data/lib/exchange/external_api/ecb.rb +16 -25
- data/lib/exchange/external_api/json.rb +11 -1
- data/lib/exchange/external_api/open_exchange_rates.rb +65 -0
- data/lib/exchange/external_api/xavier_media.rb +7 -7
- data/lib/exchange/iso_4217.rb +32 -5
- data/lib/exchange/{currency.rb → money.rb} +112 -110
- data/lib/exchange/typecasting.rb +94 -0
- data/spec/exchange/cache/base_spec.rb +2 -2
- data/spec/exchange/cache/configuration_spec.rb +56 -0
- data/spec/exchange/cache/file_spec.rb +10 -8
- data/spec/exchange/cache/memcached_spec.rb +9 -18
- data/spec/exchange/cache/memory_spec.rb +122 -0
- data/spec/exchange/cache/no_cache_spec.rb +5 -15
- data/spec/exchange/cache/rails_spec.rb +2 -6
- data/spec/exchange/cache/redis_spec.rb +8 -18
- data/spec/exchange/configuration_spec.rb +31 -7
- data/spec/exchange/core_extensions/array/cachify_spec.rb +12 -0
- data/spec/exchange/core_extensions/float/error_safe_spec.rb +49 -0
- data/spec/exchange/core_extensions/hash/cachify_spec.rb +12 -0
- data/spec/exchange/core_extensions/numeric/cachify_spec.rb +26 -0
- data/spec/{core_extensions → exchange/core_extensions/numeric}/conversability_spec.rb +22 -22
- data/spec/exchange/core_extensions/string/cachify_spec.rb +59 -0
- data/spec/exchange/core_extensions/symbol/cachify_spec.rb +12 -0
- data/spec/exchange/external_api/base_spec.rb +10 -7
- data/spec/exchange/external_api/call_spec.rb +3 -0
- data/spec/exchange/external_api/configuration_spec.rb +52 -0
- data/spec/exchange/external_api/ecb_spec.rb +8 -5
- data/spec/exchange/external_api/open_exchange_rates_spec.rb +70 -0
- data/spec/exchange/external_api/xavier_media_spec.rb +8 -5
- data/spec/exchange/iso_4217_spec.rb +208 -20
- data/spec/exchange/{currency_spec.rb → money_spec.rb} +102 -82
- data/spec/exchange/typecasting_spec.rb +86 -0
- metadata +117 -71
- data/exchange-0.7.5.gem +0 -0
- data/exchange-0.7.6.gem +0 -0
- data/lib/exchange/external_api/currency_bot.rb +0 -61
- data/spec/exchange/external_api/currency_bot_spec.rb +0 -63
data/.gitignore
CHANGED
data/.rspec
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
--color
|
2
|
-
--format
|
2
|
+
--format progress
|
data/Gemfile.lock
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
exchange (0.
|
4
|
+
exchange (0.9.0)
|
5
5
|
json (>= 1.0.0)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: http://rubygems.org/
|
9
9
|
specs:
|
10
|
-
dalli (2.
|
10
|
+
dalli (2.3.0)
|
11
11
|
diff-lcs (1.1.3)
|
12
12
|
json (1.7.5)
|
13
13
|
nokogiri (1.5.5)
|
@@ -21,7 +21,7 @@ GEM
|
|
21
21
|
rspec-expectations (2.11.3)
|
22
22
|
diff-lcs (~> 1.1.3)
|
23
23
|
rspec-mocks (2.11.3)
|
24
|
-
yard (0.8.
|
24
|
+
yard (0.8.3)
|
25
25
|
|
26
26
|
PLATFORMS
|
27
27
|
java
|
data/README.rdoc
CHANGED
@@ -4,6 +4,16 @@ The Exchange Gem gives you easy access to currency functions directly on your Nu
|
|
4
4
|
|
5
5
|
You can use it with just plain ruby projects, in Rails 2 and 3, Sinatra or whatever Framework you like.
|
6
6
|
|
7
|
+
== Installation
|
8
|
+
=== Bundler / Rails
|
9
|
+
Add it to your Gemfile
|
10
|
+
gem "exchange", ">=0.8.0"
|
11
|
+
=== Manually
|
12
|
+
Just install it as a gem
|
13
|
+
gem install exchange
|
14
|
+
Then require it
|
15
|
+
require 'exchange'
|
16
|
+
|
7
17
|
== Features
|
8
18
|
|
9
19
|
=== Easy Conversion
|
@@ -12,6 +22,63 @@ Conversion of currencies does not get any easier
|
|
12
22
|
1.eur.to_usd
|
13
23
|
or better for historic dates
|
14
24
|
1.eur.to_usd(:at => Time.now - 84600)
|
25
|
+
|
26
|
+
|
27
|
+
=== Precise Calculation
|
28
|
+
|
29
|
+
You may know the deal: Floating Point Errors can cost you money:
|
30
|
+
|
31
|
+
(0.29 * 50).round #=> 14, which is incorrect
|
32
|
+
|
33
|
+
Whereas
|
34
|
+
|
35
|
+
(BigDecimal("0.29") * 50).round #=> 15, which is correct
|
36
|
+
|
37
|
+
Exchange uses BigDecimal in all its currency and conversion operations, so you will not be a likely victim for floating point inaccuracies. It even does implicitly convert counterparts of basic operations like (* / - +) to calculate your values safely:
|
38
|
+
|
39
|
+
(50.usd * 0.29).round 0 #=> "USD 15.00"
|
40
|
+
(0.29 * 50.usd).round 0 #=> 15
|
41
|
+
|
42
|
+
=== BigDecimal? Sounds slow to me
|
43
|
+
|
44
|
+
If performance combined with conversion is your concern, {head over to this benchmark}[https://github.com/beatrichartz/exchange/blob/master/benchmark/benchmark.rb]. With ruby 1.9.3, you'll get about the following results
|
45
|
+
|
46
|
+
1000 operations
|
47
|
+
|
48
|
+
Normal Float Operation takes 0.000196s
|
49
|
+
Big Decimal Operation takes 0.001239s
|
50
|
+
Money gem Operation takes 0.05348s
|
51
|
+
Exchange gem Operation takes 0.035287s
|
52
|
+
|
53
|
+
You're right that Big Decimal is slower than Float operations, but then again, the exchange gem outscores the money gem.
|
54
|
+
|
55
|
+
=== A mixin for typecasting
|
56
|
+
|
57
|
+
There may be a need for you to typecast an attribute of an object as money. Exchange features a typecasting mixin, which you can use with Rails, Ohm, Datamapper, or just plain ruby classes to typecast an attribute as money. Use it like this:
|
58
|
+
|
59
|
+
class Article
|
60
|
+
# make the class method available
|
61
|
+
#
|
62
|
+
extend Exchange::Typecasting
|
63
|
+
|
64
|
+
# Install the typecasting for price
|
65
|
+
#
|
66
|
+
money :price, :currency => :currency
|
67
|
+
|
68
|
+
# let's say you have currency set in a unique place
|
69
|
+
#
|
70
|
+
def currency
|
71
|
+
manager.currency
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
Now you're able to do this:
|
76
|
+
|
77
|
+
article = Article.new
|
78
|
+
article.price #=> will give you money in the currency defined on the manager
|
79
|
+
article.price = 3.45.usd #Will implicitly convert the price if manager.currency is not :usd
|
80
|
+
|
81
|
+
You can feed the currency option with a proc or a symbol representing the method. For in-depth information about typecasting {visit the documentation here}[http://rubydoc.info/github/beatrichartz/exchange/Exchange/Typecasting]
|
15
82
|
|
16
83
|
=== Only one request per day to keep you up to date
|
17
84
|
|
@@ -21,11 +88,9 @@ You're hitting the internet only daily to get new rates (hourly updates are avai
|
|
21
88
|
On of the issues with currencies is: You never know the format they should be in. With Exchange, you can just use the currencies
|
22
89
|
to_s method, which takes care of the right format for you. You can either have a string with the currency code in front, or just the amount in the right format
|
23
90
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
Exchange::ISO4217.stringif(34.34, :omr).to_s(:iso) #=> "34.340"
|
28
|
-
|
91
|
+
49.567.usd.to_s #=> "USD 49.57"
|
92
|
+
45.jpy.to_s #=> "JPY 45"
|
93
|
+
34.34.omr.to_s #=> "OMR 34.340"
|
29
94
|
|
30
95
|
=== Use three great APIs or your own
|
31
96
|
|
@@ -33,7 +98,7 @@ Three open APIs are already included:
|
|
33
98
|
|
34
99
|
- {Xaviermedia}[http://www.xavierforum.com/viewtopic.php?f=5&t=10979&sid=671a685edbfa5dbec219fbc6793d5057]
|
35
100
|
- {European Central Bank}[http://www.ecb.int/stats/exchange/eurofxref/html/index.en.html]
|
36
|
-
- {
|
101
|
+
- {Open Exchange Rates}[http://openexchangerates.org/] (Look for the free plan at the bottom of the page)
|
37
102
|
|
38
103
|
but if you have another API you like to use, it becomes as easy as writing one Class and two methods to use it.
|
39
104
|
{Example of a custom API Extension}[http://rubydoc.info/github/beatrichartz/exchange/Exchange/ExternalAPI]
|
@@ -49,41 +114,31 @@ Use one of three available caching solutions:
|
|
49
114
|
But, same here, if you don't like any of these or want to use your own caching solution, it is as easy as writing one Class and two methods to use it.
|
50
115
|
{Example of a custom cache extension}[http://rubydoc.info/github/beatrichartz/exchange/Exchange/Cache]
|
51
116
|
|
52
|
-
== Installation
|
53
|
-
=== Bundler / Rails
|
54
|
-
Add it to your Gemfile
|
55
|
-
gem "exchange", ">=0.7.3"
|
56
|
-
=== Manually
|
57
|
-
Just install it as a gem
|
58
|
-
gem install exchange
|
59
|
-
Then require it
|
60
|
-
require 'exchange'
|
61
|
-
|
62
117
|
== Basic Operations
|
63
118
|
|
64
119
|
=== Convert
|
65
120
|
|
66
121
|
Converting one currency to another is as easy as 1,2,3. Don't be afraid, even if it returns a currency object, all Fixed and Float operations can be applied as method missing routes to the value
|
67
122
|
|
68
|
-
1.usd.to_eur #=> #<Exchange::
|
69
|
-
2.3.dkk.to_sek #=> #<Exchange::
|
70
|
-
45.54.nok.to_sek #=> #<Exchange::
|
123
|
+
1.usd.to_eur #=> #<Exchange::Money @value=0.93 @currency=:eur>
|
124
|
+
2.3.dkk.to_sek #=> #<Exchange::Money @value=3.33 @currency=:sek>
|
125
|
+
45.54.nok.to_sek #=> #<Exchange::Money @value=3.33 @currency=:sek>
|
71
126
|
|
72
127
|
Easily convert one currency to another at a historical rate
|
73
128
|
|
74
|
-
1.52.usd.to_eur :at => '2011-01-01' #=> #<Exchange::
|
75
|
-
3.45.eur.to_sek :at => Time.gm(2011,3,3) #=> #<Exchange::
|
76
|
-
345.sek.to_nok :at => Time.gm(2011,3,3) #=> #<Exchange::
|
129
|
+
1.52.usd.to_eur :at => '2011-01-01' #=> #<Exchange::Money @value=1.23 @currency=:eur>
|
130
|
+
3.45.eur.to_sek :at => Time.gm(2011,3,3) #=> #<Exchange::Money @value=19.23 @currency=:sek>
|
131
|
+
345.sek.to_nok :at => Time.gm(2011,3,3) #=> #<Exchange::Money @value=348 @currency=:nok>
|
77
132
|
|
78
133
|
Or even define an instance of currency as historic by adding a time.
|
79
134
|
|
80
|
-
1.52.usd(:at => '2011-01-01').to_eur #=> #<Exchange::
|
81
|
-
3.45.eur(:at => Time.gm(2011,3,3)).to_sek #=> #<Exchange::
|
82
|
-
345.sek(:at => Time.gm(2011,3,3)).to_nok #=> #<Exchange::
|
135
|
+
1.52.usd(:at => '2011-01-01').to_eur #=> #<Exchange::Money @value=1.23 @currency=:eur>
|
136
|
+
3.45.eur(:at => Time.gm(2011,3,3)).to_sek #=> #<Exchange::Money @value=19.23 @currency=:sek>
|
137
|
+
345.sek(:at => Time.gm(2011,3,3)).to_nok #=> #<Exchange::Money @value=348 @currency=:nok>
|
83
138
|
|
84
139
|
Do multiple conversion steps at once (if in any way useful)
|
85
140
|
|
86
|
-
3.chf.to_eur(:at => '2011-02-04').to_usd #=> #<Exchange::
|
141
|
+
3.chf.to_eur(:at => '2011-02-04').to_usd #=> #<Exchange::Money @value=5.3 @currency=:eur>
|
87
142
|
|
88
143
|
|
89
144
|
=== Compare
|
@@ -99,49 +154,54 @@ Compare Currencies, they will convert implicitly
|
|
99
154
|
|
100
155
|
Sort multiple currencies at once
|
101
156
|
|
102
|
-
[5.eur, 4.usd, 4.chf(:at => '2010-01-01')].sort #=> [#<Exchange::
|
157
|
+
[5.eur, 4.usd, 4.chf(:at => '2010-01-01')].sort #=> [#<Exchange::Money @value=4 @currency=:usd>, #<Exchange::Money @value=4 @currency=:chf>, #<Exchange::Money @value=5 @currency=:eur>]
|
103
158
|
|
104
159
|
This is true, because it uses the same historic conversion rate
|
105
160
|
|
106
161
|
3.eur(:at => '201-01-01').to_usd == 3.eur.to_usd(:at => '201-01-01')
|
107
162
|
|
108
|
-
But this is false, obviously, because the second instance uses the present exchange rate
|
163
|
+
But this is false, obviously, because the second instance uses the present exchange rate which differs from the historic one (if the two rates match, this will be true again)
|
109
164
|
|
110
|
-
3.eur(:at => '
|
165
|
+
3.eur(:at => '2001-01-01').to_usd == 3.eur.to_usd
|
111
166
|
|
112
167
|
=== Operate
|
113
168
|
|
114
169
|
Add, Subtract, Multiply, Divide Currencies and don't lose a dime. The result will get returned in the currency of the first argument
|
115
170
|
|
116
|
-
1.usd + 1.32.eur #=> #<Exchange::
|
117
|
-
1.usd - 1.32.eur #=> #<Exchange::
|
118
|
-
1.usd * 1.32.eur #=> #<Exchange::
|
119
|
-
1.usd / 1.32.eur #=> #<Exchange::
|
171
|
+
1.usd + 1.32.eur #=> #<Exchange::Money @value=2.54 @currency=:usd>
|
172
|
+
1.usd - 1.32.eur #=> #<Exchange::Money @value=-0.2 @currency=:usd>
|
173
|
+
1.usd * 1.32.eur #=> #<Exchange::Money @value=3.44 @currency=:usd>
|
174
|
+
1.usd / 1.32.eur #=> #<Exchange::Money @value=0.89 @currency=:usd>
|
120
175
|
|
121
176
|
|
122
177
|
If you define a currency object as historic. It will use historic conversion if it gets converted (in this example, the 1.32 eur will get converted to usd at the rate of January 1 2008)
|
123
178
|
|
124
|
-
1.usd - 1.32.eur(:at => '2008-1-1') #=> #<Exchange::
|
179
|
+
1.usd - 1.32.eur(:at => '2008-1-1') #=> #<Exchange::Money @value=2.54 @currency=:usd>
|
180
|
+
|
181
|
+
You can just instantiate currencies and apply operations. Rounding will by default round the currency to its ISO4217 decimal precision:
|
125
182
|
|
126
|
-
|
183
|
+
3.123.eur.round #=> #<Exchange::Money @value=3.12 @currency=:eur>
|
184
|
+
|
185
|
+
You can also pass the precision you wish for as an argument, round, ceil, floor act like normal:
|
127
186
|
|
128
|
-
3.
|
187
|
+
3.1234.eur.round(0) #=> #<Exchange::Money @value=3 @currency=:eur>
|
129
188
|
|
130
189
|
Convert one currency to another and round, ceil or floor it, it still retains currency information of the actual and previous currency
|
131
190
|
|
132
|
-
1.34.usd.to_eur.round
|
133
|
-
10.34.usd.to_nok.ceil
|
134
|
-
5.34.usd.to_eur.floor
|
135
|
-
5.34.usd.to_eur.floor.from #=> #<Exchange::
|
191
|
+
1.34.usd.to_eur.round(0) #=> #<Exchange::Money @value=1 @currency=:eur>
|
192
|
+
10.34.usd.to_nok.ceil(0) #=> #<Exchange::Money @value=45 @currency=:nok>
|
193
|
+
5.34.usd.to_eur.floor(0) #=> #<Exchange::Money @value=4 @currency=:eur>
|
194
|
+
5.34.usd.to_eur.floor.from #=> #<Exchange::Money @value=5.34 @currency=:usd>
|
136
195
|
|
137
196
|
|
138
197
|
=== Retain Information
|
139
198
|
|
140
199
|
Access the original currency and its value after conversion, even over multiple steps
|
141
|
-
|
142
|
-
converted.
|
143
|
-
|
144
|
-
converted2.
|
200
|
+
|
201
|
+
converted = 2.eur.to_usd #=> #<Exchange::Money @value=2.12 @currency=:usd>
|
202
|
+
converted.from #=> #<Exchange::Money @value=2 @currency=:eur>
|
203
|
+
converted2 = converted.to_nok #=> #<Exchange::Money @value=22.12 @currency=:nok>
|
204
|
+
converted2.from #=> #<Exchange::Money @value=2.12 @currency=:usd>
|
145
205
|
|
146
206
|
== Configuration
|
147
207
|
|
@@ -157,7 +217,7 @@ You can configure the exchange gem to a variety of options, allowing you to cont
|
|
157
217
|
The options available are
|
158
218
|
|
159
219
|
:cache Takes the cache options as a hash, the options are:
|
160
|
-
:subclass (default :
|
220
|
+
:subclass (default :memory) The cache subclass to use for caching. Available: Memory, Rails cache, Redis, Memcached, File
|
161
221
|
:host (default '127.0.0.1') A string with the hostname or IP to set the cache host to. Does not have to be set for Rails cache
|
162
222
|
:port (default 11211) An integer for the cache port. Does not have to be set for Rails cache
|
163
223
|
:expire (default :daily) Which period is used to expire the cache, :daily or :hourly are available
|
@@ -166,6 +226,7 @@ The options available are
|
|
166
226
|
:subclass (default :xavier_media) The api to use. Available: Xavier Media, ECB, Currency Bot
|
167
227
|
:retries (default 5) The number of times the gem should retry to connect to the api host
|
168
228
|
:app_id (default nil) The app id to use with your api request
|
229
|
+
:protocol (default :http) The protocol to use with the request
|
169
230
|
|
170
231
|
:allow_mixed_opterations (default true) If set to false, Operations with with different currencies raise errors.
|
171
232
|
|
@@ -209,10 +270,17 @@ Use the Xaviermedia API as the source of your conversion rates
|
|
209
270
|
}
|
210
271
|
end
|
211
272
|
|
212
|
-
Use the
|
273
|
+
Use the open exchange rates Open Source API as a source of your conversion rates
|
274
|
+
Exchange.configuration = Exchange::Configuration.new do |c|
|
275
|
+
c.api = {
|
276
|
+
:subclass => :open_exchange_rates
|
277
|
+
}
|
278
|
+
end
|
279
|
+
|
280
|
+
Use https as request protocol of your api requests:
|
213
281
|
Exchange.configuration = Exchange::Configuration.new do |c|
|
214
282
|
c.api = {
|
215
|
-
:
|
283
|
+
:protocol => :https
|
216
284
|
}
|
217
285
|
end
|
218
286
|
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
require 'bigdecimal'
|
3
|
+
|
4
|
+
class Helper
|
5
|
+
def load_or_omit a_gem
|
6
|
+
begin
|
7
|
+
require a_gem.to_s
|
8
|
+
return true
|
9
|
+
rescue LoadError => e
|
10
|
+
puts "You do not have #{a_gem} installed. gem install #{a_gem} to benchmark it\n\n"
|
11
|
+
return false
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def median array
|
16
|
+
(array.inject(0) { |sum, member| sum += member } / 3.0).round 6 if array
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
helper = Helper.new
|
21
|
+
|
22
|
+
operations = 1000
|
23
|
+
results = {}
|
24
|
+
|
25
|
+
results[:normal_float] = []
|
26
|
+
3.times { results[:normal_float] << Benchmark.realtime { operations.times { 3.555 * 4.234 } } }
|
27
|
+
|
28
|
+
results[:big_decimal] = []
|
29
|
+
one = BigDecimal.new("3.555")
|
30
|
+
two = BigDecimal.new("4.234")
|
31
|
+
3.times { results[:big_decimal] << Benchmark.realtime { operations.times { one * two } } }
|
32
|
+
|
33
|
+
if helper.load_or_omit(:money)
|
34
|
+
Money.add_rate("USD", "CAD", 1.24515)
|
35
|
+
results[:money] = []
|
36
|
+
3.times { results[:money] << Benchmark.realtime { operations.times { Money.us_dollar(50) * 0.29 } } }
|
37
|
+
end
|
38
|
+
|
39
|
+
if helper.load_or_omit(:exchange)
|
40
|
+
1.usd.to_cad #make the rate available in memory
|
41
|
+
results[:exchange] = []
|
42
|
+
3.times { results[:exchange] << Benchmark.realtime { operations.times { 50.usd * 0.29 } } }
|
43
|
+
end
|
44
|
+
|
45
|
+
puts "#{operations} operations\n\n"
|
46
|
+
puts "Normal Float Operation takes \t#{helper.median(results[:normal_float])}s\n"
|
47
|
+
puts "Big Decimal Operation takes \t#{helper.median(results[:big_decimal])}s\n"
|
48
|
+
puts "Money gem Operation takes \t#{helper.median(results[:money])}s\n" if results[:money]
|
49
|
+
puts "Exchange gem Operation takes \t#{helper.median(results[:exchange])}s\n" if results[:exchange]
|
data/changelog.rdoc
CHANGED
@@ -1,7 +1,14 @@
|
|
1
1
|
= Changes to Exchange
|
2
2
|
|
3
|
-
== 0.
|
3
|
+
== 0.9.0
|
4
|
+
- added memory cache support as the new default. This allows you to cache without any external requirement, directly in ruby.
|
5
|
+
- Added a typecasting helper for money to exchange. This allows you to typecast any given attribute into a instance of Exchange::Money
|
6
|
+
- made the base operations more floating point error save. Now even when you use a float with exchange, it will convert it to bigdecimal before doing base calculations (* / + -) in both ways. This does not mean you will not encounter any floating point errors, but it makes it highly unlikely.
|
7
|
+
- improved performance quite a bit on the conversion methods. Exchange now beats every other known gem for currency conversion in conversion speed
|
8
|
+
|
9
|
+
== 0.8.0
|
4
10
|
- jruby compatibility, horray!
|
11
|
+
- readded json as an explicit dependency since its used in cache and api
|
5
12
|
|
6
13
|
== 0.7.1
|
7
14
|
- The DSL is now included into Numeric, which makes currency operations available for all subclasses (including your own) of Numeric
|
data/lib/exchange.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'bigdecimal'
|
3
3
|
require 'open-uri'
|
4
|
-
require 'ostruct'
|
5
|
-
require 'json'
|
6
4
|
require 'exchange/base'
|
5
|
+
require 'exchange/configurable'
|
7
6
|
require 'exchange/gem_loader'
|
8
7
|
require 'exchange/helper'
|
9
8
|
require 'exchange/iso_4217'
|
10
|
-
require 'exchange/
|
9
|
+
require 'exchange/money'
|
11
10
|
require 'exchange/external_api'
|
12
11
|
require 'exchange/cache'
|
13
12
|
require 'exchange/configuration'
|
14
|
-
require 'core_extensions
|
13
|
+
require 'exchange/core_extensions'
|
14
|
+
require 'exchange/typecasting'
|
data/lib/exchange/base.rb
CHANGED
data/lib/exchange/cache.rb
CHANGED
data/lib/exchange/cache/base.rb
CHANGED
@@ -60,22 +60,36 @@ module Exchange
|
|
60
60
|
|
61
61
|
# A Cache Key generator for the API Classes and the time
|
62
62
|
# Generates a key which can handle expiration by itself
|
63
|
-
# @param [Exchange::ExternalAPI::Subclass]
|
64
|
-
# @param [
|
63
|
+
# @param [Exchange::ExternalAPI::Subclass] api The API to store the data for
|
64
|
+
# @param [Hash] opts The options for caching
|
65
65
|
# @return [String] A string that can be used as cache key
|
66
66
|
# @example
|
67
|
-
# Exchange::Cache::Base.key(Exchange::ExternalAPI::
|
67
|
+
# Exchange::Cache::Base.key(Exchange::ExternalAPI::OpenExchangeRates, Time.gm(2012,1,1)) #=> "Exchange_ExternalAPI_CurrencyBot_2012_1"
|
68
68
|
#
|
69
69
|
def key api, opts={}
|
70
|
-
time =
|
71
|
-
[
|
70
|
+
time = helper.assure_time(opts[:at], :default => :now)
|
71
|
+
['exchange',
|
72
72
|
api.to_s,
|
73
73
|
time.year.to_s,
|
74
74
|
time.yday.to_s,
|
75
|
-
|
75
|
+
config.expire == :hourly ? time.hour.to_s : nil,
|
76
76
|
*(opts[:key_for] || [])
|
77
77
|
].compact.join('_')
|
78
78
|
end
|
79
|
+
|
80
|
+
# Convenience accessor to get to the cache configuration
|
81
|
+
# @return [Exchange::Cache::Configuration] the current cache configuration
|
82
|
+
#
|
83
|
+
def config
|
84
|
+
Exchange.configuration.cache
|
85
|
+
end
|
86
|
+
|
87
|
+
# Convenience accessor for the helper
|
88
|
+
# @return [Exchange::Helper] the helper class
|
89
|
+
#
|
90
|
+
def helper
|
91
|
+
@helper ||= Exchange::Helper
|
92
|
+
end
|
79
93
|
|
80
94
|
end
|
81
95
|
|