big_money 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +7 -0
- data/Gemfile +11 -0
- data/LICENSE +20 -0
- data/README.rdoc +102 -0
- data/Rakefile +57 -0
- data/VERSION.yml +5 -0
- data/big_money.gemspec +65 -0
- data/lib/big_money.rb +124 -0
- data/lib/big_money/currency.rb +75 -0
- data/lib/big_money/currency/iso4217.rb +185 -0
- data/lib/big_money/exchange.rb +102 -0
- data/lib/big_money/exchange/yahoo.rb +34 -0
- data/lib/big_money/parser.rb +66 -0
- data/lib/big_money/types.rb +13 -0
- data/rakelib/iso4217.rb +49 -0
- data/rakelib/iso4217.rb.erb +10 -0
- data/test/helper.rb +18 -0
- data/test/test_big_money.rb +128 -0
- data/test/test_currency.rb +36 -0
- data/test/test_exchange.rb +37 -0
- data/test/test_parser.rb +67 -0
- metadata +84 -0
data/.document
ADDED
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008 Marshall Roch
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
= BigMoney
|
2
|
+
|
3
|
+
== Description
|
4
|
+
|
5
|
+
Represents an amount of money in a particular currency. Backed by BigDecimal, so it's safe from float rounding errors.
|
6
|
+
|
7
|
+
== Features
|
8
|
+
|
9
|
+
* Encapsulates an amount with its currency into a single object.
|
10
|
+
* Backed by BigDecimal, so it can store arbitrary-precision values without rounding errors. Useful if you're dealing
|
11
|
+
with fractional cents.
|
12
|
+
* Sensible currency handling.
|
13
|
+
* Supports all ISO-4217 currencies.
|
14
|
+
* Optional currency exchange.
|
15
|
+
* Optional string parsing.
|
16
|
+
|
17
|
+
== Problems
|
18
|
+
|
19
|
+
* Does not implement all of Numeric, so doesn't quite act like a real number.
|
20
|
+
|
21
|
+
== Todo
|
22
|
+
|
23
|
+
* Has no Money package API compatibility to ease transition (module patch welcome).
|
24
|
+
(http://dist.leetsoft.com/api/money/)
|
25
|
+
|
26
|
+
== Synopsis
|
27
|
+
|
28
|
+
=== Basic
|
29
|
+
|
30
|
+
require 'big_money'
|
31
|
+
|
32
|
+
bm = BigMoney.new('3.99', :aud)
|
33
|
+
bm.amount #=> BigDecimal.new('3.99')
|
34
|
+
bm.currency #=> BigMoney::Currency::AUD
|
35
|
+
bm.to_s #=> '3.99'
|
36
|
+
bm.to_s('$.2f') #=> '$3.99'
|
37
|
+
bm.to_s('$%.2f %s') #=> '$3.99 AUD'
|
38
|
+
|
39
|
+
# Not recommended but if you must.
|
40
|
+
BigMoney::Currency.default = :aud
|
41
|
+
|
42
|
+
bm = BigMoney.new('3.99')
|
43
|
+
bm.amount #=> BigDecimal.new('3.99')
|
44
|
+
bm.currency #=> BigMoney::Currency::AUD
|
45
|
+
|
46
|
+
bm2 = 1.to_big_money
|
47
|
+
bm2.amount #=> BigDecimal.new('3.99')
|
48
|
+
bm2.currency #=> BigMoney::Currency::AUD
|
49
|
+
|
50
|
+
=== Exchange
|
51
|
+
|
52
|
+
require 'big_money'
|
53
|
+
require 'big_money/exchange/yahoo' # Use yahoo finance exchange service.
|
54
|
+
|
55
|
+
bm = BigMoney.new('3.99', :usd)
|
56
|
+
bm.amount #=> BigDecimal.new('3.99')
|
57
|
+
bm.currency #=> BigMoney::Currency::USD
|
58
|
+
|
59
|
+
bm2 = bm.exchange(:aud)
|
60
|
+
bm.amount #=> BigDecimal.new('5.22')
|
61
|
+
bm.currency #=> BigMoney::Currency::AUD
|
62
|
+
|
63
|
+
=== Parser
|
64
|
+
|
65
|
+
require 'big_money'
|
66
|
+
require 'big_money/parser'
|
67
|
+
|
68
|
+
BigMoney.parse('JPY ¥2500') #=> BigMoney.new('2500', :jpy)
|
69
|
+
BigMoney.parse('JPY2500') #=> BigMoney.new('2500', :jpy)
|
70
|
+
BigMoney.parse('2500JPY') #=> BigMoney.new('2500', :jpy)
|
71
|
+
BigMoney.parse('¥2500JPY') #=> BigMoney.new('2500', :jpy)
|
72
|
+
|
73
|
+
# ISO-4217 BigMoney::Currency::XXX aka 'No currency' will be used if a currency cannot be parsed along with the
|
74
|
+
# amount. If you know the currency and just need the amount XXX is always exchanged 1:1 with any currency.
|
75
|
+
bm = BigMoney.parse('¥2500') #=> BigMoney.new('2500', :xxx)
|
76
|
+
bm.exchange(:jpy) #=> BigMoney.new('2500', :jpy)
|
77
|
+
|
78
|
+
=== Types
|
79
|
+
|
80
|
+
require 'big_money'
|
81
|
+
require 'big_money/types'
|
82
|
+
|
83
|
+
# Numeric
|
84
|
+
1.to_big_money(:aud) #=> BigMoney.new(1, :aud)
|
85
|
+
12_123.44.to_big_money(:aud) #=> BigMoney.new('12123.44', :aud)
|
86
|
+
|
87
|
+
# String
|
88
|
+
'1'.to_big_money(:aud) #=> BigMoney.new(1, :aud)
|
89
|
+
|
90
|
+
== Install
|
91
|
+
|
92
|
+
* Via git:
|
93
|
+
|
94
|
+
git clone git://github.com/shanna/big_money.git
|
95
|
+
|
96
|
+
* Via gem:
|
97
|
+
|
98
|
+
gem install big_money
|
99
|
+
|
100
|
+
== License
|
101
|
+
|
102
|
+
See LICENSE.
|
data/Rakefile
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'rubygems'
|
3
|
+
require 'rake'
|
4
|
+
require 'rake/testtask'
|
5
|
+
require 'rake/rdoctask'
|
6
|
+
|
7
|
+
begin
|
8
|
+
require 'jeweler'
|
9
|
+
Jeweler::Tasks.new do |gem|
|
10
|
+
gem.name = 'big_money'
|
11
|
+
gem.summary = %q{BigDecimal backed amount of money in a particular currency.}
|
12
|
+
gem.email = ['shane.hanna@gmail.com', 'mroch@cmu.edu']
|
13
|
+
gem.homepage = 'http://github.com/shanna/big_money'
|
14
|
+
gem.authors = ['Shane Hanna', 'Marshall Roch']
|
15
|
+
gem.executables = [] # Only ever bundled development executables in bin/*
|
16
|
+
end
|
17
|
+
Jeweler::GemcutterTasks.new
|
18
|
+
rescue LoadError
|
19
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
20
|
+
end
|
21
|
+
|
22
|
+
Rake::TestTask.new(:test) do |test|
|
23
|
+
test.libs << 'lib' << 'test'
|
24
|
+
test.pattern = 'test/**/test_*.rb'
|
25
|
+
test.verbose = true
|
26
|
+
end
|
27
|
+
|
28
|
+
Rake::RDocTask.new do |rdoc|
|
29
|
+
if File.exist?('VERSION.yml')
|
30
|
+
config = YAML.load(File.read('VERSION.yml'))
|
31
|
+
version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
32
|
+
else
|
33
|
+
version = ""
|
34
|
+
end
|
35
|
+
|
36
|
+
rdoc.rdoc_dir = 'rdoc'
|
37
|
+
rdoc.title = "big_money #{version}"
|
38
|
+
rdoc.rdoc_files.include('README*')
|
39
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
40
|
+
end
|
41
|
+
|
42
|
+
namespace :currency do
|
43
|
+
desc 'Create ISO 4217 currency classes from wikipedia ISO 4217 table.'
|
44
|
+
task :iso4217 do
|
45
|
+
dirname = File.dirname(__FILE__)
|
46
|
+
gen = File.join(dirname, 'rakelib', %w{iso4217.rb})
|
47
|
+
lib = File.expand_path(File.join(dirname, %w{lib big_money currency iso4217.rb}))
|
48
|
+
require gen
|
49
|
+
modules = BigMoney::Task::ISO4217.get
|
50
|
+
File.open(lib, File::CREAT | File::TRUNC | File::WRONLY) do |f|
|
51
|
+
f.write modules
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
task :default => :test
|
57
|
+
|
data/VERSION.yml
ADDED
data/big_money.gemspec
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{big_money}
|
8
|
+
s.version = "1.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Shane Hanna", "Marshall Roch"]
|
12
|
+
s.date = %q{2010-01-22}
|
13
|
+
s.email = ["shane.hanna@gmail.com", "mroch@cmu.edu"]
|
14
|
+
s.extra_rdoc_files = [
|
15
|
+
"LICENSE",
|
16
|
+
"README.rdoc"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
".document",
|
20
|
+
".gitignore",
|
21
|
+
"Gemfile",
|
22
|
+
"LICENSE",
|
23
|
+
"README.rdoc",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION.yml",
|
26
|
+
"big_money.gemspec",
|
27
|
+
"lib/big_money.rb",
|
28
|
+
"lib/big_money/currency.rb",
|
29
|
+
"lib/big_money/currency/iso4217.rb",
|
30
|
+
"lib/big_money/exchange.rb",
|
31
|
+
"lib/big_money/exchange/yahoo.rb",
|
32
|
+
"lib/big_money/parser.rb",
|
33
|
+
"lib/big_money/types.rb",
|
34
|
+
"rakelib/iso4217.rb",
|
35
|
+
"rakelib/iso4217.rb.erb",
|
36
|
+
"test/helper.rb",
|
37
|
+
"test/test_big_money.rb",
|
38
|
+
"test/test_currency.rb",
|
39
|
+
"test/test_exchange.rb",
|
40
|
+
"test/test_parser.rb"
|
41
|
+
]
|
42
|
+
s.homepage = %q{http://github.com/shanna/big_money}
|
43
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
44
|
+
s.require_paths = ["lib"]
|
45
|
+
s.rubygems_version = %q{1.3.5}
|
46
|
+
s.summary = %q{BigDecimal backed amount of money in a particular currency.}
|
47
|
+
s.test_files = [
|
48
|
+
"test/test_exchange.rb",
|
49
|
+
"test/helper.rb",
|
50
|
+
"test/test_currency.rb",
|
51
|
+
"test/test_big_money.rb",
|
52
|
+
"test/test_parser.rb"
|
53
|
+
]
|
54
|
+
|
55
|
+
if s.respond_to? :specification_version then
|
56
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
57
|
+
s.specification_version = 3
|
58
|
+
|
59
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
60
|
+
else
|
61
|
+
end
|
62
|
+
else
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
data/lib/big_money.rb
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'bigdecimal'
|
3
|
+
require 'big_money/currency'
|
4
|
+
require 'big_money/currency/iso4217'
|
5
|
+
|
6
|
+
# == Synopsis
|
7
|
+
#
|
8
|
+
# bm = BigMoney.new('3.99', :aud)
|
9
|
+
# bm.amount #=> BigDecimal.new('3.99')
|
10
|
+
# bm.currency #=> BigMoney::Currency::AUD
|
11
|
+
# bm.to_s #=> '3.99'
|
12
|
+
# bm.to_s('$.2f') #=> '$3.99'
|
13
|
+
# bm.to_s('$%.2f %s') #=> '$3.99 AUD'
|
14
|
+
#
|
15
|
+
# === Amount
|
16
|
+
#
|
17
|
+
# Amounts can be anything Numeric or Strings that are BigDecimal friendly. Keep in mind BigDecimal will silently return
|
18
|
+
# 0.0 for unrecognised strings. See BigMoney::Amount.
|
19
|
+
#
|
20
|
+
# BigMoney.new(BigDecimal.new('12.50')) # BigDecimal
|
21
|
+
# BigMoney.new(12) # Fixnum
|
22
|
+
# BigMoney.new(12.50) # Float
|
23
|
+
# BigMoney.new('12.50') # String
|
24
|
+
#
|
25
|
+
# === Currency
|
26
|
+
#
|
27
|
+
# Any currency defined by the current ISO4217 table on Wikipedia is already available. Naturally you may define your
|
28
|
+
# own currencies. See BigMoney::Currency.
|
29
|
+
#
|
30
|
+
# ==== Default
|
31
|
+
#
|
32
|
+
# A default currency risks exchanging an amount 1:1 between currencies if the default is unintentionally used.
|
33
|
+
# BigMoney expects an explicit currency in the constructor and will raise an ArugmentError unless one is given or a
|
34
|
+
# default currency set.
|
35
|
+
#
|
36
|
+
# BigMoney::Currency.default = BigMoney::Currency::AUD # Module
|
37
|
+
# BigMoney::Currency.default = 'AUD' # String, ISO4217 3 letter currency code.
|
38
|
+
# BigMoney::Currency.default = :aud # Symbol, ISO4217 3 letter currency code.
|
39
|
+
class BigMoney
|
40
|
+
include Comparable
|
41
|
+
attr_reader :amount, :currency
|
42
|
+
|
43
|
+
# Short form BigMoney::Currency.find(code) to save some typing.
|
44
|
+
#
|
45
|
+
# ==== Examples
|
46
|
+
#
|
47
|
+
# BigMoney.currency(:usd) #=> BigMoney::Currency.find(:usd)
|
48
|
+
#
|
49
|
+
# ==== Parameters
|
50
|
+
# code<#to_s>:: An upper or lowercase string or symbol of the ISO-4217 currency code.
|
51
|
+
#
|
52
|
+
# ==== Returns
|
53
|
+
# BigMoney::Currency
|
54
|
+
def self.currency(currency)
|
55
|
+
Currency.find(currency)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Create a BigMoney instance.
|
59
|
+
#
|
60
|
+
# ==== Parameters
|
61
|
+
# amount<BigDecimal, Numeric, String>:: Numeric or BigDecimal friendly String.
|
62
|
+
# currency<BigMoney::Currency, Symbol, String>:: Optional ISO-4217 3 letter currency code. Default BigMoney.currency.default
|
63
|
+
#
|
64
|
+
# ==== Returns
|
65
|
+
# BigMoney
|
66
|
+
def initialize(amount, currency = nil)
|
67
|
+
@amount = case amount
|
68
|
+
when BigDecimal then amount
|
69
|
+
when String then BigDecimal.new(amount)
|
70
|
+
when Numeric then BigDecimal.new(amount.to_s)
|
71
|
+
else raise TypeError.new("Can't convert +amount+ #{amount.class} into BigDecimal.")
|
72
|
+
end
|
73
|
+
|
74
|
+
raise ArgumentError.new("Nil +currency+ without default.") if currency.nil? && !Currency.default?
|
75
|
+
unless currency && @currency = Currency.find(currency)
|
76
|
+
raise ArgumentError.new("Unknown +currency+ '#{currency.inspect}'.") unless Currency.default?
|
77
|
+
@currency = Currency.default
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def <=>(money)
|
82
|
+
money.kind_of?(self.class) ? (currency <=> money.currency).nonzero? || (amount <=> money.amount).nonzero? || 0 : nil
|
83
|
+
end
|
84
|
+
|
85
|
+
def eql?(money)
|
86
|
+
money.kind_of?(self.class) &&
|
87
|
+
amount == money.amount &&
|
88
|
+
currency == money.currency
|
89
|
+
end
|
90
|
+
alias == eql?
|
91
|
+
|
92
|
+
def -@
|
93
|
+
self.class.new(-amount, currency)
|
94
|
+
end
|
95
|
+
|
96
|
+
[:+, :-, :*, :/].each do |op|
|
97
|
+
define_method(op) do |rvalue|
|
98
|
+
raise TypeError.new("Currency mismatch, '#{currency}' with '#{rvalue.currency}'.") \
|
99
|
+
if rvalue.kind_of?(BigMoney) && currency != rvalue.currency
|
100
|
+
|
101
|
+
rvalue = case rvalue
|
102
|
+
when BigMoney then rvalue.amount
|
103
|
+
when BigDecimal then rvalue.dup
|
104
|
+
when String then BigDecimal.new(rvalue)
|
105
|
+
when Numeric then BigDecimal.new(rvalue.to_s)
|
106
|
+
else raise TypeError.new("Can't convert +amount+ #{rvalue.class} into BigDecimal.")
|
107
|
+
end
|
108
|
+
self.class.new(amount.send(op, rvalue), currency)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def to_s(format = nil)
|
113
|
+
format ||= "%.#{currency.offset}f"
|
114
|
+
format.sub(/%s/, currency.code) % amount
|
115
|
+
end
|
116
|
+
|
117
|
+
def to_i
|
118
|
+
amount.to_i
|
119
|
+
end
|
120
|
+
|
121
|
+
def to_f
|
122
|
+
amount.to_f
|
123
|
+
end
|
124
|
+
end # BigMoney
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
class BigMoney
|
4
|
+
class Currency
|
5
|
+
include Comparable
|
6
|
+
|
7
|
+
attr_accessor :code, :offset, :name
|
8
|
+
alias to_s code
|
9
|
+
|
10
|
+
def hash
|
11
|
+
code.hash
|
12
|
+
end
|
13
|
+
|
14
|
+
def eql?(rvalue)
|
15
|
+
self.class.equal?(rvalue.class) && code == rvalue.code
|
16
|
+
end
|
17
|
+
alias == eql?
|
18
|
+
|
19
|
+
def <=>(rvalue)
|
20
|
+
self.class == rvalue.class ? (code <=> rvalue.code) || 0 : nil
|
21
|
+
end
|
22
|
+
|
23
|
+
#--
|
24
|
+
# TODO: Validate.
|
25
|
+
def initialize(code, offset, name)
|
26
|
+
@code, @offset, @name = code.to_s.upcase, offset, name
|
27
|
+
end
|
28
|
+
|
29
|
+
class << self
|
30
|
+
def default
|
31
|
+
raise "No default currency has been set. See BigMoney::Currency." unless default?
|
32
|
+
@@default
|
33
|
+
end
|
34
|
+
|
35
|
+
def default=(currency)
|
36
|
+
raise TypeError.new("Expected kind of BigMoney::Currency but got #{currency.class}.") \
|
37
|
+
unless currency.kind_of?(Currency)
|
38
|
+
@@default = currency
|
39
|
+
end
|
40
|
+
|
41
|
+
def default?
|
42
|
+
defined? @@default
|
43
|
+
end
|
44
|
+
|
45
|
+
def all
|
46
|
+
@@all ||= Set.new
|
47
|
+
end
|
48
|
+
|
49
|
+
# Find an existing currency module by Object, Symbol or String.
|
50
|
+
#
|
51
|
+
# ==== Examples
|
52
|
+
#
|
53
|
+
# AUD = BigMoney::Currency.new(:aud, 2, 'Australian Dollar')
|
54
|
+
#
|
55
|
+
# BigMoney::Currency.find(:aud)
|
56
|
+
# BigMoney::Currency.find('aud')
|
57
|
+
# BigMoney::Currency.find('AUD')
|
58
|
+
# BigMoney::Currency.find(AUD)
|
59
|
+
def find(currency)
|
60
|
+
if currency.is_a?(self)
|
61
|
+
currency
|
62
|
+
else
|
63
|
+
currency = currency.to_s.upcase
|
64
|
+
all.find{|c| c.code == currency}
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def register(*args)
|
69
|
+
self.all << currency = new(*args).freeze
|
70
|
+
currency
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end # Currency
|
74
|
+
end # BigMoney
|
75
|
+
|
@@ -0,0 +1,185 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
class BigMoney
|
4
|
+
class Currency
|
5
|
+
AED = Currency.register(%q{AED}, 2, %q{United Arab Emirates dirham})
|
6
|
+
AFN = Currency.register(%q{AFN}, 2, %q{Afghani})
|
7
|
+
ALL = Currency.register(%q{ALL}, 2, %q{Lek})
|
8
|
+
AMD = Currency.register(%q{AMD}, 0, %q{Armenian dram})
|
9
|
+
ANG = Currency.register(%q{ANG}, 2, %q{Netherlands Antillean guilder})
|
10
|
+
AOA = Currency.register(%q{AOA}, 1, %q{Kwanza})
|
11
|
+
ARS = Currency.register(%q{ARS}, 2, %q{Argentine peso})
|
12
|
+
AUD = Currency.register(%q{AUD}, 2, %q{Australian dollar})
|
13
|
+
AWG = Currency.register(%q{AWG}, 2, %q{Aruban guilder})
|
14
|
+
AZN = Currency.register(%q{AZN}, 2, %q{Azerbaijanian manat})
|
15
|
+
BAM = Currency.register(%q{BAM}, 2, %q{Convertible marks})
|
16
|
+
BBD = Currency.register(%q{BBD}, 2, %q{Barbados dollar})
|
17
|
+
BDT = Currency.register(%q{BDT}, 2, %q{Bangladeshi taka})
|
18
|
+
BGN = Currency.register(%q{BGN}, 2, %q{Bulgarian lev})
|
19
|
+
BHD = Currency.register(%q{BHD}, 3, %q{Bahraini dinar})
|
20
|
+
BIF = Currency.register(%q{BIF}, 0, %q{Burundian franc})
|
21
|
+
BMD = Currency.register(%q{BMD}, 2, %q{Bermudian dollar})
|
22
|
+
BND = Currency.register(%q{BND}, 2, %q{Brunei dollar})
|
23
|
+
BOB = Currency.register(%q{BOB}, 2, %q{Boliviano})
|
24
|
+
BOV = Currency.register(%q{BOV}, 2, %q{Bolivian Mvdol (funds code)})
|
25
|
+
BRL = Currency.register(%q{BRL}, 2, %q{Brazilian real})
|
26
|
+
BSD = Currency.register(%q{BSD}, 2, %q{Bahamian dollar})
|
27
|
+
BTN = Currency.register(%q{BTN}, 2, %q{Ngultrum})
|
28
|
+
BWP = Currency.register(%q{BWP}, 2, %q{Pula})
|
29
|
+
BYR = Currency.register(%q{BYR}, 0, %q{Belarusian ruble})
|
30
|
+
BZD = Currency.register(%q{BZD}, 2, %q{Belize dollar})
|
31
|
+
CAD = Currency.register(%q{CAD}, 2, %q{Canadian dollar})
|
32
|
+
CDF = Currency.register(%q{CDF}, 2, %q{Franc Congolais})
|
33
|
+
CHE = Currency.register(%q{CHE}, 2, %q{WIR eurocomplementary currency})
|
34
|
+
CHF = Currency.register(%q{CHF}, 2, %q{Swiss franc})
|
35
|
+
CHW = Currency.register(%q{CHW}, 2, %q{WIR franccomplementary currency})
|
36
|
+
CLF = Currency.register(%q{CLF}, 0, %q{Unidad de Fomento})
|
37
|
+
CLP = Currency.register(%q{CLP}, 0, %q{Chilean peso})
|
38
|
+
CNY = Currency.register(%q{CNY}, 1, %q{Chinese Yuan})
|
39
|
+
COP = Currency.register(%q{COP}, 0, %q{Colombian peso})
|
40
|
+
COU = Currency.register(%q{COU}, 2, %q{Unidad de Valor Real})
|
41
|
+
CRC = Currency.register(%q{CRC}, 2, %q{Costa Rican colon})
|
42
|
+
CUC = Currency.register(%q{CUC}, 2, %q{Cuban convertible peso})
|
43
|
+
CUP = Currency.register(%q{CUP}, 2, %q{Cuban peso})
|
44
|
+
CVE = Currency.register(%q{CVE}, 2, %q{Cape Verde escudo})
|
45
|
+
CZK = Currency.register(%q{CZK}, 2, %q{Czech Koruna})
|
46
|
+
DJF = Currency.register(%q{DJF}, 0, %q{Djibouti franc})
|
47
|
+
DKK = Currency.register(%q{DKK}, 2, %q{Danish krone})
|
48
|
+
DOP = Currency.register(%q{DOP}, 2, %q{Dominican peso})
|
49
|
+
DZD = Currency.register(%q{DZD}, 2, %q{Algerian dinar})
|
50
|
+
EEK = Currency.register(%q{EEK}, 2, %q{Kroon})
|
51
|
+
EGP = Currency.register(%q{EGP}, 2, %q{Egyptian pound})
|
52
|
+
ERN = Currency.register(%q{ERN}, 2, %q{Nakfa})
|
53
|
+
ETB = Currency.register(%q{ETB}, 2, %q{Ethiopian birr})
|
54
|
+
EUR = Currency.register(%q{EUR}, 2, %q{euro})
|
55
|
+
FJD = Currency.register(%q{FJD}, 2, %q{Fiji dollar})
|
56
|
+
FKP = Currency.register(%q{FKP}, 2, %q{Falkland Islands pound})
|
57
|
+
GBP = Currency.register(%q{GBP}, 2, %q{Pound sterling})
|
58
|
+
GEL = Currency.register(%q{GEL}, 2, %q{Lari})
|
59
|
+
GHS = Currency.register(%q{GHS}, 2, %q{Cedi})
|
60
|
+
GIP = Currency.register(%q{GIP}, 2, %q{Gibraltar pound})
|
61
|
+
GMD = Currency.register(%q{GMD}, 2, %q{Dalasi})
|
62
|
+
GNF = Currency.register(%q{GNF}, 0, %q{Guinea franc})
|
63
|
+
GTQ = Currency.register(%q{GTQ}, 2, %q{Quetzal})
|
64
|
+
GYD = Currency.register(%q{GYD}, 2, %q{Guyana dollar})
|
65
|
+
HKD = Currency.register(%q{HKD}, 2, %q{Hong Kong dollar})
|
66
|
+
HNL = Currency.register(%q{HNL}, 2, %q{Lempira})
|
67
|
+
HRK = Currency.register(%q{HRK}, 2, %q{Croatian kuna})
|
68
|
+
HTG = Currency.register(%q{HTG}, 2, %q{Haiti gourde})
|
69
|
+
HUF = Currency.register(%q{HUF}, 2, %q{Forint})
|
70
|
+
IDR = Currency.register(%q{IDR}, 0, %q{Rupiah})
|
71
|
+
ILS = Currency.register(%q{ILS}, 2, %q{Israeli new sheqel})
|
72
|
+
INR = Currency.register(%q{INR}, 2, %q{Indian rupee})
|
73
|
+
IQD = Currency.register(%q{IQD}, 0, %q{Iraqi dinar})
|
74
|
+
IRR = Currency.register(%q{IRR}, 0, %q{Iranian rial})
|
75
|
+
ISK = Currency.register(%q{ISK}, 0, %q{Iceland krona})
|
76
|
+
JMD = Currency.register(%q{JMD}, 2, %q{Jamaican dollar})
|
77
|
+
JOD = Currency.register(%q{JOD}, 3, %q{Jordanian dinar})
|
78
|
+
JPY = Currency.register(%q{JPY}, 0, %q{Japanese yen})
|
79
|
+
KES = Currency.register(%q{KES}, 2, %q{Kenyan shilling})
|
80
|
+
KGS = Currency.register(%q{KGS}, 2, %q{Som})
|
81
|
+
KHR = Currency.register(%q{KHR}, 0, %q{Riel})
|
82
|
+
KMF = Currency.register(%q{KMF}, 0, %q{Comoro franc})
|
83
|
+
KPW = Currency.register(%q{KPW}, 0, %q{North Korean won})
|
84
|
+
KRW = Currency.register(%q{KRW}, 0, %q{South Korean won})
|
85
|
+
KWD = Currency.register(%q{KWD}, 3, %q{Kuwaiti dinar})
|
86
|
+
KYD = Currency.register(%q{KYD}, 2, %q{Cayman Islands dollar})
|
87
|
+
KZT = Currency.register(%q{KZT}, 2, %q{Tenge})
|
88
|
+
LAK = Currency.register(%q{LAK}, 0, %q{Kip})
|
89
|
+
LBP = Currency.register(%q{LBP}, 0, %q{Lebanese pound})
|
90
|
+
LKR = Currency.register(%q{LKR}, 2, %q{Sri Lanka rupee})
|
91
|
+
LRD = Currency.register(%q{LRD}, 2, %q{Liberian dollar})
|
92
|
+
LSL = Currency.register(%q{LSL}, 2, %q{Lesotho loti})
|
93
|
+
LTL = Currency.register(%q{LTL}, 2, %q{Lithuanian litas})
|
94
|
+
LVL = Currency.register(%q{LVL}, 2, %q{Latvian lats})
|
95
|
+
LYD = Currency.register(%q{LYD}, 3, %q{Libyan dinar})
|
96
|
+
MAD = Currency.register(%q{MAD}, 2, %q{Moroccan dirham})
|
97
|
+
MDL = Currency.register(%q{MDL}, 2, %q{Moldovan leu})
|
98
|
+
MGA = Currency.register(%q{MGA}, 0, %q{Malagasy ariary})
|
99
|
+
MKD = Currency.register(%q{MKD}, 2, %q{Denar})
|
100
|
+
MMK = Currency.register(%q{MMK}, 0, %q{Kyat})
|
101
|
+
MNT = Currency.register(%q{MNT}, 2, %q{Tugrik})
|
102
|
+
MOP = Currency.register(%q{MOP}, 1, %q{Pataca})
|
103
|
+
MRO = Currency.register(%q{MRO}, 0, %q{Ouguiya})
|
104
|
+
MUR = Currency.register(%q{MUR}, 2, %q{Mauritius rupee})
|
105
|
+
MVR = Currency.register(%q{MVR}, 2, %q{Rufiyaa})
|
106
|
+
MWK = Currency.register(%q{MWK}, 2, %q{Kwacha})
|
107
|
+
MXN = Currency.register(%q{MXN}, 2, %q{Mexican peso})
|
108
|
+
MXV = Currency.register(%q{MXV}, 2, %q{Mexican Unidad de Inversion})
|
109
|
+
MYR = Currency.register(%q{MYR}, 2, %q{Malaysian ringgit})
|
110
|
+
MZN = Currency.register(%q{MZN}, 2, %q{Metical})
|
111
|
+
NAD = Currency.register(%q{NAD}, 2, %q{Namibian dollar})
|
112
|
+
NGN = Currency.register(%q{NGN}, 2, %q{Naira})
|
113
|
+
NIO = Currency.register(%q{NIO}, 2, %q{Cordoba oro})
|
114
|
+
NOK = Currency.register(%q{NOK}, 2, %q{Norwegian krone})
|
115
|
+
NPR = Currency.register(%q{NPR}, 2, %q{Nepalese rupee})
|
116
|
+
NZD = Currency.register(%q{NZD}, 2, %q{New Zealand dollar})
|
117
|
+
OMR = Currency.register(%q{OMR}, 3, %q{Rial Omani})
|
118
|
+
PAB = Currency.register(%q{PAB}, 2, %q{Balboa})
|
119
|
+
PEN = Currency.register(%q{PEN}, 2, %q{Nuevo sol})
|
120
|
+
PGK = Currency.register(%q{PGK}, 2, %q{Kina})
|
121
|
+
PHP = Currency.register(%q{PHP}, 2, %q{Philippine peso})
|
122
|
+
PKR = Currency.register(%q{PKR}, 2, %q{Pakistan rupee})
|
123
|
+
PLN = Currency.register(%q{PLN}, 2, %q{Złoty})
|
124
|
+
PYG = Currency.register(%q{PYG}, 0, %q{Guarani})
|
125
|
+
QAR = Currency.register(%q{QAR}, 2, %q{Qatari rial})
|
126
|
+
RON = Currency.register(%q{RON}, 2, %q{Romanian new leu})
|
127
|
+
RSD = Currency.register(%q{RSD}, 2, %q{Serbian dinar})
|
128
|
+
RUB = Currency.register(%q{RUB}, 2, %q{Russian rouble})
|
129
|
+
RWF = Currency.register(%q{RWF}, 0, %q{Rwanda franc})
|
130
|
+
SAR = Currency.register(%q{SAR}, 2, %q{Saudi riyal})
|
131
|
+
SBD = Currency.register(%q{SBD}, 2, %q{Solomon Islands dollar})
|
132
|
+
SCR = Currency.register(%q{SCR}, 2, %q{Seychelles rupee})
|
133
|
+
SDG = Currency.register(%q{SDG}, 2, %q{Sudanese pound})
|
134
|
+
SEK = Currency.register(%q{SEK}, 2, %q{Swedish krona})
|
135
|
+
SGD = Currency.register(%q{SGD}, 2, %q{Singapore dollar})
|
136
|
+
SHP = Currency.register(%q{SHP}, 2, %q{Saint Helena pound})
|
137
|
+
SLL = Currency.register(%q{SLL}, 0, %q{Leone})
|
138
|
+
SOS = Currency.register(%q{SOS}, 2, %q{Somali shilling})
|
139
|
+
SRD = Currency.register(%q{SRD}, 2, %q{Surinam dollar})
|
140
|
+
STD = Currency.register(%q{STD}, 0, %q{Dobra})
|
141
|
+
SYP = Currency.register(%q{SYP}, 2, %q{Syrian pound})
|
142
|
+
SZL = Currency.register(%q{SZL}, 2, %q{Lilangeni})
|
143
|
+
THB = Currency.register(%q{THB}, 2, %q{Baht})
|
144
|
+
TJS = Currency.register(%q{TJS}, 2, %q{Somoni})
|
145
|
+
TMT = Currency.register(%q{TMT}, 2, %q{Manat})
|
146
|
+
TND = Currency.register(%q{TND}, 3, %q{Tunisian dinar})
|
147
|
+
TOP = Currency.register(%q{TOP}, 2, %q{Pa'anga})
|
148
|
+
TRY = Currency.register(%q{TRY}, 2, %q{Turkish lira})
|
149
|
+
TTD = Currency.register(%q{TTD}, 2, %q{Trinidad and Tobago dollar})
|
150
|
+
TWD = Currency.register(%q{TWD}, 1, %q{New Taiwan dollar})
|
151
|
+
TZS = Currency.register(%q{TZS}, 2, %q{Tanzanian shilling})
|
152
|
+
UAH = Currency.register(%q{UAH}, 2, %q{Hryvnia})
|
153
|
+
UGX = Currency.register(%q{UGX}, 0, %q{Uganda shilling})
|
154
|
+
USD = Currency.register(%q{USD}, 2, %q{US dollar})
|
155
|
+
USN = Currency.register(%q{USN}, 2, %q{United States dollar (next day) (funds code)})
|
156
|
+
USS = Currency.register(%q{USS}, 2, %q{who?})
|
157
|
+
UYU = Currency.register(%q{UYU}, 2, %q{Peso Uruguayo})
|
158
|
+
UZS = Currency.register(%q{UZS}, 2, %q{Uzbekistan som})
|
159
|
+
VEF = Currency.register(%q{VEF}, 2, %q{Venezuelan bolívar fuerte})
|
160
|
+
VND = Currency.register(%q{VND}, 0, %q{Vietnamese đồng})
|
161
|
+
VUV = Currency.register(%q{VUV}, 0, %q{Vatu})
|
162
|
+
WST = Currency.register(%q{WST}, 2, %q{Samoan tala})
|
163
|
+
XAF = Currency.register(%q{XAF}, 0, %q{CFA franc BEAC})
|
164
|
+
XAG = Currency.register(%q{XAG}, 0, %q{Silvertroy ounce})
|
165
|
+
XAU = Currency.register(%q{XAU}, 0, %q{Goldtroy ounce})
|
166
|
+
XBA = Currency.register(%q{XBA}, 0, %q{European Composite Unit})
|
167
|
+
XBB = Currency.register(%q{XBB}, 0, %q{European Monetary Unit})
|
168
|
+
XBC = Currency.register(%q{XBC}, 0, %q{European Unit of Account 9})
|
169
|
+
XBD = Currency.register(%q{XBD}, 0, %q{European Unit of Account 17})
|
170
|
+
XCD = Currency.register(%q{XCD}, 2, %q{East Caribbean dollar})
|
171
|
+
XDR = Currency.register(%q{XDR}, 0, %q{Special Drawing Rights})
|
172
|
+
XFU = Currency.register(%q{XFU}, 0, %q{UIC franc})
|
173
|
+
XOF = Currency.register(%q{XOF}, 0, %q{CFA Franc BCEAO})
|
174
|
+
XPD = Currency.register(%q{XPD}, 0, %q{Palladiumtroy ounce})
|
175
|
+
XPF = Currency.register(%q{XPF}, 0, %q{CFP franc})
|
176
|
+
XPT = Currency.register(%q{XPT}, 0, %q{Platinumtroy ounce})
|
177
|
+
XTS = Currency.register(%q{XTS}, 0, %q{Code reserved for testing purposes})
|
178
|
+
XXX = Currency.register(%q{XXX}, 0, %q{No currency})
|
179
|
+
YER = Currency.register(%q{YER}, 0, %q{Yemeni rial})
|
180
|
+
ZAR = Currency.register(%q{ZAR}, 2, %q{South African rand})
|
181
|
+
ZMK = Currency.register(%q{ZMK}, 0, %q{Kwacha})
|
182
|
+
ZWL = Currency.register(%q{ZWL}, 2, %q{Zimbabwe dollar})
|
183
|
+
end # Currency
|
184
|
+
end # BigMoney
|
185
|
+
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'bigdecimal'
|
3
|
+
|
4
|
+
class BigMoney
|
5
|
+
|
6
|
+
# == Synopsis
|
7
|
+
#
|
8
|
+
# require 'big_money'
|
9
|
+
# require 'big_money/exchange/yahoo' # Use yahoo finance exchange service.
|
10
|
+
#
|
11
|
+
# bm = BigMoney.new('3.99', :usd)
|
12
|
+
# bm.amount #=> BigDecimal.new('3.99')
|
13
|
+
# bm.currency #=> BigMoney::Currency::USD
|
14
|
+
#
|
15
|
+
# bm2 = bm.exchange(:aud)
|
16
|
+
# bm.amount #=> BigDecimal.new('5.22')
|
17
|
+
# bm.currency #=> BigMoney::Currency::AUD
|
18
|
+
module Exchangeable
|
19
|
+
# Exchange to a new Currency.
|
20
|
+
#
|
21
|
+
# ==== Examples
|
22
|
+
#
|
23
|
+
# BigMoney.new(12.50, :aud).exchange(:usd)
|
24
|
+
#
|
25
|
+
# ==== Parameters
|
26
|
+
# from<BigMoney::Currency, #to_s>:: Anything that BigMoney::Currency#find can find.
|
27
|
+
#
|
28
|
+
# ==== Returns
|
29
|
+
# BigMoney
|
30
|
+
def exchange(to)
|
31
|
+
ex = amount * Exchange.rate(currency, to)
|
32
|
+
self.class.new(ex, to)
|
33
|
+
end
|
34
|
+
end # Exchangeable
|
35
|
+
include Exchangeable
|
36
|
+
|
37
|
+
# Find the exchange rate between two currencies.
|
38
|
+
#
|
39
|
+
# Be aware no caching is done at all at the moment.
|
40
|
+
#--
|
41
|
+
# TODO: Moneta would be ideal for this.
|
42
|
+
class Exchange
|
43
|
+
class ConversionError < StandardError; end
|
44
|
+
|
45
|
+
class << self
|
46
|
+
@@services = []
|
47
|
+
def inherited(service) #:nodoc:
|
48
|
+
@@services << service
|
49
|
+
end
|
50
|
+
|
51
|
+
# Fetch the exchange rate between two currencies.
|
52
|
+
#
|
53
|
+
# ==== Parameters
|
54
|
+
# from<BigMoney::Currency, .to_s>:: Anything that BigMoney::Currency#find can find.
|
55
|
+
# to<BigMoney::Currency, .to_s>:: Anything that BigMoney::Currency#find can find.
|
56
|
+
#
|
57
|
+
# ==== Returns
|
58
|
+
# BigDecimal
|
59
|
+
def rate(from, to)
|
60
|
+
exchange = []
|
61
|
+
exchange << (Currency.find(from) or raise ArgumentError.new("Unknown +from+ currency #{from.inspect}."))
|
62
|
+
exchange << (Currency.find(to) or raise ArgumentError.new("Unknown +to+ currency #{to.inspect}."))
|
63
|
+
return BigDecimal.new(1.to_s) if exchange.uniq.size == 1 || exchange.find{|c| c == Currency::XXX}
|
64
|
+
|
65
|
+
service = @@services.reverse.find do |service|
|
66
|
+
!!exchange.reject{|c| service.currencies.include?(c)}
|
67
|
+
end
|
68
|
+
|
69
|
+
service or raise ConversionError # TODO: Message?
|
70
|
+
BigDecimal.new(service.read_rate(*exchange).to_s)
|
71
|
+
end
|
72
|
+
|
73
|
+
protected
|
74
|
+
# Exchange rate from the first currency to the second.
|
75
|
+
#
|
76
|
+
# ==== Notes
|
77
|
+
# Abstract.
|
78
|
+
#
|
79
|
+
# ==== Parameters
|
80
|
+
# from<BigMoney::Currency>::
|
81
|
+
# to<BigMoney::Currency>::
|
82
|
+
#
|
83
|
+
# ==== Returns
|
84
|
+
# BigDecimal
|
85
|
+
def read_rate(from, to)
|
86
|
+
raise NotImplementedError
|
87
|
+
end
|
88
|
+
|
89
|
+
# Supported currencies.
|
90
|
+
#
|
91
|
+
# ==== Notes
|
92
|
+
# Abstract.
|
93
|
+
#
|
94
|
+
# ==== Returns
|
95
|
+
# Array<BigMoney::Currency, #to_s>:: Anything that BigMoney::Currency#find can find.
|
96
|
+
def currencies
|
97
|
+
raise NotImplementedError
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end # Exchange
|
101
|
+
|
102
|
+
end # Money
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require 'open-uri'
|
3
|
+
require 'big_money/exchange'
|
4
|
+
|
5
|
+
class BigMoney
|
6
|
+
class Exchange
|
7
|
+
|
8
|
+
# Yahoo finance exchange service.
|
9
|
+
#
|
10
|
+
# http://finance.yahoo.com
|
11
|
+
class Yahoo < Exchange
|
12
|
+
class << self
|
13
|
+
protected
|
14
|
+
def read_rate(from, to)
|
15
|
+
s = [from, to].map{|c| c.code}.join
|
16
|
+
open("http://download.finance.yahoo.com/d/quotes.csv?s=#{s}=X&f=l1&e=.csv").read.strip rescue nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def currencies
|
20
|
+
%w{
|
21
|
+
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
|
22
|
+
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
|
23
|
+
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
|
24
|
+
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
|
25
|
+
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
|
26
|
+
CHF SYP TWD TZS THB TOP TTD TND USD AED UGX UAH UYU VUV VEB VND YER ZMK ZWD
|
27
|
+
}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end # Yahoo
|
31
|
+
|
32
|
+
end # Exchange
|
33
|
+
end # Money
|
34
|
+
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'big_money' # Make it possible to just require 'big_money/parser'.
|
3
|
+
|
4
|
+
class BigMoney
|
5
|
+
# Fuzzy string parsing.
|
6
|
+
#
|
7
|
+
# Supports scientific notation for amounts and ISO-4217 currency symbols.
|
8
|
+
#
|
9
|
+
# == Synopsis
|
10
|
+
#
|
11
|
+
# require 'big_money'
|
12
|
+
# require 'big_money/parser' # This module/mixin.
|
13
|
+
#
|
14
|
+
# BigMoney.parse('JPY ¥2500') #=> BigMoney.new('2500', :jpy)
|
15
|
+
# BigMoney.parse('JPY2500') #=> BigMoney.new('2500', :jpy)
|
16
|
+
# BigMoney.parse('2500JPY') #=> BigMoney.new('2500', :jpy)
|
17
|
+
# BigMoney.parse('¥2500JPY') #=> BigMoney.new('2500', :jpy)
|
18
|
+
# BigMoney.parse('¥2500') #=> BigMoney.new('2500', :xxx)
|
19
|
+
#
|
20
|
+
# == Currency
|
21
|
+
#
|
22
|
+
# Due to the nature of string parsing it's possible t
|
23
|
+
module Parser
|
24
|
+
REGEXP = %r{
|
25
|
+
(?:^|\b)
|
26
|
+
((?:[a-zA-Z]{3})?)\s* # ISO4217 Currency code.
|
27
|
+
[^\d+-]? # Currency symbol.
|
28
|
+
([-+]?) # +-
|
29
|
+
[^\d+-]? # Currency symbol.
|
30
|
+
\s*(
|
31
|
+
(?:(?:\d(?:\d+|[., ]?)*\d)|\d) # Digits and ., or spaces.
|
32
|
+
(?:[eE][-+]?\d+)? # Exponents.
|
33
|
+
)\s*
|
34
|
+
((?:[a-zA-Z]{3})?) # ISO4217 Currency code.
|
35
|
+
(?:$|\b)
|
36
|
+
}x
|
37
|
+
|
38
|
+
# Fuzzy parsing.
|
39
|
+
#
|
40
|
+
# ==== Parameters
|
41
|
+
# money<.to_s>:: The object to parse as money.
|
42
|
+
#
|
43
|
+
# ==== Currency
|
44
|
+
# ISO-4217 BigMoney::Currency::XXX aka 'No currency' will be used if a currency cannot be parsed along with the
|
45
|
+
# amount. If you know the currency and just need the amount XXX is always exchanged 1:1 with any currency:
|
46
|
+
#
|
47
|
+
# money = BigMoney.parse('¥2500') #=> BigMoney.new('2500', :xxx)
|
48
|
+
# money.exchange(:jpy) #=> BigMoney.new('2500', :jpy)
|
49
|
+
#
|
50
|
+
# ==== Returns
|
51
|
+
# BigMoney or nil
|
52
|
+
def parse(money)
|
53
|
+
raise TypeError.new("Can't convert +money+ #{money.class} into String.") unless money.respond_to?(:to_s)
|
54
|
+
|
55
|
+
match = REGEXP.match(money.to_s) || return
|
56
|
+
currency = [match[1], match[4]].find{|c| Currency.find(c)} || Currency::XXX
|
57
|
+
|
58
|
+
# TODO: Currency should have a .delimiter method I reckon that returns the major/minor delimiter.
|
59
|
+
# For now '.' will do and everything else will be stripped.
|
60
|
+
money = [match[2], match[3].gsub(/[^0-9.Ee]/, '')].join
|
61
|
+
new(money, currency)
|
62
|
+
end
|
63
|
+
end # Parser
|
64
|
+
|
65
|
+
extend Parser
|
66
|
+
end # BigMoney
|
data/rakelib/iso4217.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.join(File.dirname(__FILE__), '..', 'gems', 'environment')
|
3
|
+
require 'hpricot'
|
4
|
+
require 'open-uri'
|
5
|
+
require 'erubis'
|
6
|
+
|
7
|
+
class BigMoney
|
8
|
+
module Task
|
9
|
+
module ISO4217
|
10
|
+
def self.get
|
11
|
+
doc = Hpricot(open('http://en.wikipedia.org/wiki/ISO_4217').read)
|
12
|
+
codes = doc.at('#Active_codes').parent
|
13
|
+
codes.name =~ /table/ && break while codes = codes.next_sibling
|
14
|
+
to_ruby(codes) if codes
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.to_ruby(codes)
|
18
|
+
currencies = (codes / 'tr').map{|tr| currency tr}.compact
|
19
|
+
currencies.reject!{|c| c[:code] !~ /[A-Z]{3}/ || c[:name] !~ /\w+/}
|
20
|
+
tmpl = File.read(File.join(File.dirname(__FILE__), 'iso4217.rb.erb'))
|
21
|
+
eruby = Erubis::Eruby.new(tmpl)
|
22
|
+
eruby.result(:currencies => currencies)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.currency(tr)
|
26
|
+
values = (tr / 'td')
|
27
|
+
return unless values && values.size >= 4
|
28
|
+
{
|
29
|
+
:code => code(values),
|
30
|
+
:name => name(values),
|
31
|
+
:offset => offset(values)
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.code(chunks)
|
36
|
+
chunks[0].inner_html
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.offset(chunks)
|
40
|
+
chunks[2].inner_html.to_i rescue 0
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.name(chunks)
|
44
|
+
name = (chunks[3] / 'a').inner_html rescue nil
|
45
|
+
(name.nil? || name.empty?) ? chunks[3].inner_html : name
|
46
|
+
end
|
47
|
+
end # ISO4217
|
48
|
+
end # Task
|
49
|
+
end # BigMoney
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
class BigMoney
|
4
|
+
class Currency
|
5
|
+
<% currencies.each do |currency| -%>
|
6
|
+
<%= currency[:code].upcase %> = Currency.register(%q{<%= currency[:code] %>}, <%= currency[:offset] %>, %q{<%= currency[:name] %>})
|
7
|
+
<% end -%>
|
8
|
+
end # Currency
|
9
|
+
end # BigMoney
|
10
|
+
|
data/test/helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
2
|
+
|
3
|
+
require File.join(root, 'gems', 'environment')
|
4
|
+
Bundler.require_env(:development)
|
5
|
+
require 'test/unit'
|
6
|
+
|
7
|
+
begin
|
8
|
+
require 'shoulda'
|
9
|
+
rescue LoadError
|
10
|
+
warn 'Shoulda is required for testing. Use gem bundle to install development gems.'
|
11
|
+
exit 1
|
12
|
+
end
|
13
|
+
|
14
|
+
$:.unshift File.join(root, 'lib'), File.dirname(__FILE__)
|
15
|
+
require 'big_money'
|
16
|
+
|
17
|
+
class Test::Unit::TestCase
|
18
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
|
3
|
+
|
4
|
+
class TestBigMoney < Test::Unit::TestCase
|
5
|
+
context BigMoney do
|
6
|
+
setup do
|
7
|
+
BigMoney::Currency.default = BigMoney::Currency::USD
|
8
|
+
end
|
9
|
+
|
10
|
+
context '#new' do
|
11
|
+
should 'initialize with big decimal' do
|
12
|
+
decimal = BigDecimal.new('1.005')
|
13
|
+
assert_same decimal, BigMoney.new(decimal).amount, 'Should not create clone of input'
|
14
|
+
end
|
15
|
+
|
16
|
+
should 'initialize with string' do
|
17
|
+
assert_equal BigDecimal.new('1.005'), BigMoney.new('1.005').amount
|
18
|
+
assert_equal BigDecimal.new('10'), BigMoney.new('10').amount
|
19
|
+
assert_equal BigDecimal.new('0'), BigMoney.new('0').amount
|
20
|
+
assert_equal BigDecimal.new('0'), BigMoney.new('foo').amount
|
21
|
+
end
|
22
|
+
|
23
|
+
should 'initialize with integer' do
|
24
|
+
assert_equal BigDecimal.new("100"), BigMoney.new(100).amount
|
25
|
+
assert_equal BigDecimal.new("0"), BigMoney.new(0).amount
|
26
|
+
end
|
27
|
+
|
28
|
+
should 'initialize with float' do
|
29
|
+
assert_equal BigDecimal.new('1.005'), BigMoney.new(1.005).amount
|
30
|
+
assert_equal BigDecimal.new('0'), BigMoney.new(0.0).amount
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'operators' do
|
35
|
+
should 'eql?' do
|
36
|
+
m1, m2 = BigMoney.new(1.00), BigMoney.new(1.50)
|
37
|
+
assert m1.eql?(m1)
|
38
|
+
assert !m1.eql?(m2)
|
39
|
+
end
|
40
|
+
|
41
|
+
should '<=> spaceship' do
|
42
|
+
m1, m2 = BigMoney.new(1.00), BigMoney.new(1.50)
|
43
|
+
assert_equal(-1, (m1 <=> m2))
|
44
|
+
assert_equal(0, (m1 <=> m1))
|
45
|
+
assert_equal(1, (m2 <=> m1))
|
46
|
+
end
|
47
|
+
|
48
|
+
should 'add' do
|
49
|
+
m1, m2, m3 = BigMoney.new(1.00), BigMoney.new(1.50), BigMoney.new(0)
|
50
|
+
assert_equal BigDecimal.new('2.50'), (m1 + m2).amount
|
51
|
+
assert_equal BigDecimal.new('2.50'), (m2 + m1).amount
|
52
|
+
assert_equal BigDecimal.new('1.00'), (m1 + m3).amount
|
53
|
+
assert_equal BigDecimal.new('1.00'), (m3 + m1).amount
|
54
|
+
assert_not_same m1, m1 + m3
|
55
|
+
assert_not_same m1, m3 + m1
|
56
|
+
assert_equal BigDecimal.new('5.50'), (m2 + 4).amount
|
57
|
+
assert_equal BigDecimal.new('5.50'), (m2 + 4.00).amount
|
58
|
+
end
|
59
|
+
|
60
|
+
should 'subtract' do
|
61
|
+
m1, m2, m3 = BigMoney.new(1.00), BigMoney.new(1.50), BigMoney.new(0)
|
62
|
+
assert_equal BigDecimal.new('-0.50'), (m1 - m2).amount
|
63
|
+
assert_equal BigDecimal.new('0.50'), (m2 - m1).amount
|
64
|
+
assert_equal BigDecimal.new('1.00'), (m1 - m3).amount
|
65
|
+
assert_equal BigDecimal.new('-1.00'), (m3 - m1).amount
|
66
|
+
assert_equal BigDecimal.new('-2.50'), (m2 - 4).amount
|
67
|
+
assert_equal BigDecimal.new('-2.50'), (m2 - 4.00).amount
|
68
|
+
end
|
69
|
+
|
70
|
+
should 'multiply' do
|
71
|
+
m1, m2, m3 = BigMoney.new(2.00), BigMoney.new(1.50), BigMoney.new(0)
|
72
|
+
assert_equal BigDecimal.new('4.00'), (m1 * m1).amount
|
73
|
+
assert_equal BigDecimal.new('3.00'), (m1 * m2).amount
|
74
|
+
assert_equal BigDecimal.new('3.00'), (m2 * m1).amount
|
75
|
+
assert_equal BigDecimal.new('0'), (m1 * m3).amount
|
76
|
+
assert_equal BigDecimal.new('0'), (m3 * m1).amount
|
77
|
+
assert_equal BigDecimal.new('0'), (m3 * m3).amount
|
78
|
+
assert_equal BigDecimal.new('3.00'), (m2 * 2).amount
|
79
|
+
assert_equal BigDecimal.new('3.00'), (m2 * 2.00).amount
|
80
|
+
end
|
81
|
+
|
82
|
+
should 'divide' do
|
83
|
+
m1, m2, m3 = BigMoney.new(2.00), BigMoney.new(1.50), BigMoney.new(0)
|
84
|
+
assert_equal BigDecimal.new('1.00'), (m1 / m1).amount
|
85
|
+
assert_equal BigDecimal.new('0.75'), (m2 / m1).amount
|
86
|
+
assert_equal BigDecimal.new('0'), (m3 / m1).amount
|
87
|
+
assert((m1 / m3).amount.infinite?)
|
88
|
+
assert((m3 / m3).amount.nan?)
|
89
|
+
assert((m1 / 0).amount.infinite?)
|
90
|
+
assert((m3 / 0).amount.nan?)
|
91
|
+
assert_equal BigDecimal.new('0.75'), (m2 / 2).amount
|
92
|
+
assert_equal BigDecimal.new('0.75'), (m2 / 2.00).amount
|
93
|
+
end
|
94
|
+
|
95
|
+
should 'negate' do
|
96
|
+
assert_equal BigMoney.new(-1), -BigMoney.new(1)
|
97
|
+
assert_equal BigMoney.new(1), -BigMoney.new(-1)
|
98
|
+
assert_equal BigMoney.new(1), -BigMoney.new(-1)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context 'serialization' do
|
103
|
+
should '.to_s' do
|
104
|
+
assert_equal '1.00', BigMoney.new(1).to_s
|
105
|
+
assert_equal '1.50', BigMoney.new(1.5).to_s
|
106
|
+
assert_equal '-11.50', BigMoney.new(-11.5).to_s
|
107
|
+
end
|
108
|
+
|
109
|
+
should 'formatted .to_s' do
|
110
|
+
assert_equal '1.00', BigMoney.new(1).to_s('%.2f')
|
111
|
+
assert_equal '$1.00', BigMoney.new(1).to_s('$%.2f')
|
112
|
+
end
|
113
|
+
|
114
|
+
should '.to_i' do
|
115
|
+
assert_equal(1, BigMoney.new(1).to_i)
|
116
|
+
assert_equal(1, BigMoney.new(1.5).to_i)
|
117
|
+
assert_equal(-11, BigMoney.new(-11.5).to_i)
|
118
|
+
end
|
119
|
+
|
120
|
+
should '.to_f' do
|
121
|
+
assert_in_delta(1.0, BigMoney.new(1).to_f, 0.000001)
|
122
|
+
assert_in_delta(1.5, BigMoney.new(1.5).to_f, 0.000001)
|
123
|
+
assert_in_delta(-11.5, BigMoney.new(-11.5).to_f, 0.000001)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
|
2
|
+
|
3
|
+
class TestCurrency < Test::Unit::TestCase
|
4
|
+
context BigMoney::Currency do
|
5
|
+
should 'find' do
|
6
|
+
assert_kind_of BigMoney::Currency, BigMoney::Currency.find(:aud)
|
7
|
+
assert_kind_of BigMoney::Currency, BigMoney::Currency.find(:AUD)
|
8
|
+
assert_kind_of BigMoney::Currency, BigMoney::Currency.find('aud')
|
9
|
+
assert_kind_of BigMoney::Currency, BigMoney::Currency.find('AUD')
|
10
|
+
assert_nil BigMoney::Currency.find(:fud)
|
11
|
+
end
|
12
|
+
|
13
|
+
should 'be comparable' do
|
14
|
+
aud = BigMoney::Currency::AUD
|
15
|
+
assert_operator aud, :==, BigMoney::Currency::AUD
|
16
|
+
assert aud != BigMoney::Currency::USD
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'default' do
|
20
|
+
should 'raise exception for bad type' do
|
21
|
+
assert_raise(TypeError) { BigMoney::Currency.default = :fud}
|
22
|
+
end
|
23
|
+
|
24
|
+
should 'be settable' do
|
25
|
+
assert_nothing_raised{ BigMoney::Currency.default = BigMoney::Currency::AUD}
|
26
|
+
assert_kind_of BigMoney::Currency, BigMoney::Currency.default
|
27
|
+
assert_equal BigMoney::Currency::AUD, BigMoney::Currency.default
|
28
|
+
end
|
29
|
+
|
30
|
+
should 'be ackowledged' do
|
31
|
+
BigMoney::Currency.default = BigMoney::Currency::AUD
|
32
|
+
assert BigMoney::Currency.default?
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
|
3
|
+
require 'big_money/exchange'
|
4
|
+
|
5
|
+
class TestEx < BigMoney::Exchange
|
6
|
+
def self.read_rate(from, to)
|
7
|
+
BigDecimal.new('2')
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.currencies
|
11
|
+
BigMoney::Currency.all
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class TestExchange < Test::Unit::TestCase
|
16
|
+
context BigMoney::Exchange do
|
17
|
+
setup do
|
18
|
+
@aud = BigMoney.currency(:aud)
|
19
|
+
@usd = BigMoney.currency(:usd)
|
20
|
+
end
|
21
|
+
|
22
|
+
should 'return rate' do
|
23
|
+
bd = BigDecimal.new('2')
|
24
|
+
assert_equal bd, BigMoney::Exchange.rate(@aud, @usd)
|
25
|
+
assert_equal bd, BigMoney::Exchange.rate(:aud, :usd)
|
26
|
+
assert_raise(ArgumentError) do
|
27
|
+
BigMoney::Exchange.rate(:aud, :fud)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
should 'return equal rate' do
|
32
|
+
assert_equal BigDecimal.new('1'), BigMoney::Exchange.rate(:usd, :usd)
|
33
|
+
assert_equal BigDecimal.new('1'), BigMoney::Exchange.rate(:usd, :xxx)
|
34
|
+
assert_equal BigDecimal.new('1'), BigMoney::Exchange.rate(:xxx, :usd)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/test/test_parser.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
|
3
|
+
require 'big_money/parser'
|
4
|
+
|
5
|
+
class TestParser < Test::Unit::TestCase
|
6
|
+
context BigMoney::Parser do
|
7
|
+
setup do
|
8
|
+
@xxx = BigMoney.new('1.50', :xxx)
|
9
|
+
@aud = BigMoney.new('1.50', :aud)
|
10
|
+
@jpy = BigMoney.new('1.50', :jpy)
|
11
|
+
end
|
12
|
+
|
13
|
+
should 'parse' do
|
14
|
+
assert_equal @xxx, BigMoney.parse('1.50')
|
15
|
+
end
|
16
|
+
|
17
|
+
should 'parse scientific notation' do
|
18
|
+
assert_equal @xxx, BigMoney.parse('0.15E1')
|
19
|
+
end
|
20
|
+
|
21
|
+
should 'parse with leading currency' do
|
22
|
+
assert_equal @aud, BigMoney.parse('AUD 1.50')
|
23
|
+
assert_equal @aud, BigMoney.parse('AUD1.50')
|
24
|
+
assert_equal @aud, BigMoney.parse('AUD 0.15E1')
|
25
|
+
assert_equal @aud, BigMoney.parse('AUD0.15E1')
|
26
|
+
|
27
|
+
assert_equal @jpy, BigMoney.parse('JPY 1.50')
|
28
|
+
assert_equal @jpy, BigMoney.parse('JPY1.50')
|
29
|
+
assert_equal @jpy, BigMoney.parse('JPY 0.15E1')
|
30
|
+
assert_equal @jpy, BigMoney.parse('JPY0.15E1')
|
31
|
+
end
|
32
|
+
|
33
|
+
should 'parse with trailing currency' do
|
34
|
+
assert_equal @aud, BigMoney.parse('1.50 AUD')
|
35
|
+
assert_equal @aud, BigMoney.parse('1.50AUD')
|
36
|
+
assert_equal @aud, BigMoney.parse('0.15E1 AUD')
|
37
|
+
assert_equal @aud, BigMoney.parse('0.15E1AUD')
|
38
|
+
|
39
|
+
assert_equal @jpy, BigMoney.parse('1.50 JPY')
|
40
|
+
assert_equal @jpy, BigMoney.parse('1.50JPY')
|
41
|
+
assert_equal @jpy, BigMoney.parse('0.15E1 JPY')
|
42
|
+
assert_equal @jpy, BigMoney.parse('0.15E1JPY')
|
43
|
+
end
|
44
|
+
|
45
|
+
should 'parse with currency symbols' do
|
46
|
+
assert_equal @xxx, BigMoney.parse('$1.50')
|
47
|
+
assert_equal @xxx, BigMoney.parse('¤1.50')
|
48
|
+
assert_equal @xxx, BigMoney.parse('¥1.50')
|
49
|
+
|
50
|
+
assert_equal @xxx, BigMoney.parse('$ 1.50')
|
51
|
+
assert_equal @xxx, BigMoney.parse('¤ 1.50')
|
52
|
+
assert_equal @xxx, BigMoney.parse('¥ 1.50')
|
53
|
+
end
|
54
|
+
|
55
|
+
should 'parse with currency and symbols' do
|
56
|
+
assert_equal @aud, BigMoney.parse('AUD ¤ 1.50')
|
57
|
+
assert_equal @aud, BigMoney.parse('AUD ¤1.50')
|
58
|
+
assert_equal @aud, BigMoney.parse('AUD¤ 1.50')
|
59
|
+
assert_equal @aud, BigMoney.parse('AUD¤1.50')
|
60
|
+
|
61
|
+
assert_equal @aud, BigMoney.parse('¤ 1.50 AUD')
|
62
|
+
assert_equal @aud, BigMoney.parse('¤ 1.50AUD')
|
63
|
+
assert_equal @aud, BigMoney.parse('¤1.50 AUD')
|
64
|
+
assert_equal @aud, BigMoney.parse('¤1.50AUD')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
metadata
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: big_money
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Shane Hanna
|
8
|
+
- Marshall Roch
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2010-01-22 00:00:00 +11:00
|
14
|
+
default_executable:
|
15
|
+
dependencies: []
|
16
|
+
|
17
|
+
description:
|
18
|
+
email:
|
19
|
+
- shane.hanna@gmail.com
|
20
|
+
- mroch@cmu.edu
|
21
|
+
executables: []
|
22
|
+
|
23
|
+
extensions: []
|
24
|
+
|
25
|
+
extra_rdoc_files:
|
26
|
+
- LICENSE
|
27
|
+
- README.rdoc
|
28
|
+
files:
|
29
|
+
- .document
|
30
|
+
- .gitignore
|
31
|
+
- Gemfile
|
32
|
+
- LICENSE
|
33
|
+
- README.rdoc
|
34
|
+
- Rakefile
|
35
|
+
- VERSION.yml
|
36
|
+
- big_money.gemspec
|
37
|
+
- lib/big_money.rb
|
38
|
+
- lib/big_money/currency.rb
|
39
|
+
- lib/big_money/currency/iso4217.rb
|
40
|
+
- lib/big_money/exchange.rb
|
41
|
+
- lib/big_money/exchange/yahoo.rb
|
42
|
+
- lib/big_money/parser.rb
|
43
|
+
- lib/big_money/types.rb
|
44
|
+
- rakelib/iso4217.rb
|
45
|
+
- rakelib/iso4217.rb.erb
|
46
|
+
- test/helper.rb
|
47
|
+
- test/test_big_money.rb
|
48
|
+
- test/test_currency.rb
|
49
|
+
- test/test_exchange.rb
|
50
|
+
- test/test_parser.rb
|
51
|
+
has_rdoc: true
|
52
|
+
homepage: http://github.com/shanna/big_money
|
53
|
+
licenses: []
|
54
|
+
|
55
|
+
post_install_message:
|
56
|
+
rdoc_options:
|
57
|
+
- --charset=UTF-8
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: "0"
|
65
|
+
version:
|
66
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: "0"
|
71
|
+
version:
|
72
|
+
requirements: []
|
73
|
+
|
74
|
+
rubyforge_project:
|
75
|
+
rubygems_version: 1.3.5
|
76
|
+
signing_key:
|
77
|
+
specification_version: 3
|
78
|
+
summary: BigDecimal backed amount of money in a particular currency.
|
79
|
+
test_files:
|
80
|
+
- test/test_exchange.rb
|
81
|
+
- test/helper.rb
|
82
|
+
- test/test_currency.rb
|
83
|
+
- test/test_big_money.rb
|
84
|
+
- test/test_parser.rb
|