acvwilson-currency 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. data/COPYING.txt +339 -0
  2. data/ChangeLog +8 -0
  3. data/LICENSE.txt +65 -0
  4. data/Manifest.txt +58 -0
  5. data/README.txt +51 -0
  6. data/Releases.txt +155 -0
  7. data/TODO.txt +9 -0
  8. data/currency.gemspec +18 -0
  9. data/examples/ex1.rb +13 -0
  10. data/examples/xe1.rb +20 -0
  11. data/lib/currency.rb +143 -0
  12. data/lib/currency/active_record.rb +265 -0
  13. data/lib/currency/config.rb +91 -0
  14. data/lib/currency/core_extensions.rb +83 -0
  15. data/lib/currency/currency.rb +175 -0
  16. data/lib/currency/currency/factory.rb +121 -0
  17. data/lib/currency/currency_version.rb +6 -0
  18. data/lib/currency/exception.rb +119 -0
  19. data/lib/currency/exchange.rb +48 -0
  20. data/lib/currency/exchange/rate.rb +214 -0
  21. data/lib/currency/exchange/rate/deriver.rb +157 -0
  22. data/lib/currency/exchange/rate/source.rb +89 -0
  23. data/lib/currency/exchange/rate/source/base.rb +166 -0
  24. data/lib/currency/exchange/rate/source/failover.rb +63 -0
  25. data/lib/currency/exchange/rate/source/federal_reserve.rb +160 -0
  26. data/lib/currency/exchange/rate/source/historical.rb +79 -0
  27. data/lib/currency/exchange/rate/source/historical/rate.rb +184 -0
  28. data/lib/currency/exchange/rate/source/historical/rate_loader.rb +186 -0
  29. data/lib/currency/exchange/rate/source/historical/writer.rb +220 -0
  30. data/lib/currency/exchange/rate/source/new_york_fed.rb +127 -0
  31. data/lib/currency/exchange/rate/source/provider.rb +120 -0
  32. data/lib/currency/exchange/rate/source/test.rb +50 -0
  33. data/lib/currency/exchange/rate/source/the_financials.rb +191 -0
  34. data/lib/currency/exchange/rate/source/timed_cache.rb +198 -0
  35. data/lib/currency/exchange/rate/source/xe.rb +165 -0
  36. data/lib/currency/exchange/time_quantitizer.rb +111 -0
  37. data/lib/currency/formatter.rb +310 -0
  38. data/lib/currency/macro.rb +321 -0
  39. data/lib/currency/money.rb +298 -0
  40. data/lib/currency/money_helper.rb +13 -0
  41. data/lib/currency/parser.rb +193 -0
  42. data/spec/ar_column_spec.rb +76 -0
  43. data/spec/ar_core_spec.rb +68 -0
  44. data/spec/ar_simple_spec.rb +23 -0
  45. data/spec/config_spec.rb +29 -0
  46. data/spec/federal_reserve_spec.rb +75 -0
  47. data/spec/formatter_spec.rb +72 -0
  48. data/spec/historical_writer_spec.rb +187 -0
  49. data/spec/macro_spec.rb +109 -0
  50. data/spec/money_spec.rb +355 -0
  51. data/spec/new_york_fed_spec.rb +73 -0
  52. data/spec/parser_spec.rb +105 -0
  53. data/spec/spec_helper.rb +25 -0
  54. data/spec/time_quantitizer_spec.rb +115 -0
  55. data/spec/timed_cache_spec.rb +95 -0
  56. data/spec/xe_spec.rb +50 -0
  57. metadata +117 -0
