acvwilson-acvwilson-currency 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) 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 +48 -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 +50 -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 +300 -0
  38. data/lib/currency/macro.rb +321 -0
  39. data/lib/currency/money.rb +296 -0
  40. data/lib/currency/money_helper.rb +13 -0
  41. data/lib/currency/parser.rb +193 -0
  42. data/spec/ar_base_spec.rb +140 -0
  43. data/spec/ar_column_spec.rb +69 -0
  44. data/spec/ar_core_spec.rb +64 -0
  45. data/spec/ar_simple_spec.rb +31 -0
  46. data/spec/config_spec.rb +29 -0
  47. data/spec/federal_reserve_spec.rb +75 -0
  48. data/spec/formatter_spec.rb +72 -0
  49. data/spec/historical_writer_spec.rb +187 -0
  50. data/spec/macro_spec.rb +109 -0
  51. data/spec/money_spec.rb +347 -0
  52. data/spec/new_york_fed_spec.rb +73 -0
  53. data/spec/parser_spec.rb +105 -0
  54. data/spec/spec_helper.rb +25 -0
  55. data/spec/time_quantitizer_spec.rb +115 -0
  56. data/spec/timed_cache_spec.rb +95 -0
  57. data/spec/xe_spec.rb +50 -0
  58. metadata +117 -0
