exchange 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. data/.gitignore +1 -0
  2. data/.rspec +1 -1
  3. data/Gemfile.lock +3 -3
  4. data/README.rdoc +115 -47
  5. data/benchmark/benchmark.rb +49 -0
  6. data/changelog.rdoc +8 -1
  7. data/lib/exchange.rb +4 -4
  8. data/lib/exchange/base.rb +1 -1
  9. data/lib/exchange/cache.rb +2 -0
  10. data/lib/exchange/cache/base.rb +20 -6
  11. data/lib/exchange/cache/configuration.rb +24 -0
  12. data/lib/exchange/cache/file.rb +24 -9
  13. data/lib/exchange/cache/memcached.rb +3 -3
  14. data/lib/exchange/cache/memory.rb +89 -0
  15. data/lib/exchange/cache/rails.rb +1 -1
  16. data/lib/exchange/cache/redis.rb +4 -4
  17. data/lib/exchange/configurable.rb +53 -0
  18. data/lib/exchange/configuration.rb +32 -26
  19. data/lib/exchange/core_extensions.rb +3 -0
  20. data/lib/exchange/core_extensions/cachify.rb +25 -0
  21. data/lib/exchange/core_extensions/float/error_safe.rb +25 -0
  22. data/lib/{core_extensions → exchange/core_extensions/numeric}/conversability.rb +12 -12
  23. data/lib/exchange/external_api.rb +2 -1
  24. data/lib/exchange/external_api/base.rb +34 -9
  25. data/lib/exchange/external_api/call.rb +6 -8
  26. data/lib/exchange/external_api/configuration.rb +25 -0
  27. data/lib/exchange/external_api/ecb.rb +16 -25
  28. data/lib/exchange/external_api/json.rb +11 -1
  29. data/lib/exchange/external_api/open_exchange_rates.rb +65 -0
  30. data/lib/exchange/external_api/xavier_media.rb +7 -7
  31. data/lib/exchange/iso_4217.rb +32 -5
  32. data/lib/exchange/{currency.rb → money.rb} +112 -110
  33. data/lib/exchange/typecasting.rb +94 -0
  34. data/spec/exchange/cache/base_spec.rb +2 -2
  35. data/spec/exchange/cache/configuration_spec.rb +56 -0
  36. data/spec/exchange/cache/file_spec.rb +10 -8
  37. data/spec/exchange/cache/memcached_spec.rb +9 -18
  38. data/spec/exchange/cache/memory_spec.rb +122 -0
  39. data/spec/exchange/cache/no_cache_spec.rb +5 -15
  40. data/spec/exchange/cache/rails_spec.rb +2 -6
  41. data/spec/exchange/cache/redis_spec.rb +8 -18
  42. data/spec/exchange/configuration_spec.rb +31 -7
  43. data/spec/exchange/core_extensions/array/cachify_spec.rb +12 -0
  44. data/spec/exchange/core_extensions/float/error_safe_spec.rb +49 -0
  45. data/spec/exchange/core_extensions/hash/cachify_spec.rb +12 -0
  46. data/spec/exchange/core_extensions/numeric/cachify_spec.rb +26 -0
  47. data/spec/{core_extensions → exchange/core_extensions/numeric}/conversability_spec.rb +22 -22
  48. data/spec/exchange/core_extensions/string/cachify_spec.rb +59 -0
  49. data/spec/exchange/core_extensions/symbol/cachify_spec.rb +12 -0
  50. data/spec/exchange/external_api/base_spec.rb +10 -7
  51. data/spec/exchange/external_api/call_spec.rb +3 -0
  52. data/spec/exchange/external_api/configuration_spec.rb +52 -0
  53. data/spec/exchange/external_api/ecb_spec.rb +8 -5
  54. data/spec/exchange/external_api/open_exchange_rates_spec.rb +70 -0
  55. data/spec/exchange/external_api/xavier_media_spec.rb +8 -5
  56. data/spec/exchange/iso_4217_spec.rb +208 -20
  57. data/spec/exchange/{currency_spec.rb → money_spec.rb} +102 -82
  58. data/spec/exchange/typecasting_spec.rb +86 -0
  59. metadata +117 -71
  60. data/exchange-0.7.5.gem +0 -0
  61. data/exchange-0.7.6.gem +0 -0
  62. data/lib/exchange/external_api/currency_bot.rb +0 -61
  63. data/spec/exchange/external_api/currency_bot_spec.rb +0 -63