@@ -0,0 +1,109 @@
1
+ # Copyright (C) 2006-2007 Kurt Stephens <ruby-currency(at)umleta.com>
2
+ # See LICENSE.txt for details.
3
+
4
+ require 'test/test_base'
5
+ require 'currency'
6
+ require 'currency/macro'
7
+
8
+ module Currency
9
+
10
+ class MacroTest < TestBase
11
+ class Record
12
+ include ::Currency::Macro
13
+
14
+ attr_accessor :date
15
+ attr_accessor :gross
16
+ attr_accessor :tax
17
+ attr_accessor :net
18
+ attr_accessor :currency
19
+
20
+ attr_money :gross_money, :value => :gross, :time => :date, :currency => :currency
21
+ attr_money :tax_money, :value => :tax, :time => :date, :currency => :currency
22
+ attr_money :net_money, :value => :net, :time => :date, :currency => :currency
23
+
24
+ def initialize
25
+ self.date = Time.now
26
+ self.currency = :USD
27
+ end
28
+
29
+ def compute_net
30
+ self.net = self.gross - self.tax
31
+ end
32
+
33
+ def compute_net_money
34
+ self.net_money = self.gross_money - self.tax_money
35
+ end
36
+
37
+ end
38
+
39
+ before do
40
+ super
41
+ end
42
+
43
+ ############################################
44
+ # Tests
45
+ #
46
+
47
+ it "read money" do
48
+ assert_kind_of Record, r = Record.new
49
+ r.gross = 10.00.should.not == nil
50
+ r.gross.should == r.gross_money.to_f
51
+ r.currency.should == r.gross_money.currency.code
52
+ r.date.should == r.gross_money.time
53
+
54
+ r
55
+ end
56
+
57
+
58
+ it "write money rep" do
59
+ assert_kind_of Record, r = Record.new
60
+ r.gross_money = 10.00.should.not == nil
61
+ r.gross.should == r.gross_money.to_f
62
+ r.currency.should == r.gross_money.currency.code
63
+ r.date.should == r.gross_money.time
64
+
65
+ r
66
+ end
67
+
68
+
69
+ it "money cache" do
70
+ r = test_read_money
71
+
72
+ r_gross = r.gross.should.not == nil
73
+ r_gross.object_id.should == r.gross.object_id
74
+
75
+ # Cache flush
76
+ r.gross = 12.00.should.not == nil
77
+ r.gross.should == r.gross_money.to_f
78
+ r_gross.object_id != r.gross.object_id.should.not == nil
79
+ end
80
+
81
+
82
+ it "currency" do
83
+ r = test_read_money
84
+
85
+ r.gross_money.currency.should.not == nil
86
+ r.currency.should == r.gross_money.currency.code
87
+
88
+ end
89
+
90
+
91
+ it "compute" do
92
+ assert_kind_of Record, r = Record.new
93
+ r.gross = 10.00.should.not == nil
94
+ r.tax = 1.50.should.not == nil
95
+ r.compute_net
96
+
97
+ r.net.should == 8.50
98
+ r.net_money.to_f.should == r.net
99
+
100
+ r.compute_net_money
101
+
102
+ r.net.should == 8.50
103
+ r.net_money.to_f.should == r.net
104
+ end
105
+
106
+ end # class
107
+
108
+ end # module
109
+
@@ -0,0 +1,355 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+
4
+ describe Currency::Money do
5
+
6
+ it "create" do
7
+ m = Currency::Money.new(1.99)
8
+ m.should be_kind_of(Currency::Money)
9
+ Currency::Currency.default.should == m.currency
10
+ :USD.should == m.currency.code
11
+ end
12
+
13
+ describe "object money method" do
14
+ it "works with a float" do
15
+ m = 1.99.money(:USD)
16
+ m.should be_kind_of(Currency::Money)
17
+ :USD.should == m.currency.code
18
+ m.rep.should == 1990000
19
+ end
20
+
21
+ it "works with a FixNum" do
22
+ m = 199.money(:CAD)
23
+ m.should be_kind_of(Currency::Money)
24
+ :CAD.should == m.currency.code
25
+ m.rep.should == 199000000
26
+ end
27
+
28
+ it "works with a string" do
29
+ m = "13.98".money(:CAD)
30
+ m.should be_kind_of(Currency::Money)
31
+ :CAD.should == m.currency.code
32
+ m.rep.should == 13980000
33
+ end
34
+
35
+ it "works with a string again" do
36
+ m = "45.99".money(:EUR)
37
+ m.should be_kind_of(Currency::Money)
38
+ :EUR.should == m.currency.code
39
+ m.rep.should == 45990000
40
+ end
41
+
42
+ it "creates money objects from strings" do
43
+ "12.0001".money(:USD).to_s.should == "$12.0001"
44
+ # "12.000108".money(:USD).to_s(:thousands => false, :decimals => 5).should == "$12.00011"
45
+ @money = Currency::Money.new_rep(1234567890000, :USD, nil)
46
+
47
+ Currency::Money.new("12.000108").to_s(:thousands => false, :decimals => 5).should == "$12.00011"
48
+ end
49
+ end
50
+
51
+ def zero_money
52
+ @zero_money ||= Currency::Money.new(0)
53
+ end
54
+
55
+ it "zero" do
56
+ zero_money.negative?.should_not == true
57
+ zero_money.zero?.should_not == nil
58
+ zero_money.positive?.should_not == true
59
+ end
60
+
61
+ def negative_money
62
+ @negative_money ||= Currency::Money.new(-1.00, :USD)
63
+ end
64
+
65
+ it "negative" do
66
+ negative_money.negative?.should_not == nil
67
+ negative_money.zero?.should_not == true
68
+ negative_money.positive?.should_not == true
69
+ end
70
+
71
+ def positive_money
72
+ @positive_money ||= Currency::Money.new(2.99, :USD)
73
+ end
74
+ it "positive" do
75
+ positive_money.negative?.should_not == true
76
+ positive_money.zero?.should_not == true
77
+ positive_money.positive?.should_not == nil
78
+ end
79
+
80
+ it "relational" do
81
+ n = negative_money
82
+ z = zero_money
83
+ p = positive_money
84
+
85
+ (n.should < p)
86
+ (n > p).should_not == true
87
+ (p < n).should_not == true
88
+ (p.should > n)
89
+ (p != n).should_not == nil
90
+
91
+ (z.should <= z)
92
+ (z.should >= z)
93
+
94
+ (z.should <= p)
95
+ (n.should <= z)
96
+ (z.should >= n)
97
+
98
+ n.should == n
99
+ p.should == p
100
+
101
+ z.should == zero_money
102
+ end
103
+
104
+ it "compare" do
105
+ n = negative_money
106
+ z = zero_money
107
+ p = positive_money
108
+
109
+ (n <=> p).should == -1
110
+ (p <=> n).should == 1
111
+ (p <=> z).should == 1
112
+
113
+ (n <=> n).should == 0
114
+ (z <=> z).should == 0
115
+ (p <=> p).should == 0
116
+ end
117
+
118
+ it "rep" do
119
+ m = Currency::Money.new(123, :USD)
120
+ m.should_not == nil
121
+ m.rep.should == 123000000
122
+
123
+ m = Currency::Money.new(123.45, :USD)
124
+ m.should_not == nil
125
+ m.rep.should == 123450000
126
+
127
+ m = Currency::Money.new("123.456", :USD)
128
+ m.should_not == nil
129
+ m.rep.should == 123456000
130
+ end
131
+
132
+ it "convert" do
133
+ m = Currency::Money.new("123.456", :USD)
134
+ m.should_not == nil
135
+ m.rep.should == 123456000
136
+
137
+ m.to_i.should == 123
138
+ m.to_f.should == 123.456
139
+ m.to_s.should == "$123.456000"
140
+ end
141
+
142
+ it "eql" do
143
+ usd1 = Currency::Money.new(123, :USD)
144
+ usd1.should_not == nil
145
+ usd2 = Currency::Money.new("123", :USD)
146
+ usd2.should_not == nil
147
+
148
+ usd1.currency.code.should == :USD
149
+ usd2.currency.code.should == :USD
150
+
151
+ usd2.rep.should == usd1.rep
152
+
153
+ usd1.should == usd2
154
+
155
+ end
156
+
157
+ it "not eql" do
158
+
159
+ usd1 = Currency::Money.new(123, :USD)
160
+ usd1.should_not == nil
161
+ usd2 = Currency::Money.new("123.01", :USD)
162
+ usd2.should_not == nil
163
+
164
+ usd1.currency.code.should == :USD
165
+ usd2.currency.code.should == :USD
166
+
167
+ usd2.rep.should_not == usd1.rep
168
+
169
+ (usd1 != usd2).should_not == nil
170
+
171
+ ################
172
+ # currency !=
173
+ # rep ==
174
+
175
+ usd = Currency::Money.new(123, :USD)
176
+ usd.should_not == nil
177
+ cad = Currency::Money.new(123, :CAD)
178
+ cad.should_not == nil
179
+
180
+ usd.currency.code.should == :USD
181
+ cad.currency.code.should == :CAD
182
+
183
+ cad.rep.should == usd.rep
184
+ (usd.currency != cad.currency).should_not == nil
185
+
186
+ (usd != cad).should_not == nil
187
+
188
+ end
189
+
190
+ describe "operations" do
191
+ before(:each) do
192
+ @usd = Currency::Money.new(123.45, :USD)
193
+ @cad = Currency::Money.new(123.45, :CAD)
194
+ end
195
+
196
+ it "should work" do
197
+ @usd.should_not == nil
198
+ @cad.should_not == nil
199
+ end
200
+
201
+ it "handle negative money" do
202
+ # - Currency::Money => Currency::Money
203
+ (- @usd).rep.should == -123450000
204
+ (- @usd).currency.code.should == :USD
205
+
206
+ (- @cad).rep.should == -123450000
207
+ (- @cad).currency.code.should == :CAD
208
+ end
209
+
210
+ it "should add monies of the same currency" do
211
+ m = (@usd + @usd)
212
+ m.should be_kind_of(Currency::Money)
213
+ m.rep.should == 246900000
214
+ m.currency.code.should == :USD
215
+ end
216
+
217
+ it "should add monies of different currencies and return USD" do
218
+ m = (@usd + @cad)
219
+ m.should be_kind_of(Currency::Money)
220
+ m.rep.should == 228890724
221
+ m.currency.code.should == :USD
222
+ end
223
+
224
+ it "should add monies of different currencies and return CAD" do
225
+ m = (@cad + @usd)
226
+ m.should be_kind_of(Currency::Money)
227
+ m.rep.should == 267985260
228
+ m.currency.code.should == :CAD
229
+ end
230
+
231
+ it "should subtract monies of the same currency" do
232
+ m = (@usd - @usd)
233
+ m.should be_kind_of(Currency::Money)
234
+ m.rep.should == 0
235
+ m.currency.code.should == :USD
236
+ end
237
+
238
+ it "should subtract monies of different currencies and return USD" do
239
+ m = (@usd - @cad)
240
+ m.should be_kind_of(Currency::Money)
241
+ m.rep.should == 18009276
242
+ m.currency.code.should == :USD
243
+ end
244
+
245
+ it "should subtract monies of different currencies and return CAD" do
246
+ m = (@cad - @usd)
247
+ m.should be_kind_of(Currency::Money)
248
+ m.rep.should == -21085260
249
+ m.currency.code.should == :CAD
250
+ end
251
+
252
+ it "should multiply by numerics and return money" do
253
+ m = (@usd * 0.5)
254
+ m.should be_kind_of(Currency::Money)
255
+ m.rep.should == 61725000
256
+ m.currency.code.should == :USD
257
+ end
258
+
259
+ it "should divide by numerics and return money" do
260
+ m = @usd / 3
261
+ m.should be_kind_of(Currency::Money)
262
+ m.rep.should == 41150000
263
+ m.currency.code.should == :USD
264
+ end
265
+
266
+ it "should divide by monies of the same currency and return numeric" do
267
+ m = @usd / Currency::Money.new("41.15", :USD)
268
+ m.should be_kind_of(Numeric)
269
+ m.should be_close(3.0, 1.0e-8)
270
+ end
271
+
272
+ it "should divide by monies of different currencies and return numeric" do
273
+ m = (@usd / @cad)
274
+ m.should be_kind_of(Numeric)
275
+ m.should be_close(Currency::Exchange::Rate::Source::Test.USD_CAD, 0.0001)
276
+ end
277
+ end
278
+
279
+ it "pivot conversions" do
280
+ # Using default get_rate
281
+ cad = Currency::Money.new(123.45, :CAD)
282
+ cad.should_not == nil
283
+ eur = cad.convert(:EUR)
284
+ eur.should_not == nil
285
+ m = (eur.to_f / cad.to_f)
286
+ m.should be_kind_of(Numeric)
287
+ m_expected = (1.0 / Currency::Exchange::Rate::Source::Test.USD_CAD) * Currency::Exchange::Rate::Source::Test.USD_EUR
288
+ m.should be_close(m_expected, 0.001)
289
+
290
+
291
+ gbp = Currency::Money.new(123.45, :GBP)
292
+ gbp.should_not == nil
293
+ eur = gbp.convert(:EUR)
294
+ eur.should_not == nil
295
+ m = (eur.to_f / gbp.to_f)
296
+ m.should be_kind_of(Numeric)
297
+ m_expected = (1.0 / Currency::Exchange::Rate::Source::Test.USD_GBP) * Currency::Exchange::Rate::Source::Test.USD_EUR
298
+ m.should be_close(m_expected, 0.001)
299
+ end
300
+
301
+
302
+ it "invalid currency code" do
303
+ lambda {Currency::Money.new(123, :asdf)}.should raise_error(Currency::Exception::InvalidCurrencyCode)
304
+ lambda {Currency::Money.new(123, 5)}.should raise_error(Currency::Exception::InvalidCurrencyCode)
305
+ end
306
+
307
+
308
+ it "time default" do
309
+ Currency::Money.default_time = nil
310
+
311
+ usd = Currency::Money.new(123.45, :USD)
312
+ usd.should_not == nil
313
+ usd.time.should == nil
314
+
315
+ Currency::Money.default_time = Time.now
316
+ usd = Currency::Money.new(123.45, :USD)
317
+ usd.should_not == nil
318
+ Currency::Money.default_time.should == usd.time
319
+ end
320
+
321
+
322
+ it "time now" do
323
+ Currency::Money.default_time = :now
324
+
325
+ usd = Currency::Money.new(123.45, :USD)
326
+ usd.should_not == nil
327
+ usd.time.should_not == nil
328
+
329
+ sleep 1
330
+
331
+ usd2 = Currency::Money.new(123.45, :USD)
332
+ usd2.should_not == nil
333
+ usd2.time.should_not == nil
334
+ (usd.time != usd2.time).should_not == nil
335
+
336
+ Currency::Money.default_time = nil
337
+ end
338
+
339
+
340
+ it "time fixed" do
341
+ Currency::Money.default_time = Time.new
342
+
343
+ usd = Currency::Money.new(123.45, :USD)
344
+ usd.should_not == nil
345
+ usd.time.should_not == nil
346
+
347
+ sleep 1
348
+
349
+ usd2 = Currency::Money.new(123.45, :USD)
350
+ usd2.should_not == nil
351
+ usd2.time.should_not == nil
352
+ usd.time.should == usd2.time
353
+ end
354
+ end
355
+