@@ -0,0 +1,73 @@
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
+
6
+ require 'currency' # For :type => :money
7
+ require 'currency/exchange/rate/source/new_york_fed'
8
+
9
+ module Currency
10
+
11
+ class NewYorkFedTest < TestBase
12
+ before do
13
+ super
14
+ end
15
+
16
+
17
+ @@available = nil
18
+
19
+ # New York Fed rates are not available on Saturday and Sunday.
20
+ def available?
21
+ if @@available == nil
22
+ @@available = @source.available?
23
+ STDERR.puts "Warning: NewYorkFed unavailable on Saturday and Sunday, skipping tests."
24
+ end
25
+ @@available
26
+ end
27
+
28
+
29
+ def get_rate_source
30
+ # Force NewYorkFed Exchange.
31
+ verbose = false
32
+ source = @source = Exchange::Rate::Source::NewYorkFed.new(:verbose => verbose)
33
+ deriver = Exchange::Rate::Deriver.new(:source => source, :verbose => source.verbose)
34
+ end
35
+
36
+
37
+
38
+ it "usd cad" do
39
+ return unless available?
40
+
41
+ rates = Exchange::Rate::Source.default.source.raw_rates.should.not == nil
42
+ rates[:USD].should.not == nil
43
+ usd_cad = rates[:USD][:CAD].should.not == nil
44
+
45
+ usd = Money.new(123.45, :USD).should.not == nil
46
+ cad = usd.convert(:CAD).should.not == nil
47
+
48
+ assert_kind_of Numeric, m = (cad.to_f / usd.to_f)
49
+ # $stderr.puts "m = #{m}"
50
+ assert_equal_float usd_cad, m, 0.001
51
+ end
52
+
53
+
54
+ it "cad eur" do
55
+ return unless available?
56
+
57
+ rates = Exchange::Rate::Source.default.source.raw_rates.should.not == nil
58
+ rates[:USD].should.not == nil
59
+ usd_cad = rates[:USD][:CAD].should.not == nil
60
+ usd_eur = rates[:USD][:EUR].should.not == nil
61
+
62
+ cad = Money.new(123.45, :CAD).should.not == nil
63
+ eur = cad.convert(:EUR).should.not == nil
64
+
65
+ assert_kind_of Numeric, m = (eur.to_f / cad.to_f)
66
+ # $stderr.puts "m = #{m}"
67
+ assert_equal_float (1.0 / usd_cad) * usd_eur, m, 0.001
68
+ end
69
+
70
+ end
71
+
72
+ end # module
73
+
@@ -0,0 +1,105 @@
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
+
7
+ module Currency
8
+
9
+ class ParserTest < TestBase
10
+ before do
11
+ super
12
+ @parser = ::Currency::Currency.USD.parser_or_default
13
+ end
14
+
15
+ ############################################
16
+ # Simple stuff.
17
+ #
18
+
19
+ it "default" do
20
+
21
+ end
22
+
23
+
24
+ it "thousands" do
25
+ @parser.parse("1234567.89").rep.should == 123456789
26
+ assert_equal 123456789, @parser.parse("1,234,567.89").rep
27
+ end
28
+
29
+
30
+ it "cents" do
31
+ @parser.parse("1234567.89").rep.should == 123456789
32
+ @parser.parse("1234567").rep.should == 123456700
33
+ @parser.parse("1234567.").rep.should == 123456700
34
+ @parser.parse("1234567.8").rep.should == 123456780
35
+ @parser.parse("1234567.891").rep.should == 123456789
36
+ @parser.parse("-1234567").rep.should == -123456700
37
+ @parser.parse("+1234567").rep.should == 123456700
38
+ end
39
+
40
+
41
+ it "misc" do
42
+ m = "123.45 USD".money + "100 CAD".should.not == nil
43
+ (m.rep == 200.45).should.not == true
44
+ end
45
+
46
+
47
+ it "round trip" do
48
+ ::Currency::Currency.default = :USD
49
+ m = ::Currency::Money("1234567.89", :CAD).should.not == nil
50
+ m2 = ::Currency::Money(m.inspect).should.not == nil
51
+ m2.rep.should == m.rep
52
+ m2.currency.should == m.currency
53
+ m2.time.should == nil
54
+ m2.inspect.should == m.inspect
55
+ end
56
+
57
+
58
+ it "round trip time" do
59
+ ::Currency::Currency.default = :USD
60
+ time = Time.now.getutc
61
+ m = ::Currency::Money("1234567.89", :CAD, time).should.not == nil
62
+ m.time.should.not == nil
63
+ m2 = ::Currency::Money(m.inspect).should.not == nil
64
+ m2.time.should.not == nil
65
+ m2.rep.should == m.rep
66
+ m2.currency.should == m.currency
67
+ m2.time.to_i.should == m.time.to_i
68
+ m2.inspect.should == m.inspect
69
+ end
70
+
71
+
72
+ it "time nil" do
73
+ parser = ::Currency::Parser.new
74
+ parser.time = nil
75
+
76
+ m = parser.parse("$1234.55").should.not == nil
77
+ m.time.should == nil
78
+ end
79
+
80
+
81
+ it "time" do
82
+ parser = ::Currency::Parser.new
83
+ parser.time = Time.new
84
+
85
+ m = parser.parse("$1234.55").should.not == nil
86
+ m.time.should == parser.time
87
+ end
88
+
89
+
90
+ it "time now" do
91
+ parser = ::Currency::Parser.new
92
+ parser.time = :now
93
+
94
+ m = parser.parse("$1234.55").should.not == nil
95
+ m1_time = m.time.should.not == nil
96
+
97
+ m = parser.parse("$1234.55").should.not == nil
98
+ m2_time = m.time.should.not == nil
99
+
100
+ assert_not_equal m1_time, m2_time
101
+ end
102
+ end
103
+
104
+ end # module
105
+
@@ -0,0 +1,25 @@
1
+ # Copyright (C) 2006-2007 Kurt Stephens <ruby-currency(at)umleta.com>
2
+ # See LICENSE.txt for details.
3
+
4
+ require 'spec'
5
+ require 'currency'
6
+ require 'currency/exchange/rate/source/test'
7
+
8
+ def setup
9
+ rate_source ||= get_rate_source
10
+ Currency::Exchange::Rate::Source.default = rate_source
11
+
12
+ # Force non-historical money values.
13
+ Currency::Money.default_time = nil
14
+ end
15
+
16
+ def get_rate_source
17
+ source = Currency::Exchange::Rate::Source::Test.instance
18
+ Currency::Exchange::Rate::Deriver.new(:source => source)
19
+ end
20
+
21
+ Spec::Runner.configure do |config|
22
+ config.before(:all) {setup}
23
+ end
24
+
25
+
@@ -0,0 +1,115 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe Currency::Exchange::TimeQuantitizerTest do
4
+
5
+ def assert_test_day(t0)
6
+ tq = test_create
7
+
8
+ begin
9
+ t1 = tq.quantitize_time(t0).should_not == nil
10
+ #$stderr.puts "t0 = #{t0}"
11
+ #$stderr.puts "t1 = #{t1}"
12
+
13
+ t1.year.should == t0.year
14
+ t1.month.should == t0.month
15
+ t1.day.should == t0.day
16
+ assert_time_beginning_of_day(t1)
17
+ rescue Object => err
18
+ raise("#{err}\nDuring quantitize_time(#{t0} (#{t0.to_i}))")
19
+ end
20
+
21
+ t1
22
+ end
23
+
24
+ def assert_test_minute(t0)
25
+ tq = TimeQuantitizer.new(:time_quant_size => 60) # 1 minute
26
+
27
+ tq.local_timezone_offset
28
+
29
+ t1 = tq.quantitize_time(t0).should_not == nil
30
+ $stderr.puts "t0 = #{t0}"
31
+ $stderr.puts "t1 = #{t1}"
32
+
33
+ t1.year.should == t0.year
34
+ t1.month.should == t0.month
35
+ t1.day.should == t0.day
36
+ assert_time_beginning_of_day(t1)
37
+
38
+ t1
39
+ end
40
+
41
+
42
+ def assert_time_beginning_of_day(t1)
43
+ t1.hour.should == 0
44
+ assert_time_beginning_of_hour(t1)
45
+ end
46
+
47
+
48
+ def assert_time_beginning_of_hour(t1)
49
+ t1.min.should == 0
50
+ assert_time_beginning_of_min(t1)
51
+ end
52
+
53
+
54
+ def assert_time_beginning_of_min(t1)
55
+ t1.sec.should == 0
56
+ endshould_not
57
+
58
+ it "create" do
59
+ tq = TimeQuantitizer.new()
60
+ tg.should be_kind_of(TimeQuantitizer)
61
+ tq.time_quant_size.should == 60 * 60 * 24
62
+ tq.quantitize_time(nil).should == nil
63
+ end
64
+
65
+
66
+ it "localtime" do
67
+ t1 = assert_test_day(t0 = Time.new)
68
+ t1.utc_offset.should == t0.utc_offset
69
+ t1.utc_offset.should == Time.now.utc_offset
70
+ end
71
+
72
+
73
+ it "utc" do
74
+ t1 = assert_test_day(t0 = Time.new.utc)
75
+ t1.utc_offset.should == t0.utc_offset
76
+ end
77
+
78
+
79
+ it "random" do
80
+ (1 .. 1000).each do
81
+ t0 = Time.at(rand(1234567901).to_i)
82
+ assert_test_day(t0)
83
+ assert_test_hour(t0)
84
+ # Problem year?
85
+ t0 = Time.parse('1977/01/01') + rand(60 * 60 * 24 * 7 * 52).to_i
86
+ assert_test_day(t0)
87
+ assert_test_hour(t0)
88
+ # Problem year?
89
+ t0 = Time.parse('1995/01/01') + rand(60 * 60 * 24 * 7 * 52).to_i
90
+ assert_test_day(t0)
91
+ assert_test_hour(t0)
92
+ end
93
+
94
+
95
+ end
96
+
97
+
98
+ def assert_test_hour(t0)
99
+ tq = TimeQuantitizer.new(:time_quant_size => 60 * 60) # 1 hour
100
+
101
+ t1 = tq.quantitize_time(t0).should_not == nil
102
+ #$stderr.puts "t0 = #{t0}"
103
+ #$stderr.puts "t1 = #{t1}"
104
+
105
+ t1.year.should == t0.year
106
+ t1.month.should == t0.month
107
+ t1.day.should == t0.day
108
+ assert_time_beginning_of_hour(t1)
109
+
110
+ t1
111
+ end
112
+
113
+ end # class
114
+
115
+
@@ -0,0 +1,95 @@
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
+
6
+ require 'currency'
7
+ require 'currency/exchange/rate/source/xe'
8
+ require 'currency/exchange/rate/source/timed_cache'
9
+
10
+ module Currency
11
+
12
+ class TimedCacheTest < TestBase
13
+ before do
14
+ super
15
+ end
16
+
17
+
18
+ def get_rate_source
19
+ @source = source = Exchange::Rate::Source::Xe.new
20
+
21
+ # source.verbose = true
22
+ deriver = Exchange::Rate::Deriver.new(:source => source)
23
+
24
+ @cache = cache = Exchange::Rate::Source::TimedCache.new(:source => deriver)
25
+
26
+ cache
27
+ end
28
+
29
+
30
+ it "timed cache usd cad" do
31
+ rates = @source.raw_rates.should.not == nil
32
+ rates[:USD].should.not == nil
33
+ usd_cad = rates[:USD][:CAD].should.not == nil
34
+
35
+ usd = Money.new(123.45, :USD).should.not == nil
36
+ cad = usd.convert(:CAD).should.not == nil
37
+
38
+ assert_kind_of Numeric, m = (cad.to_f / usd.to_f)
39
+ # $stderr.puts "m = #{m}"
40
+ assert_equal_float usd_cad, m, 0.001
41
+ end
42
+
43
+
44
+ it "timed cache cad eur" do
45
+ rates = @source.raw_rates.should.not == nil
46
+ rates[:USD].should.not == nil
47
+ usd_cad = rates[:USD][:CAD].should.not == nil
48
+ usd_eur = rates[:USD][:EUR].should.not == nil
49
+
50
+ cad = Money.new(123.45, :CAD).should.not == nil
51
+ eur = cad.convert(:EUR).should.not == nil
52
+
53
+ assert_kind_of Numeric, m = (eur.to_f / cad.to_f)
54
+ # $stderr.puts "m = #{m}"
55
+ assert_equal_float((1.0 / usd_cad) * usd_eur, m, 0.001)
56
+ end
57
+
58
+
59
+ it "reload" do
60
+ # @cache.verbose = 5
61
+
62
+ test_timed_cache_cad_eur
63
+
64
+ rates = @source.raw_rates.should.not == nil
65
+ rates[:USD].should.not == nil
66
+ usd_cad_1 = rates[:USD][:CAD].should.not == nil
67
+
68
+ t1 = @cache.rate_load_time.should.not == nil
69
+ t1_reload = @cache.rate_reload_time.should.not == nil
70
+ t1_reload.to_i.should > t1.to_i
71
+
72
+ @cache.time_to_live = 5
73
+ @cache.time_to_live_fudge = 0
74
+
75
+ # puts @cache.rate_reload_time.to_i - @cache.rate_load_time.to_i
76
+ @cache.rate_reload_time.to_i - @cache.rate_load_time.to_i == @cache.time_to_live.should.not == nil
77
+
78
+ sleep 10
79
+
80
+ test_timed_cache_cad_eur
81
+
82
+ t2 = @cache.rate_load_time.should.not == nil
83
+ t1.to_i != t2.to_i.should.not == nil
84
+
85
+ rates = @source.raw_rates.should.not == nil
86
+ rates[:USD].should.not == nil
87
+ usd_cad_2 = rates[:USD][:CAD].should.not == nil
88
+
89
+ usd_cad_1.object_id != usd_cad_2.object_id.should.not == nil
90
+ end
91
+
92
+ end
93
+
94
+ end # module
95
+
data/spec/xe_spec.rb ADDED
@@ -0,0 +1,50 @@
1
+ # Copyright (C) 2006-2007 Kurt Stephens <ruby-currency(at)umleta.com>
2
+ # See LICENSE.txt for details.
3
+
4
+ require 'currency/exchange/rate/source/xe'
5
+
6
+ describe Currency::Exchange::Rate::Source::XE do
7
+
8
+ before(:all) do
9
+ get_rate_source
10
+ end
11
+
12
+ def get_rate_source
13
+ source = Currency::Exchange::Rate::Source::XE.new
14
+ Currency::Exchange::Rate::Deriver.new(:source => source)
15
+ end
16
+
17
+ it "xe usd cad" do
18
+ rates = Currency::Exchange::Rate::Source.default.source.raw_rates
19
+ rates.should_not == nil
20
+ rates[:USD].should_not == nil
21
+ usd_cad = rates[:USD][:CAD].should_not == nil
22
+
23
+ usd = Currency::Money.new(123.45, :USD)
24
+ usd.should_not == nil
25
+ cad = usd.convert(:CAD).should_not == nil
26
+
27
+ m = (cad.to_f / usd.to_f)
28
+ m.should be_kind_of(Numeric)
29
+ m.should be_close(usd_cad, 0.001)
30
+ end
31
+
32
+
33
+ it "xe cad eur" do
34
+ rates = Currency::Exchange::Rate::Source.default.source.raw_rates
35
+ rates.should_not == nil
36
+ rates[:USD].should_not == nil
37
+ usd_cad = rates[:USD][:CAD].should_not == nil
38
+ usd_eur = rates[:USD][:EUR].should_not == nil
39
+
40
+ cad = Currency::Money.new(123.45, :CAD)
41
+ cad.should_not == nil
42
+ eur = cad.convert(:EUR)
43
+ eur.should_not == nil
44
+
45
+ m = (eur.to_f / cad.to_f)
46
+ m.should be_kind_of(Numeric)
47
+ m.should be_close((1.0 / usd_cad) * usd_eur, 0.001)
48
+ end
49
+
50
+ end