@@ -1,11 +1,11 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe "Exchange::Currency" do
4
- subject { Exchange::Currency.new(40, :usd) }
3
+ describe "Exchange::Money" do
4
+ subject { Exchange::Money.new(40, :usd) }
5
5
  before(:all) do
6
6
  Exchange.configuration = Exchange::Configuration.new do |c|
7
7
  c.api = {
8
- :subclass => :currency_bot
8
+ :subclass => :open_exchange_rates
9
9
  }
10
10
  c.cache = {
11
11
  :subclass => :no_cache
@@ -14,22 +14,30 @@ describe "Exchange::Currency" do
14
14
  end
15
15
  end
16
16
  after(:all) do
17
- Exchange.configuration = Exchange::Configuration.new do |c|
18
- c.api = {
19
- :subclass => :memcached
20
- }
21
- end
17
+ Exchange.configuration.reset
22
18
  end
23
19
  it "should initialize with a number and a currency" do
24
20
  subject.value.should == 40
25
21
  subject.currency.should == :usd
26
22
  end
23
+ describe "initializing with a block" do
24
+ it "should be possible" do
25
+ currency = Exchange::Money.new(40) do |c|
26
+ c.currency = :usd
27
+ c.time = Time.gm(2012,9,9)
28
+ end
29
+
30
+ currency.value.should == 40
31
+ currency.currency.should == :usd
32
+ currency.time.should == Time.gm(2012,9,9)
33
+ end
34
+ end
27
35
  describe "convert_to" do
28
36
  it "should be able to convert itself to other currencies" do
29
37
  mock_api("http://openexchangerates.org/api/latest.json?app_id=", fixture('api_responses/example_json_api.json'), 3)
30
38
  subject.convert_to(:chf).value.round(2).should == 36.5
31
39
  subject.convert_to(:chf).currency.should == :chf
32
- subject.convert_to(:chf).should be_kind_of Exchange::Currency
40
+ subject.convert_to(:chf).should be_kind_of Exchange::Money
33
41
  end
34
42
  end
35
43
  describe "operations" do
@@ -46,20 +54,20 @@ describe "Exchange::Currency" do
46
54
  end
47
55
  it "should be able to add another currency value" do
48
56
  mock_api("http://openexchangerates.org/api/latest.json?app_id=", fixture('api_responses/example_json_api.json'), 2)
49
- (subject + Exchange::Currency.new(30, :chf)).value.round(2).should == 72.87
50
- (subject + Exchange::Currency.new(30, :sek)).currency.should == :usd
57
+ (subject + Exchange::Money.new(30, :chf)).value.round(2).should == 72.87
58
+ (subject + Exchange::Money.new(30, :sek)).currency.should == :usd
51
59
  subject.value.round(2).should == 40
52
60
  subject.currency.should == :usd
53
61
  end
54
62
  it "should raise when currencies get mixed and the configuration does not allow it" do
55
63
  Exchange.configuration.allow_mixed_operations = false
56
- lambda { subject + Exchange::Currency.new(30, :chf) }.should raise_error(Exchange::CurrencyMixError)
64
+ lambda { subject + Exchange::Money.new(30, :chf) }.should raise_error(Exchange::CurrencyMixError)
57
65
  Exchange.configuration.allow_mixed_operations = true
58
66
  end
59
67
  it "should not raise when currencies get mixed and the configuration does not allow if the other currency is the same" do
60
68
  Exchange.configuration.allow_mixed_operations = false
61
69
  mock_api("http://openexchangerates.org/api/latest.json?app_id=", fixture('api_responses/example_json_api.json'), 2)
62
- lambda { subject + Exchange::Currency.new(30, :usd) }.should_not raise_error
70
+ lambda { subject + Exchange::Money.new(30, :usd) }.should_not raise_error
63
71
  Exchange.configuration.allow_mixed_operations = true
64
72
  end
65
73
  context "modifying the base value" do
@@ -79,7 +87,7 @@ describe "Exchange::Currency" do
79
87
  end
80
88
  it "should be able to add another currency value" do
81
89
  mock_api("http://openexchangerates.org/api/latest.json?app_id=", fixture('api_responses/example_json_api.json'), 2)
82
- added = (@instantiated += Exchange::Currency.new(30, :chf))
90
+ added = (@instantiated += Exchange::Money.new(30, :chf))
83
91
  added.value.round(2).should == 72.87
84
92
  added.currency.should == :usd
85
93
  @instantiated.value.round(2).should == 72.87
@@ -87,13 +95,13 @@ describe "Exchange::Currency" do
87
95
  end
88
96
  it "should raise when currencies get mixed and the configuration does not allow it" do
89
97
  Exchange.configuration.allow_mixed_operations = false
90
- lambda { @instantiated += Exchange::Currency.new(30, :chf) }.should raise_error(Exchange::CurrencyMixError)
98
+ lambda { @instantiated += Exchange::Money.new(30, :chf) }.should raise_error(Exchange::CurrencyMixError)
91
99
  Exchange.configuration.allow_mixed_operations = true
92
100
  end
93
101
  it "should not raise when currencies get mixed and the configuration does not allow if the other currency is the same" do
94
102
  Exchange.configuration.allow_mixed_operations = false
95
103
  mock_api("http://openexchangerates.org/api/latest.json?app_id=", fixture('api_responses/example_json_api.json'), 2)
96
- lambda { @instantiated += Exchange::Currency.new(30, :usd) }.should_not raise_error
104
+ lambda { @instantiated += Exchange::Money.new(30, :usd) }.should_not raise_error
97
105
  Exchange.configuration.allow_mixed_operations = true
98
106
  end
99
107
  end
@@ -112,18 +120,18 @@ describe "Exchange::Currency" do
112
120
  it "should be able to subtract another currency value" do
113
121
  mock_api("http://openexchangerates.org/api/latest.json?app_id=", fixture('api_responses/example_json_api.json'), 2)
114
122
  Exchange.configuration.allow_mixed_operations = true
115
- (subject - Exchange::Currency.new(10, :chf)).value.round(2).should == 29.04
116
- (subject - Exchange::Currency.new(23.3, :eur)).currency.should == :usd
123
+ (subject - Exchange::Money.new(10, :chf)).value.round(2).should == 29.04
124
+ (subject - Exchange::Money.new(23.3, :eur)).currency.should == :usd
117
125
  end
118
126
  it "should raise when currencies get mixed and the configuration does not allow it" do
119
127
  Exchange.configuration.allow_mixed_operations = false
120
- lambda { subject - Exchange::Currency.new(30, :chf) }.should raise_error(Exchange::CurrencyMixError)
128
+ lambda { subject - Exchange::Money.new(30, :chf) }.should raise_error(Exchange::CurrencyMixError)
121
129
  Exchange.configuration.allow_mixed_operations = true
122
130
  end
123
131
  it "should not raise when currencies get mixed and the configuration does not allow if the other currency is the same" do
124
132
  Exchange.configuration.allow_mixed_operations = false
125
133
  mock_api("http://openexchangerates.org/api/latest.json?app_id=", fixture('api_responses/example_json_api.json'), 2)
126
- lambda { subject - Exchange::Currency.new(30, :usd) }.should_not raise_error
134
+ lambda { subject - Exchange::Money.new(30, :usd) }.should_not raise_error
127
135
  Exchange.configuration.allow_mixed_operations = true
128
136
  end
129
137
  context "modifying the base value" do
@@ -144,7 +152,7 @@ describe "Exchange::Currency" do
144
152
  it "should be able to subtract another currency value" do
145
153
  mock_api("http://openexchangerates.org/api/latest.json?app_id=", fixture('api_responses/example_json_api.json'), 2)
146
154
  Exchange.configuration.allow_mixed_operations = true
147
- added = (@instantiated -= Exchange::Currency.new(10, :chf))
155
+ added = (@instantiated -= Exchange::Money.new(10, :chf))
148
156
  added.value.round(2).should == 29.04
149
157
  added.currency.should == :usd
150
158
  @instantiated.value.round(2).should == 29.04
@@ -152,13 +160,13 @@ describe "Exchange::Currency" do
152
160
  end
153
161
  it "should raise when currencies get mixed and the configuration does not allow it" do
154
162
  Exchange.configuration.allow_mixed_operations = false
155
- lambda { @instantiated -= Exchange::Currency.new(30, :chf) }.should raise_error(Exchange::CurrencyMixError)
163
+ lambda { @instantiated -= Exchange::Money.new(30, :chf) }.should raise_error(Exchange::CurrencyMixError)
156
164
  Exchange.configuration.allow_mixed_operations = true
157
165
  end
158
166
  it "should not raise when currencies get mixed and the configuration does not allow if the other currency is the same" do
159
167
  Exchange.configuration.allow_mixed_operations = false
160
168
  mock_api("http://openexchangerates.org/api/latest.json?app_id=", fixture('api_responses/example_json_api.json'), 2)
161
- lambda { @instantiated -= Exchange::Currency.new(30, :usd) }.should_not raise_error
169
+ lambda { @instantiated -= Exchange::Money.new(30, :usd) }.should_not raise_error
162
170
  Exchange.configuration.allow_mixed_operations = true
163
171
  end
164
172
  end
@@ -167,28 +175,33 @@ describe "Exchange::Currency" do
167
175
  it "should be able to multiply by an integer" do
168
176
  (subject * 40).value.should == 1600
169
177
  end
170
- it "should be able to multiply a float" do
171
- (subject * 40.5).value.should == 1620
178
+ context "with a float" do
179
+ subject { Exchange::Money.new(50, :usd) }
180
+ it "should be able to multiply a float" do
181
+ (subject * 40.5).value.should == 2025
182
+ end
183
+ it "should not fall for rounding errors" do
184
+ (subject * 0.29).round(0).value.should == 15
185
+ end
172
186
  end
173
- it "should not modify the base value" do
174
- (subject * 40).value.should == 1600
175
- subject.value.should == 40.0
187
+ it "should not fall for float rounding errors" do
188
+ (subject * 40.5)
176
189
  end
177
190
  it "should be able to multiply by another currency value" do
178
191
  mock_api("http://openexchangerates.org/api/latest.json?app_id=", fixture('api_responses/example_json_api.json'), 2)
179
192
  Exchange.configuration.allow_mixed_operations = true
180
- (subject * Exchange::Currency.new(10, :chf)).value.round(1).should == 438.3
181
- (subject * Exchange::Currency.new(23.3, :eur)).currency.should == :usd
193
+ (subject * Exchange::Money.new(10, :chf)).value.round(1).should == 438.3
194
+ (subject * Exchange::Money.new(23.3, :eur)).currency.should == :usd
182
195
  end
183
196
  it "should raise when currencies get mixed and the configuration does not allow it" do
184
197
  Exchange.configuration.allow_mixed_operations = false
185
- lambda { subject * Exchange::Currency.new(30, :chf) }.should raise_error(Exchange::CurrencyMixError)
198
+ lambda { subject * Exchange::Money.new(30, :chf) }.should raise_error(Exchange::CurrencyMixError)
186
199
  Exchange.configuration.allow_mixed_operations = true
187
200
  end
188
201
  it "should not raise when currencies get mixed and the configuration does not allow if the other currency is the same" do
189
202
  Exchange.configuration.allow_mixed_operations = false
190
203
  mock_api("http://openexchangerates.org/api/latest.json?app_id=", fixture('api_responses/example_json_api.json'), 2)
191
- lambda { subject * Exchange::Currency.new(30, :usd) }.should_not raise_error
204
+ lambda { subject * Exchange::Money.new(30, :usd) }.should_not raise_error
192
205
  Exchange.configuration.allow_mixed_operations = true
193
206
  end
194
207
  context "modifying the base value" do
@@ -209,7 +222,7 @@ describe "Exchange::Currency" do
209
222
  it "should be able to multiply by another currency value" do
210
223
  mock_api("http://openexchangerates.org/api/latest.json?app_id=", fixture('api_responses/example_json_api.json'), 2)
211
224
  Exchange.configuration.allow_mixed_operations = true
212
- added = (@instantiated *= Exchange::Currency.new(9, :chf))
225
+ added = (@instantiated *= Exchange::Money.new(9, :chf))
213
226
  added.value.round(1).should == 394.50
214
227
  added.currency.should == :usd
215
228
  @instantiated.value.round(1).should == 394.50
@@ -217,13 +230,13 @@ describe "Exchange::Currency" do
217
230
  end
218
231
  it "should raise when currencies get mixed and the configuration does not allow it" do
219
232
  Exchange.configuration.allow_mixed_operations = false
220
- lambda { @instantiated *= Exchange::Currency.new(30, :chf) }.should raise_error(Exchange::CurrencyMixError)
233
+ lambda { @instantiated *= Exchange::Money.new(30, :chf) }.should raise_error(Exchange::CurrencyMixError)
221
234
  Exchange.configuration.allow_mixed_operations = true
222
235
  end
223
236
  it "should not raise when currencies get mixed and the configuration does not allow if the other currency is the same" do
224
237
  Exchange.configuration.allow_mixed_operations = false
225
238
  mock_api("http://openexchangerates.org/api/latest.json?app_id=", fixture('api_responses/example_json_api.json'), 2)
226
- lambda { @instantiated *= Exchange::Currency.new(30, :usd) }.should_not raise_error
239
+ lambda { @instantiated *= Exchange::Money.new(30, :usd) }.should_not raise_error
227
240
  Exchange.configuration.allow_mixed_operations = true
228
241
  end
229
242
  end
@@ -232,9 +245,16 @@ describe "Exchange::Currency" do
232
245
  it "should be able to divide by an integer" do
233
246
  (subject / 40).value.should == 1
234
247
  end
235
- it "should be able to divide by a float" do
236
- BigDecimal.new((subject / 40.5).value.to_s).round(4).should == 0.9877
248
+ context "with a float" do
249
+ subject { Exchange::Money.new(1829.82, :omr) }
250
+ it "should be able to divide by a float" do
251
+ (subject / 40.5).value.round(4).should == 45.1807
252
+ end
253
+ it "should not fall for floating point errors" do
254
+ (subject / 12.0).round(2).value.should == 152.49
255
+ end
237
256
  end
257
+
238
258
  it "should not modify the base value" do
239
259
  (subject / 40).value.should == 1
240
260
  subject.value.should == 40.0
@@ -247,18 +267,18 @@ describe "Exchange::Currency" do
247
267
  it "should be able to divide by another currency value" do
248
268
  mock_api("http://openexchangerates.org/api/latest.json?app_id=", fixture('api_responses/example_json_api.json'), 2)
249
269
  Exchange.configuration.allow_mixed_operations = true
250
- (subject / Exchange::Currency.new(10, :chf)).value.round(2).should == BigDecimal.new("3.65")
251
- (subject / Exchange::Currency.new(23.3, :eur)).currency.should == :usd
270
+ (subject / Exchange::Money.new(10, :chf)).value.round(2).should == BigDecimal.new("3.65")
271
+ (subject / Exchange::Money.new(23.3, :eur)).currency.should == :usd
252
272
  end
253
273
  it "should raise when currencies get mixed and the configuration does not allow it" do
254
274
  Exchange.configuration.allow_mixed_operations = false
255
- lambda { subject / Exchange::Currency.new(30, :chf) }.should raise_error(Exchange::CurrencyMixError)
275
+ lambda { subject / Exchange::Money.new(30, :chf) }.should raise_error(Exchange::CurrencyMixError)
256
276
  Exchange.configuration.allow_mixed_operations = true
257
277
  end
258
278
  it "should not raise when currencies get mixed and the configuration does not allow if the other currency is the same" do
259
279
  Exchange.configuration.allow_mixed_operations = false
260
280
  mock_api("http://openexchangerates.org/api/latest.json?app_id=", fixture('api_responses/example_json_api.json'), 2)
261
- lambda { subject / Exchange::Currency.new(30, :usd) }.should_not raise_error
281
+ lambda { subject / Exchange::Money.new(30, :usd) }.should_not raise_error
262
282
  Exchange.configuration.allow_mixed_operations = true
263
283
  end
264
284
  context "modifying the base value" do
@@ -279,7 +299,7 @@ describe "Exchange::Currency" do
279
299
  it "should be able to divide by another currency value" do
280
300
  mock_api("http://openexchangerates.org/api/latest.json?app_id=", fixture('api_responses/example_json_api.json'), 2)
281
301
  Exchange.configuration.allow_mixed_operations = true
282
- added = (@instantiated /= Exchange::Currency.new(10, :chf))
302
+ added = (@instantiated /= Exchange::Money.new(10, :chf))
283
303
  added.value.round(2).should == 3.65
284
304
  added.currency.should == :usd
285
305
  @instantiated.value.round(2).should == 3.65
@@ -287,25 +307,25 @@ describe "Exchange::Currency" do
287
307
  end
288
308
  it "should raise when currencies get mixed and the configuration does not allow it" do
289
309
  Exchange.configuration.allow_mixed_operations = false
290
- lambda { @instantiated /= Exchange::Currency.new(30, :chf) }.should raise_error(Exchange::CurrencyMixError)
310
+ lambda { @instantiated /= Exchange::Money.new(30, :chf) }.should raise_error(Exchange::CurrencyMixError)
291
311
  Exchange.configuration.allow_mixed_operations = true
292
312
  end
293
313
  it "should not raise when currencies get mixed and the configuration does not allow if the other currency is the same" do
294
314
  Exchange.configuration.allow_mixed_operations = false
295
315
  mock_api("http://openexchangerates.org/api/latest.json?app_id=", fixture('api_responses/example_json_api.json'), 2)
296
- lambda { @instantiated /= Exchange::Currency.new(30, :usd) }.should_not raise_error
316
+ lambda { @instantiated /= Exchange::Money.new(30, :usd) }.should_not raise_error
297
317
  Exchange.configuration.allow_mixed_operations = true
298
318
  end
299
319
  end
300
320
  end
301
321
  describe "comparison" do
302
- subject { Exchange::Currency.new(40.123, :usd) }
303
- let(:comp1) { Exchange::Currency.new(40.123, :usd) }
304
- let(:comp2) { Exchange::Currency.new(40, :usd) }
305
- let(:comp3) { Exchange::Currency.new(50, :eur) }
306
- let(:comp4) { Exchange::Currency.new(45, :eur) }
307
- let(:comp5) { Exchange::Currency.new(50, :eur).to_usd }
308
- let(:comp6) { Exchange::Currency.new(66.1, :usd, :at => Time.gm(2011,1,1)) }
322
+ subject { Exchange::Money.new(40.123, :usd) }
323
+ let(:comp1) { Exchange::Money.new(40.123, :usd) }
324
+ let(:comp2) { Exchange::Money.new(40, :usd) }
325
+ let(:comp3) { Exchange::Money.new(50, :eur) }
326
+ let(:comp4) { Exchange::Money.new(45, :eur) }
327
+ let(:comp5) { Exchange::Money.new(50, :eur).to_usd }
328
+ let(:comp6) { Exchange::Money.new(66.1, :usd, :at => Time.gm(2011,1,1)) }
309
329
  before(:each) do
310
330
  mock_api("http://openexchangerates.org/api/latest.json?app_id=", fixture('api_responses/example_json_api.json'), 2)
311
331
  end
@@ -331,11 +351,11 @@ describe "Exchange::Currency" do
331
351
  end
332
352
  end
333
353
  describe "sorting" do
334
- subject { Exchange::Currency.new(40.123, :usd) }
335
- let(:comp1) { Exchange::Currency.new(40.123, :usd) }
336
- let(:comp2) { Exchange::Currency.new(40, :usd) }
337
- let(:comp3) { Exchange::Currency.new(50, :eur) }
338
- let(:comp4) { Exchange::Currency.new(45, :eur) }
354
+ subject { Exchange::Money.new(40.123, :usd) }
355
+ let(:comp1) { Exchange::Money.new(40.123, :usd) }
356
+ let(:comp2) { Exchange::Money.new(40, :usd) }
357
+ let(:comp3) { Exchange::Money.new(50, :eur) }
358
+ let(:comp4) { Exchange::Money.new(45, :eur) }
339
359
  before(:each) do
340
360
  mock_api("http://openexchangerates.org/api/latest.json?app_id=", fixture('api_responses/example_json_api.json'), 6)
341
361
  end
@@ -344,12 +364,12 @@ describe "Exchange::Currency" do
344
364
  end
345
365
  end
346
366
  describe "round" do
347
- subject { Exchange::Currency.new(40.123, :usd) }
367
+ subject { Exchange::Money.new(40.123, :usd) }
348
368
  context "without arguments" do
349
369
  it "should apply it to its number in the iso certified format" do
350
370
  subject.round.value.should == 40.12
351
371
  subject.round.currency.should == :usd
352
- subject.round.should be_kind_of Exchange::Currency
372
+ subject.round.should be_kind_of Exchange::Money
353
373
  end
354
374
  it "should not modify the base value" do
355
375
  subject.round.value.should == 40.12
@@ -360,22 +380,22 @@ describe "Exchange::Currency" do
360
380
  it "should apply it to its number" do
361
381
  subject.round(0).value.should == 40
362
382
  subject.round(0).currency.should == :usd
363
- subject.round(0).should be_kind_of Exchange::Currency
383
+ subject.round(0).should be_kind_of Exchange::Money
364
384
  end
365
385
  it "should allow to round to whatever number of decimals" do
366
386
  subject.round(2).value.should == 40.12
367
387
  subject.round(2).currency.should == :usd
368
- subject.round(2).should be_kind_of Exchange::Currency
388
+ subject.round(2).should be_kind_of Exchange::Money
369
389
  end
370
390
  end
371
391
  end
372
392
  describe "ceil" do
373
- subject { Exchange::Currency.new(40.1236, :omr) }
393
+ subject { Exchange::Money.new(40.1236, :omr) }
374
394
  context "without arguments" do
375
395
  it "should apply it to its number in the iso certified format" do
376
396
  subject.ceil.value.should == 40.124
377
397
  subject.ceil.currency.should == :omr
378
- subject.ceil.should be_kind_of Exchange::Currency
398
+ subject.ceil.should be_kind_of Exchange::Money
379
399
  end
380
400
  it "should not modify the base value" do
381
401
  subject.ceil.value.should == 40.124
@@ -386,22 +406,22 @@ describe "Exchange::Currency" do
386
406
  it "should apply it to its number" do
387
407
  subject.ceil(0).value.should == 41
388
408
  subject.ceil(0).currency.should == :omr
389
- subject.ceil(0).should be_kind_of Exchange::Currency
409
+ subject.ceil(0).should be_kind_of Exchange::Money
390
410
  end
391
411
  it "should allow to round to whatever number of decimals" do
392
412
  subject.ceil(2).value.should == 40.13
393
413
  subject.ceil(2).currency.should == :omr
394
- subject.ceil(2).should be_kind_of Exchange::Currency
414
+ subject.ceil(2).should be_kind_of Exchange::Money
395
415
  end
396
416
  end
397
417
  end
398
418
  describe "floor" do
399
- subject { Exchange::Currency.new(40.723, :jpy) }
419
+ subject { Exchange::Money.new(40.723, :jpy) }
400
420
  context "without arguments" do
401
421
  it "should apply it to its number in the iso certified format" do
402
422
  subject.floor.value.should == 40
403
423
  subject.floor.currency.should == :jpy
404
- subject.floor.should be_kind_of Exchange::Currency
424
+ subject.floor.should be_kind_of Exchange::Money
405
425
  end
406
426
  it "should not modify the base value" do
407
427
  subject.floor.value.should == 40
@@ -412,38 +432,38 @@ describe "Exchange::Currency" do
412
432
  it "should apply it to its number" do
413
433
  subject.floor(1).value.should == 40.7
414
434
  subject.floor(1).currency.should == :jpy
415
- subject.floor(1).should be_kind_of Exchange::Currency
435
+ subject.floor(1).should be_kind_of Exchange::Money
416
436
  end
417
437
  it "should allow to round to whatever number of decimals" do
418
438
  subject.floor(2).value.should == 40.72
419
439
  subject.floor(2).currency.should == :jpy
420
- subject.floor(2).should be_kind_of Exchange::Currency
440
+ subject.floor(2).should be_kind_of Exchange::Money
421
441
  end
422
442
  end
423
443
  end
424
444
  end
425
445
  describe "to_s" do
426
446
  it "should render the currency according to ISO 4217 Definitions" do
427
- Exchange::Currency.new(23.232524, 'TND').to_s.should == "TND 23.233"
428
- Exchange::Currency.new(23.23252423, 'SAR').to_s.should == "SAR 23.23"
429
- Exchange::Currency.new(23.23252423, 'CLP').to_s.should == "CLP 23"
430
- Exchange::Currency.new(23.2, 'TND').to_s.should == "TND 23.200"
431
- Exchange::Currency.new(23.4, 'SAR').to_s.should == "SAR 23.40"
432
- Exchange::Currency.new(23.0, 'CLP').to_s.should == "CLP 23"
447
+ Exchange::Money.new(23.232524, :tnd).to_s.should == "TND 23.233"
448
+ Exchange::Money.new(23.23252423, :sar).to_s.should == "SAR 23.23"
449
+ Exchange::Money.new(23.23252423, :clp).to_s.should == "CLP 23"
450
+ Exchange::Money.new(23.2, :tnd).to_s.should == "TND 23.200"
451
+ Exchange::Money.new(23.4, :sar).to_s.should == "SAR 23.40"
452
+ Exchange::Money.new(23.0, :clp).to_s.should == "CLP 23"
433
453
  end
434
454
  it "should render only the currency amount if the argument amount is passed" do
435
- Exchange::Currency.new(23.232524, 'TND').to_s(:amount).should == "23.233"
436
- Exchange::Currency.new(23.23252423, 'SAR').to_s(:amount).should == "23.23"
437
- Exchange::Currency.new(23.23252423, 'CLP').to_s(:amount).should == "23"
438
- Exchange::Currency.new(23.2, 'TND').to_s(:amount).should == "23.200"
439
- Exchange::Currency.new(23.4, 'SAR').to_s(:amount).should == "23.40"
440
- Exchange::Currency.new(23.0, 'CLP').to_s(:amount).should == "23"
455
+ Exchange::Money.new(23.232524, :tnd).to_s(:amount).should == "23.233"
456
+ Exchange::Money.new(23.23252423, :sar).to_s(:amount).should == "23.23"
457
+ Exchange::Money.new(23.23252423, :clp).to_s(:amount).should == "23"
458
+ Exchange::Money.new(23.2, :tnd).to_s(:amount).should == "23.200"
459
+ Exchange::Money.new(23.4, :sar).to_s(:amount).should == "23.40"
460
+ Exchange::Money.new(23.0, :clp).to_s(:amount).should == "23"
441
461
  end
442
462
  end
443
463
  describe "methods via method missing" do
444
464
  it "should be able to convert via to_currency to other currencies" do
445
465
  mock_api("http://openexchangerates.org/api/latest.json?app_id=", fixture('api_responses/example_json_api.json'), 6)
446
- {'chf' => 36.5, 'usd' => 40.0, 'dkk' => 225.12, 'sek' => 269.85, 'nok' => 232.06, 'rub' => 1205.24}.each do |currency, value|
466
+ {:chf => 36.5, :usd => 40.0, :dkk => 225.12, :sek => 269.85, :nok => 232.06, :rub => 1205.24}.each do |currency, value|
447
467
  c = subject.send(:"to_#{currency}")
448
468
  c.value.round(2).should == value
449
469
  c.currency.should == currency
@@ -451,7 +471,7 @@ describe "Exchange::Currency" do
451
471
  end
452
472
  it "should be able to convert via to_currency to other currencies and use historic data" do
453
473
  mock_api("http://openexchangerates.org/api/historical/2011-10-09.json?app_id=", fixture('api_responses/example_json_api.json'), 6)
454
- {'chf' => 36.5, 'usd' => 40.0, 'dkk' => 225.12, 'sek' => 269.85, 'nok' => 232.06, 'rub' => 1205.24}.each do |currency, value|
474
+ {:chf => 36.5, :usd => 40.0, :dkk => 225.12, :sek => 269.85, :nok => 232.06, :rub => 1205.24}.each do |currency, value|
455
475
  c = subject.send(:"to_#{currency}", :at => Time.gm(2011,10,9))
456
476
  c.value.round(2).should == value
457
477
  c.currency.should == currency
@@ -0,0 +1,86 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Exchange::Typecasting" do
4
+
5
+ class Manager
6
+
7
+ attr_accessor :currency
8
+
9
+ def initialize *args
10
+ self.currency = :eur
11
+
12
+ super
13
+ end
14
+
15
+ end
16
+
17
+ class MyClass
18
+ extend Exchange::Typecasting
19
+
20
+ attr_accessor :price, :manager
21
+
22
+ def initialize *args
23
+ self.manager = Manager.new
24
+
25
+ super
26
+ end
27
+
28
+ def created_at
29
+ Time.gm(2012,8,8)
30
+ end
31
+
32
+ money :price, :at => :created_at, :currency => lambda { |s| s.manager.currency }
33
+
34
+ end
35
+
36
+ describe "get" do
37
+ subject { MyClass.new }
38
+ before(:each) do
39
+ subject.price = 0.77
40
+ end
41
+ it "should instantiate the attribute as a currency" do
42
+ subject.price.should be_instance_of(Exchange::Money)
43
+ end
44
+ it "should instantiate the currency with the right currency" do
45
+ subject.price.currency.should == :eur
46
+ end
47
+ it "should instantiate with the right value" do
48
+ subject.price.value.should == 0.77
49
+ end
50
+ it "should instantiate the currency with the right time" do
51
+ subject.price.time.should == Time.gm(2012,8,8)
52
+ end
53
+ context "when changing the currency value" do
54
+ before(:each) do
55
+ subject.manager.currency = :usd
56
+ end
57
+ it "should instantiate with the new currency" do
58
+ subject.price.currency.should == :usd
59
+ end
60
+ it "should leave the value unchanged" do
61
+ subject.price.value.should == 0.77
62
+ end
63
+ end
64
+ end
65
+
66
+ describe "set" do
67
+ subject { MyClass.new }
68
+ before(:each) do
69
+ subject.price = 0.77
70
+ end
71
+ it "should set the value if the given value is numeric" do
72
+ subject.price = 0.83
73
+ subject.price.should == 0.83.eur
74
+ end
75
+ it "should not convert the value if the given value is in the same currency" do
76
+ subject.price = 0.83.eur
77
+ subject.price.should == 0.83.eur
78
+ end
79
+ it "should convert the value if the given value is in another currency" do
80
+ mock_api("http://api.finance.xaviermedia.com/api/#{Time.now.strftime("%Y/%m/%d")}.xml", fixture('api_responses/example_xml_api.xml'))
81
+ subject.price = 0.83.usd
82
+ subject.price.should == 0.62.eur
83
+ end
84
+ end
85
+
86
+ end