mroch-BigMoney 0.1.2 → 0.2.1

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.
@@ -0,0 +1,47 @@
1
+ require 'bigdecimal'
2
+
3
+ class BigMoney
4
+
5
+ # Find the exchange rate between two currencies.
6
+ #
7
+ # Be aware no caching is done at all at the moment.
8
+ class Exchange
9
+ class ExchangeError < StandardError; end
10
+ class ConversionError < ExchangeError; end
11
+
12
+ class << self
13
+ @@services = []
14
+ def inherited(service) #:nodoc:
15
+ @@services << service
16
+ end
17
+
18
+ # Fetch the exchange rate between two currencies. The arguments may be anything that BigMoney::Currency can
19
+ # parse. The rate is returned as a BigDecimal.
20
+ def rate(from, to)
21
+ exchange = [from, to].map do |c|
22
+ Currency.parse(c) or raise BigMoney::UnknownCurrency
23
+ end
24
+ return BigDecimal(1.to_s) if exchange.uniq.length == 1
25
+
26
+ service = @@services.reverse.find do |service|
27
+ !!exchange.reject{|c| service.currencies.include?(c)}
28
+ end
29
+
30
+ service or raise ConversionError # TODO: Message?
31
+ BigDecimal.new(service.read_rate(*exchange).to_s)
32
+ end
33
+
34
+ protected
35
+ # Exchange rate from the first currency to the second.
36
+ def read_rate(from, to)
37
+ raise NotImplementedError
38
+ end
39
+
40
+ # An array of supported currencies.
41
+ def currencies
42
+ raise NotImplementedError
43
+ end
44
+ end
45
+ end # Exchange
46
+
47
+ end # Money
@@ -0,0 +1,32 @@
1
+ require 'open-uri'
2
+
3
+ class BigMoney
4
+ class Exchange
5
+
6
+ # Yahoo finance exchange service.
7
+ #
8
+ # http://finance.yahoo.com
9
+ class Yahoo < Exchange
10
+ class << self
11
+ protected
12
+ def read_rate(from, to)
13
+ s = [from, to].map{|c| c.code}.join
14
+ open("http://download.finance.yahoo.com/d/quotes.csv?s=#{s}=X&f=l1&e=.csv").read.strip rescue nil
15
+ end
16
+
17
+ def currencies
18
+ %w{
19
+ ALL DZD XAL ARS AWG AUD BSD BHD BDT BBD BYR BZD BMD BTN BOB BWP BRL GBP BND BGN BIF KHR CAD CVE KYD XOF XAF
20
+ CLP CNY COP KMF XCP CRC HRK CUP CYP CZK DKK DJF DOP XCD ECS EGP SVC ERN EEK ETB EUR FKP FJD GMD GHC GIP XAU
21
+ GTQ GNF GYD HTG HNL HKD HUF ISK INR IDR IRR IQD ILS JMD JPY JOD KZT KES KRW KWD LAK LVL LBP LSL LRD LYD LTL
22
+ MOP MKD MWK MYR MVR MTL MRO MUR MXN MDL MNT MAD MMK NAD NPR ANG TRY NZD NIO NGN KPW NOK OMR XPF PKR XPD PAB
23
+ PGK PYG PEN PHP XPT PLN QAR RON RUB RWF WST STD SAR SCR SLL XAG SGD SKK SIT SBD SOS ZAR LKR SHP SDD SZL SEK
24
+ CHF SYP TWD TZS THB TOP TTD TND USD AED UGX UAH UYU VUV VEB VND YER ZMK ZWD
25
+ }
26
+ end
27
+ end
28
+ end # Yahoo
29
+
30
+ end # Exchange
31
+ end # Money
32
+
@@ -0,0 +1,7 @@
1
+ # Only works on unixy type systems.
2
+ # http://blog.behindlogic.com/2008/10/auto-generate-your-manifest-and-gemspec.html
3
+ desc 'Rebuild manifest and gemspec.'
4
+ task :cultivate do
5
+ system %q{touch Manifest.txt; rake check_manifest | grep -v "(in " | patch}
6
+ system %q{rake debug_gem | grep -v "(in " > `basename \`pwd\``.gemspec}
7
+ end
@@ -0,0 +1,16 @@
1
+ namespace :currency do
2
+
3
+ desc 'Create ISO 4217 currency classes from wikipedia ISO 4217 table.'
4
+ task :iso4217 do
5
+ dirname = File.dirname(__FILE__)
6
+ gen = File.join(dirname, %w{iso4217.rb})
7
+ lib = File.expand_path(File.join(dirname, %w{.. lib big_money currency iso4217.rb}))
8
+ require gen
9
+ modules = BigMoney::Task::ISO4217.get
10
+ File.open(lib, File::CREAT | File::TRUNC | File::WRONLY) do |f|
11
+ f.write modules
12
+ end
13
+ end
14
+
15
+ end # :currency
16
+
@@ -0,0 +1,46 @@
1
+ require 'hpricot'
2
+ require 'open-uri'
3
+ require 'erubis'
4
+
5
+ class BigMoney
6
+ module Task
7
+ module ISO4217
8
+ def self.get
9
+ doc = Hpricot(open('http://en.wikipedia.org/wiki/ISO_4217').read)
10
+ codes = doc.at('//a#Active_codes').parent
11
+ codes.name =~ /table/ && break while codes = codes.next_sibling
12
+ to_ruby(codes) if codes
13
+ end
14
+
15
+ def self.to_ruby(codes)
16
+ currencies = (codes / 'tr').map{|tr| currency tr}.compact
17
+ currencies.reject!{|c| c[:code] !~ /[A-Z]{3}/ || c[:name] !~ /\w+/}
18
+ tmpl = File.read(File.join(File.dirname(__FILE__), 'iso4217.rb.erb'))
19
+ eruby = Erubis::Eruby.new(tmpl)
20
+ eruby.result(:currencies => currencies)
21
+ end
22
+
23
+ def self.currency(tr)
24
+ values = (tr / 'td')
25
+ return unless values && values.size >= 4
26
+ {
27
+ :code => code(values),
28
+ :name => name(values),
29
+ :offset => offset(values)
30
+ }
31
+ end
32
+
33
+ def self.code(chunks)
34
+ chunks[0].inner_html
35
+ end
36
+
37
+ def self.offset(chunks)
38
+ chunks[2].inner_html.to_i rescue 0
39
+ end
40
+
41
+ def self.name(chunks)
42
+ (chunks[3] / 'a').inner_html rescue chunks[3].inner_html
43
+ end
44
+ end # ISO4217
45
+ end # Task
46
+ end # BigMoney
@@ -0,0 +1,13 @@
1
+ class BigMoney
2
+ class Currency
3
+ <% currencies.each do |currency| -%>
4
+ class <%= currency[:code].upcase %> < Currency #:nodoc:
5
+ self.name = %q{<%= currency[:name] %>}
6
+ self.code = %q{<%= currency[:code] %>}
7
+ self.offset = <%= currency[:offset] %>
8
+ end
9
+
10
+ <% end -%>
11
+ end # Currency
12
+ end # BigMoney
13
+
@@ -3,47 +3,58 @@ require 'big_money'
3
3
  require 'bigdecimal'
