big_money 1.1.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.
- 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
|