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,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 File.dirname(__FILE__) + '/../lib/currency'
6
+ require File.dirname(__FILE__) + '/../lib/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