4
4
 
5
5
  class TestBigMoney < Test::Unit::TestCase
6
-
6
+
7
7
  def test_initialize_with_bigdecimal
8
8
  val = BigDecimal.new("1.005")
9
9
  assert_same val, BigMoney.new(val).amount, 'Should not create a clone of the input'
10
10
  end
11
-
11
+
12
12
  def test_initialize_with_string
13
13
  assert_equal BigDecimal.new("1.005"), BigMoney.new("1.005").amount
14
14
  assert_equal BigDecimal.new("10"), BigMoney.new("10").amount
15
15
  assert_equal BigDecimal.new("0"), BigMoney.new("0").amount
16
16
  assert_equal BigDecimal.new("0"), BigMoney.new("foo").amount
17
17
  end
18
-
18
+
19
19
  def test_initialize_with_integer
20
20
  assert_equal BigDecimal.new("100"), BigMoney.new(100).amount
21
21
  assert_equal BigDecimal.new("0"), BigMoney.new(0).amount
22
22
  end
23
-
23
+
24
24
  def test_initialize_with_float
25
25
  assert_equal BigDecimal.new("1.005"), BigMoney.new(1.005).amount
26
26
  assert_equal BigDecimal.new("0"), BigMoney.new(0.0).amount
27
27
  end
28
-
28
+
29
+ def test_initialize_without_currency
30
+ assert_equal BigMoney::Currency::USD.instance, BigMoney.new(1.23).currency
31
+ end
32
+
33
+ def test_initialize_with_currency
34
+ assert_equal BigMoney::Currency::AUD.instance, BigMoney.new(1.23, :aud).currency
35
+ assert_raises BigMoney::UnknownCurrency do
36
+ BigMoney.new(1.23, :fud)
37
+ end
38
+ end
39
+
29
40
  def test_eql?
30
41
  assert BigMoney.new("1.00", :usd).eql?(BigMoney.new("1.00", :usd))
31
42
  assert !BigMoney.new("1.00", :usd).eql?(BigMoney.new("1.01", :usd))
32
43
  assert !BigMoney.new("1.00", :usd).eql?(BigMoney.new("1.00", :cad))
33
44
  end
34
-
45
+
35
46
  def test_compare
36
47
  m1, m2 = BigMoney.new("1.00", :usd), BigMoney.new("1.50", :usd)
