cleanconscience-currency 0.7.0.11

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 (55) hide show
  1. data/COPYING.txt +339 -0
  2. data/ChangeLog +8 -0
  3. data/LICENSE.txt +65 -0
  4. data/Manifest.txt +57 -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 +304 -0
  13. data/lib/currency/config.rb +93 -0
  14. data/lib/currency/core_extensions.rb +33 -0
  15. data/lib/currency/currency.rb +172 -0
  16. data/lib/currency/currency/factory.rb +131 -0
  17. data/lib/currency/exception.rb +119 -0
  18. data/lib/currency/exchange.rb +48 -0
  19. data/lib/currency/exchange/rate.rb +214 -0
  20. data/lib/currency/exchange/rate/deriver.rb +157 -0
  21. data/lib/currency/exchange/rate/source.rb +89 -0
  22. data/lib/currency/exchange/rate/source/base.rb +166 -0
  23. data/lib/currency/exchange/rate/source/failover.rb +63 -0
  24. data/lib/currency/exchange/rate/source/federal_reserve.rb +151 -0
  25. data/lib/currency/exchange/rate/source/historical.rb +79 -0
  26. data/lib/currency/exchange/rate/source/historical/rate.rb +185 -0
  27. data/lib/currency/exchange/rate/source/historical/rate_loader.rb +186 -0
  28. data/lib/currency/exchange/rate/source/historical/writer.rb +220 -0
  29. data/lib/currency/exchange/rate/source/new_york_fed.rb +127 -0
  30. data/lib/currency/exchange/rate/source/provider.rb +117 -0
  31. data/lib/currency/exchange/rate/source/test.rb +50 -0
  32. data/lib/currency/exchange/rate/source/the_financials.rb +191 -0
  33. data/lib/currency/exchange/rate/source/timed_cache.rb +198 -0
  34. data/lib/currency/exchange/rate/source/xe.rb +152 -0
  35. data/lib/currency/exchange/time_quantitizer.rb +111 -0
  36. data/lib/currency/formatter.rb +308 -0
  37. data/lib/currency/macro.rb +321 -0
  38. data/lib/currency/money.rb +293 -0
  39. data/lib/currency/money_helper.rb +13 -0
  40. data/lib/currency/parser.rb +196 -0
  41. data/spec/ar_simple_spec.rb +80 -0
  42. data/spec/ar_spec_helper.rb +164 -0
  43. data/spec/config_spec.rb +70 -0
  44. data/spec/federal_reserve_spec.rb +71 -0
  45. data/spec/formatter_spec.rb +72 -0
  46. data/spec/historical_writer_spec.rb +121 -0
  47. data/spec/macro_spec.rb +109 -0
  48. data/spec/money_spec.rb +367 -0
  49. data/spec/new_york_fed_spec.rb +73 -0
  50. data/spec/parser_spec.rb +105 -0
  51. data/spec/spec_helper.rb +25 -0
  52. data/spec/time_quantitizer_spec.rb +115 -0
  53. data/spec/timed_cache_spec.rb +95 -0
  54. data/spec/xe_spec.rb +50 -0
  55. metadata +116 -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
+ require File.dirname(__FILE__) + '/spec_helper'
4
+
5
+ describe Currency::Parser do
6
+ before do
7
+ @parser = ::Currency::Currency.USD.parser_or_default
8
+ end
9
+
10
+ describe "is great at parsing strings" do
11
+ it "can use a string that uses the thousands-separator (comma)" do
12
+ @parser.parse("1234567.89").rep.should == 123456789
13
+ @parser.parse("1,234,567.89").rep.should == 123456789
14
+ end
15
+
16
+
17
+ it "parses cents" do
18
+ @parser.parse("1234567.89").rep.should == 123456789
19
+ @parser.parse("1234567").rep.should == 123456700
20
+ @parser.parse("1234567.").rep.should == 123456700
21
+ @parser.parse("1234567.8").rep.should == 123456780
22
+ @parser.parse("1234567.891").rep.should == 123456789
23
+ @parser.parse("-1234567").rep.should == -123456700
24
+ @parser.parse("+1234567").rep.should == 123456700
25
+ end
26
+ end
27
+
28
+ describe "can convert the right hand side argument" do
29
+ it "converts the right hand argument to the left hand side currency if needed" do
30
+ m = "123.45 USD".money + "100 CAD"
31
+ m.should_not == nil
32
+ m.rep.should == ("123.45".money(:USD) + "100 CAD".money(:USD)).rep
33
+ end
34
+
35
+ it "uses the left hand sides currency if the right hand side argument does provide currency info" do
36
+ m = "123.45 USD".money
37
+ (m + 100).rep.should == (m + "100".money(:USD)).rep
38
+ end
39
+ end
40
+
41
+ describe "can use the inspect method as a serialization of self" do
42
+ it "can recreate a money object by using a .inspect-string" do
43
+ ::Currency::Currency.default = :USD
44
+ m = ::Currency::Money("1234567.89", :CAD)
45
+ m2 = ::Currency::Money(m.inspect)
46
+
47
+ m2.rep.should == m.rep
48
+ m2.currency.should == m.currency
49
+
50
+ m2.inspect.should == m.inspect
51
+ end
52
+
53
+
54
+ it "can recreate a money objectby using a .inspect-string and keep the time parameter as well" do
55
+ ::Currency::Currency.default = :USD
56
+ time = Time.now.getutc
57
+ m = ::Currency::Money("1234567.89", :CAD, time)
58
+ m.time.should_not == nil
59
+
60
+ m2 = ::Currency::Money(m.inspect)
61
+ m2.time.should_not == nil
62
+
63
+ m.should_not be(m2)
64
+
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
+ end
71
+
72
+ describe "deals with time when creating money objects" do
73
+ before do
74
+ @parser = ::Currency::Parser.new
75
+ end
76
+
77
+ it "can parse even though the parser time is nil" do
78
+ @parser.time = nil
79
+
80
+ m = @parser.parse("$1234.55")
81
+ m.time.should == nil
82
+ end
83
+
84
+
85
+ it "parses money strings into money object using the parsers time" do
86
+ @parser.time = Time.now
87
+
88
+ m = @parser.parse("$1234.55")
89
+ m.time.should == @parser.time
90
+ end
91
+
92
+
93
+ it "when re-initializing a money object, the time is also re-initialized" do
94
+ @parser.time = :now
95
+
96
+ m = @parser.parse("$1234.55")
97
+ m1_time = m.time
98
+
99
+ m = @parser.parse("$1234.55")
100
+ m2_time = m.time
101
+
102
+ m1_time.should_not == m2_time
103
+ end
104
+ end
105
+ end
@@ -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(source = nil)
9
+ rate_source ||= get_rate_source(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(source = nil)
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