37
48
  assert_equal(-1, (m1 <=> m2))
38
49
  assert_equal(0, (m1 <=> m1))
39
50
  assert_equal(1, (m2 <=> m1))
40
-
51
+
41
52
  m3 = BigMoney.new("1.00", :cad)
42
53
  assert_raises BigMoney::UncomparableCurrency do
43
54
  m1 <=> m3
44
55
  end
45
56
  end
46
-
57
+
47
58
  def test_add
48
59
  m1, m2, m3 = BigMoney.new(1.00, :usd), BigMoney.new(1.50, :usd), BigMoney.new(0, :usd)
49
60
  assert_equal BigDecimal.new("2.50"), (m1 + m2).amount
@@ -55,7 +66,7 @@ class TestBigMoney < Test::Unit::TestCase
55
66
  assert_equal BigDecimal.new("5.50"), (m2 + 4).amount
56
67
  assert_equal BigDecimal.new("5.50"), (m2 + 4.00).amount
57
68
  end
58
-
69
+
59
70
  def test_subtract
60
71
  m1, m2, m3 = BigMoney.new(1.00, :usd), BigMoney.new(1.50, :usd), BigMoney.new(0, :usd)
61
72
  assert_equal BigDecimal.new("-0.50"), (m1 - m2).amount
@@ -65,7 +76,7 @@ class TestBigMoney < Test::Unit::TestCase
65
76
  assert_equal BigDecimal.new("-2.50"), (m2 - 4).amount
66
77
  assert_equal BigDecimal.new("-2.50"), (m2 - 4.00).amount
67
78
  end
68
-
79
+
69
80
  def test_multiply
70
81
  m1, m2, m3 = BigMoney.new(2.00, :usd), BigMoney.new(1.50, :usd), BigMoney.new(0, :usd)
71
82
  assert_equal BigDecimal.new("4.00"), (m1 * m1).amount
@@ -77,7 +88,7 @@ class TestBigMoney < Test::Unit::TestCase
77
88
  assert_equal BigDecimal.new("3.00"), (m2 * 2).amount
78
89
  assert_equal BigDecimal.new("3.00"), (m2 * 2.00).amount
79
90
  end
80
-
91
+
81
92
  def test_divide
82
93
  m1, m2, m3 = BigMoney.new(2.00, :usd), BigMoney.new(1.50, :usd), BigMoney.new(0, :usd)
83
94
  assert_equal BigDecimal.new("1.00"), (m1 / m1).amount
@@ -91,13 +102,13 @@ class TestBigMoney < Test::Unit::TestCase
91
102
  assert_equal BigDecimal.new("0.75"), (m2 / 2).amount
92
103
  assert_equal BigDecimal.new("0.75"), (m2 / 2.00).amount
93
104
  end
94
-
105
+
95
106
  def test_to_s
96
107
  assert_equal '1.00', BigMoney.new(1).to_s
97
108
  assert_equal '1.50', BigMoney.new(1.5).to_s
98
109
  assert_equal '-11.50', BigMoney.new(-11.5).to_s
99
110
  end
100
-
111
+
101
112
  def test_to_formatted_s
102
113
  assert_equal '1.00', BigMoney.new(1).to_formatted_s("%.2f")
103
114
  assert_equal '$1.00', BigMoney.new(1).to_formatted_s("$%.2f")
@@ -106,23 +117,30 @@ class TestBigMoney < Test::Unit::TestCase
106
117
  assert_equal '$1 USD', BigMoney.new(1).to_formatted_s("$%.0f %s")
107
118
  assert_equal '$1.00 <span class="currency">USD</span>', BigMoney.new(1).to_formatted_s('$%.2f <span class="currency">%s</span>')
108
119
  end
109
-
120
+
110
121
  def test_to_i
111
122
  assert_equal(1, BigMoney.new(1).to_i)
112
123
  assert_equal(1, BigMoney.new(1.5).to_i)
113
124
  assert_equal(-11, BigMoney.new(-11.5).to_i)
114
125
  end
115
-
126
+
116
127
  def test_to_f
117
128
  assert_in_delta(1.0, BigMoney.new(1).to_f, 0.000001)
118
129
  assert_in_delta(1.5, BigMoney.new(1.5).to_f, 0.000001)
119
130
  assert_in_delta(-11.5, BigMoney.new(-11.5).to_f, 0.000001)
120
131
  end
121
-
132
+
122
133
  def test_neg
123
134
  assert_equal BigMoney.new(-1), -BigMoney.new(1)
124
135
  assert_equal BigMoney.new(1), -BigMoney.new(-1)
125
136
  assert_equal BigMoney.new(1), -BigMoney.new(-1)
126
137
  end
127
138
 
128
- end
139
+ def test_currency
140
+ assert_equal BigMoney::Currency::AUD.instance, BigMoney.currency(:aud)
141
+ end
142
+
143
+ def test_exchange
144
+ assert BigMoney.new(1.50).exchange(:aud)
145
+ end
146
+ end
@@ -0,0 +1,23 @@
1
+ require 'test/unit'
2
+ require 'big_money'
3
+
4
+ class TestCurrency < Test::Unit::TestCase
5
+ def test_parse
6
+ assert_kind_of BigMoney::Currency, BigMoney::Currency.parse(:aud)
7
+ assert_nil BigMoney::Currency.parse(:fud)
8
+ end
9
+
10
+ def test_compare
11
+ aud = BigMoney::Currency::AUD.instance
12
+ assert_operator aud, :==, :aud
13
+ assert_operator aud, :==, :AUD
14
+ assert_operator aud, :==, 'aud'
15
+ assert_operator aud, :==, 'AUD'
16
+
17
+ # assert_operator aud, '!=', :fud
18
+ assert aud != :fud
19
+ assert aud != :FUD
20
+ assert aud != 'fud'
21
+ assert aud != 'FUD'
22
+ end
23
+ end
@@ -0,0 +1,21 @@
1
+ require 'test/unit'
2
+ require 'big_money'
3
+
4
+ class TestExchange < Test::Unit::TestCase
5
+ def setup
6
+ @aud = BigMoney.currency(:aud)
7
+ @usd = BigMoney.currency(:usd)
8
+ end
9
+
10
+ def test_rate
11
+ assert_kind_of BigDecimal, BigMoney::Exchange.rate(@aud, @usd)
12
+ assert_kind_of BigDecimal, BigMoney::Exchange.rate(:aud, :usd)
13
+ assert_raise BigMoney::UnknownCurrency do
14
+ BigMoney::Exchange.rate(:aud, :fud)
15
+ end
16
+ end
17
+
18
+ def test_equal_rate
19
+ assert_equal BigDecimal(1.to_s), BigMoney::Exchange.rate(:usd, :usd)
20
+ end
21
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mroch-BigMoney
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marshall Roch
@@ -9,34 +9,57 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-08-09 00:00:00 -07:00
12
+ date: 2008-10-20 00:00:00 -07:00
13
13
  default_executable:
14
- dependencies: []
15
-
16
- description: Represents an amount of money in a particular currency. Backed by BigDecimal, so is safe from float rounding errors.
17
- email: mroch@cmu.edu
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: hoe
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.8.0
23
+ version:
24
+ description: Represents an amount of money in a particular currency. Backed by BigDecimal, so is safe from float rounding errors.
25
+ email:
26
+ - mroch@cmu.edu
18
27
  executables: []
19
28
 
20
29
  extensions: []
21
30
 
22
- extra_rdoc_files: []
23
-
24
- files:
25
- - bigmoney.gemspec
31
+ extra_rdoc_files:
26
32
  - History.txt
33
+ - LICENSE.txt
27
34
  - Manifest.txt
35
+ - README.txt
36
+ files:
37
+ - History.txt
28
38
  - LICENSE.txt
29
- - Rakefile
39
+ - Manifest.txt
30
40
  - README.txt
41
+ - Rakefile
42
+ - bigmoney.gemspec
31
43
  - lib/big_money.rb
32
44
  - lib/big_money/big_money.rb
33
45
  - lib/big_money/core_extensions.rb
46
+ - lib/big_money/currency.rb
47
+ - lib/big_money/currency/iso4217.rb
48
+ - lib/big_money/exchange.rb
49
+ - lib/big_money/exchange/yahoo.rb
50
+ - rakelib/cultivate.rake
51
+ - rakelib/iso4217.rake
52
+ - rakelib/iso4217.rb
53
+ - rakelib/iso4217.rb.erb
34
54
  - test/test_big_money.rb
35
- has_rdoc: false
36
- homepage: http://github.com/mroch/bigmoney
55
+ - test/test_currency.rb
56
+ - test/test_exchange.rb
57
+ has_rdoc: true
58
+ homepage:
37
59
  post_install_message:
38
- rdoc_options: []
39
-
60
+ rdoc_options:
61
+ - --main
62
+ - README.txt
40
63
  require_paths:
41
64
  - lib
42
65
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -53,10 +76,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
53
76
  version:
54
77
  requirements: []
55
78
 
56
- rubyforge_project:
79
+ rubyforge_project: bigmoney
57
80
  rubygems_version: 1.2.0
58
81
  signing_key:
59
82
  specification_version: 2
60
- summary: Represents an amount of money in a particular currency.
83
+ summary: Represents an amount of money in a particular currency
61
84
  test_files:
62
85
  - test/test_big_money.rb
86
+ - test/test_currency.rb
87
+ - test/test_exchange.rb