monetary_value 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/README.rdoc +6 -0
- data/Rakefile +11 -0
- data/lib/currency.rb +82 -0
- data/lib/monetary_value.rb +200 -0
- data/lib/monetary_value/version.rb +3 -0
- data/monetary_value.gemspec +23 -0
- data/test/currency_test.rb +9 -0
- data/test/monetary_value_test.rb +149 -0
- data/test/test_helper.rb +3 -0
- metadata +89 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.rdoc
ADDED
data/Rakefile
ADDED
data/lib/currency.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'active_support/core_ext/enumerable' # Provides Enumerable#index_by
|
2
|
+
|
3
|
+
class Currency
|
4
|
+
attr_reader :id, :name, :code, :minor_divisor
|
5
|
+
|
6
|
+
def initialize(id, name, code, minor_divisor)
|
7
|
+
@id = id
|
8
|
+
@name = name
|
9
|
+
@code = code
|
10
|
+
@minor_divisor = minor_divisor
|
11
|
+
end
|
12
|
+
|
13
|
+
unless const_defined?(:CURRENCIES)
|
14
|
+
CURRENCIES = [
|
15
|
+
new(840, "United States Dollar", "USD", 100),
|
16
|
+
]
|
17
|
+
CURRENCIES_BY_ID = CURRENCIES.index_by(&:id)
|
18
|
+
CURRENCIES_BY_NAME = CURRENCIES.index_by(&:name)
|
19
|
+
CURRENCIES_BY_CODE = CURRENCIES.index_by(&:code)
|
20
|
+
|
21
|
+
CURRENCIES.freeze
|
22
|
+
CURRENCIES_BY_ID.freeze
|
23
|
+
CURRENCIES_BY_NAME.freeze
|
24
|
+
CURRENCIES_BY_CODE.freeze
|
25
|
+
end
|
26
|
+
|
27
|
+
def convert_to_minor_denomination(major_denomination)
|
28
|
+
return nil if major_denomination.nil?
|
29
|
+
(major_denomination.to_f * self.minor_divisor.to_f).round
|
30
|
+
end
|
31
|
+
|
32
|
+
def convert_to_major_denomination(minor_denomination)
|
33
|
+
return nil if minor_denomination.nil?
|
34
|
+
minor_denomination.to_f / self.minor_divisor.to_f
|
35
|
+
end
|
36
|
+
|
37
|
+
class << self
|
38
|
+
def all
|
39
|
+
CURRENCIES
|
40
|
+
end
|
41
|
+
|
42
|
+
def new(id = 840)
|
43
|
+
self[id]
|
44
|
+
end
|
45
|
+
|
46
|
+
def [](arg)
|
47
|
+
case arg
|
48
|
+
when Integer
|
49
|
+
CURRENCIES_BY_ID[arg]
|
50
|
+
else
|
51
|
+
raise ArgumentError, "invalid argument to Currency[]: #{arg.inspect}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def typecast(object)
|
56
|
+
return nil if object.nil?
|
57
|
+
return object if object.is_a? self
|
58
|
+
|
59
|
+
case object
|
60
|
+
when Integer
|
61
|
+
currency = CURRENCIES_BY_ID[object]
|
62
|
+
currency.nil? ? Currency.new : currency
|
63
|
+
when String
|
64
|
+
currency = CURRENCIES_BY_CODE[object]
|
65
|
+
currency.nil? ? Currency.new : currency
|
66
|
+
else
|
67
|
+
raise UntypecastableArgumentError, "#{object.inspect}:#{object.class} cannot be cast as #{self}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
def new_record?
|
74
|
+
false
|
75
|
+
end
|
76
|
+
|
77
|
+
def destroyed?
|
78
|
+
false
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
@@ -0,0 +1,200 @@
|
|
1
|
+
require 'monetary_value/version'
|
2
|
+
|
3
|
+
require 'currency'
|
4
|
+
|
5
|
+
class MonetaryValue
|
6
|
+
attr_reader :currency, :denomination
|
7
|
+
|
8
|
+
def initialize(denomination = 0, currency = Currency.new)
|
9
|
+
@denomination = denomination
|
10
|
+
@currency = currency
|
11
|
+
end
|
12
|
+
|
13
|
+
# Backwards compatibility
|
14
|
+
# TODO: Remove minor_denomination from MonetaryValue
|
15
|
+
def minor_denomination
|
16
|
+
denomination
|
17
|
+
end
|
18
|
+
|
19
|
+
def major_denomination
|
20
|
+
"%01.2f" % (currency.convert_to_major_denomination(denomination))
|
21
|
+
end
|
22
|
+
|
23
|
+
# Display
|
24
|
+
def to_s(format = :default)
|
25
|
+
case format
|
26
|
+
when :default, :short
|
27
|
+
"$#{major_denomination}"
|
28
|
+
when :long
|
29
|
+
"#{major_denomination} #{currency.code}"
|
30
|
+
else
|
31
|
+
"$#{major_denomination}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def inspect
|
36
|
+
to_s(:long)
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.parse(string)
|
40
|
+
currency = Currency.new
|
41
|
+
string.strip!
|
42
|
+
denomination = nil
|
43
|
+
nonnegative_string_formats = [
|
44
|
+
/^(\d+)$/, # "123"
|
45
|
+
/^\$(\d+)$/, # "$123"
|
46
|
+
/^(\d*)\.(\d{1,2})$/, # "123.4", ".4", "123.45", ".45"
|
47
|
+
/^\$(\d*)\.(\d{1,2})$/, # "$123.4", "$.4", "$123.45", "$.45"
|
48
|
+
]
|
49
|
+
|
50
|
+
nonnegative_string_formats.each do |format|
|
51
|
+
result = string.scan(format)
|
52
|
+
if result.size == 1
|
53
|
+
denominations = result.first
|
54
|
+
major_denomination = denominations[0].to_i
|
55
|
+
minor_denomination = denominations[1].nil? ? 0 : denominations[1].ljust(2, "0").to_i
|
56
|
+
denomination = major_denomination * 100 + minor_denomination
|
57
|
+
return MonetaryValue.new(denomination, currency)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
negative_string_formats = [
|
62
|
+
/^-(\d+)$/, # "-123"
|
63
|
+
/^-\$(\d+)$/, # "-$123"
|
64
|
+
/^\$-(\d+)$/, # "$-123"
|
65
|
+
/^-(\d*)\.(\d{1,2})$/, # "-123.4", "-.4", "-123.45", "-.45"
|
66
|
+
/^-\$(\d*)\.(\d{1,2})$/, # "-$123.4", "-$.4", "-$123.45", "-$.45"
|
67
|
+
/^\$-(\d*)\.(\d{1,2})$/, # "$-123.4", "$-.4", "$-123.45", "$-.45"
|
68
|
+
]
|
69
|
+
|
70
|
+
negative_string_formats.each do |format|
|
71
|
+
result = string.scan(format)
|
72
|
+
if result.size == 1
|
73
|
+
denominations = result.first
|
74
|
+
major_denomination = denominations[0].to_i
|
75
|
+
minor_denomination = denominations[1].nil? ? 0 : denominations[1].ljust(2, "0").to_i
|
76
|
+
denomination = major_denomination * 100 + minor_denomination
|
77
|
+
return MonetaryValue.new(-denomination, currency)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
raise ArgumentError, "invalid money_value"
|
82
|
+
end
|
83
|
+
|
84
|
+
class << self
|
85
|
+
def typecast(object)
|
86
|
+
return nil if object.nil?
|
87
|
+
return object if object.is_a? self
|
88
|
+
|
89
|
+
case object
|
90
|
+
when String
|
91
|
+
begin
|
92
|
+
parse(object)
|
93
|
+
rescue ArgumentError => e
|
94
|
+
raise UntypecastableArgumentError, "#{object.inspect}:#{object.class} cannot be cast as #{self}"
|
95
|
+
end
|
96
|
+
else
|
97
|
+
raise UntypecastableArgumentError, "#{object.inspect}:#{object.class} cannot be cast as #{self}"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
##############
|
104
|
+
# Arithmetic #
|
105
|
+
##############
|
106
|
+
|
107
|
+
# Comparisons
|
108
|
+
include Comparable
|
109
|
+
def <=>(other)
|
110
|
+
raise ArgumentError, "can't compare values in difference currencies" unless self =~ other
|
111
|
+
denomination <=> other.denomination
|
112
|
+
end
|
113
|
+
|
114
|
+
# Addition
|
115
|
+
def +(other)
|
116
|
+
raise ArgumentError, "can't add values in difference currencies" unless self =~ other
|
117
|
+
MonetaryValue.new(denomination + other.denomination, currency)
|
118
|
+
end
|
119
|
+
|
120
|
+
# Subtraction
|
121
|
+
def -(other)
|
122
|
+
raise ArgumentError, "can't subtract values in difference currencies" unless self =~ other
|
123
|
+
MonetaryValue.new(denomination - other.denomination, currency)
|
124
|
+
end
|
125
|
+
|
126
|
+
# Multiplication
|
127
|
+
def *(num)
|
128
|
+
MonetaryValue.new(denomination * num, currency)
|
129
|
+
end
|
130
|
+
|
131
|
+
# Division
|
132
|
+
def /(num)
|
133
|
+
MonetaryValue.new(denomination / num, currency)
|
134
|
+
end
|
135
|
+
|
136
|
+
# Absolute value
|
137
|
+
def abs
|
138
|
+
MonetaryValue.new(denomination.abs, currency)
|
139
|
+
end
|
140
|
+
|
141
|
+
# Unary plus
|
142
|
+
def +@
|
143
|
+
MonetaryValue.new(denomination, currency)
|
144
|
+
end
|
145
|
+
|
146
|
+
# Unary minus
|
147
|
+
def -@
|
148
|
+
MonetaryValue.new(-denomination, currency)
|
149
|
+
end
|
150
|
+
|
151
|
+
# Currency matching
|
152
|
+
def =~(other)
|
153
|
+
currency == other.currency
|
154
|
+
end
|
155
|
+
|
156
|
+
# Next
|
157
|
+
def next
|
158
|
+
MonetaryValue.new(denomination.next, currency)
|
159
|
+
end
|
160
|
+
alias :succ :next
|
161
|
+
|
162
|
+
##############
|
163
|
+
# Sign tests #
|
164
|
+
##############
|
165
|
+
|
166
|
+
def zero?
|
167
|
+
denomination.zero?
|
168
|
+
end
|
169
|
+
|
170
|
+
def sign
|
171
|
+
denomination.sign
|
172
|
+
end
|
173
|
+
|
174
|
+
def positive?
|
175
|
+
denomination.positive?
|
176
|
+
end
|
177
|
+
|
178
|
+
def negative?
|
179
|
+
denomination.negative?
|
180
|
+
end
|
181
|
+
|
182
|
+
#################
|
183
|
+
# Serialization #
|
184
|
+
#################
|
185
|
+
|
186
|
+
def self.xml_root
|
187
|
+
"money"
|
188
|
+
end
|
189
|
+
|
190
|
+
def to_xml(options = {})
|
191
|
+
options[:root] ||= self.class.xml_root
|
192
|
+
{ :currency_id => currency.id, :denomination => denomination }.to_xml(options)
|
193
|
+
end
|
194
|
+
|
195
|
+
def self.from_xml(xml)
|
196
|
+
attributes = Hash.from_xml(xml)[xml_root].symbolize_keys
|
197
|
+
new( attributes[:denomination] || attributes[:minor_value], Currency.new(attributes[:currency_id]) )
|
198
|
+
end
|
199
|
+
|
200
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "monetary_value/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "monetary_value"
|
7
|
+
s.version = MonetaryValue::VERSION
|
8
|
+
s.authors = ["Ian James"]
|
9
|
+
s.email = ["ian@opencuro.com"]
|
10
|
+
s.homepage = "https://opencuro.com"
|
11
|
+
s.summary = %q{Library for working with monetary values}
|
12
|
+
s.description = %q{Provides the MonetaryValue and Currency classes.}
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
|
19
|
+
# specify any dependencies here; for example:
|
20
|
+
# s.add_development_dependency "rspec"
|
21
|
+
# s.add_runtime_dependency "rest-client"
|
22
|
+
s.add_dependency "activesupport"
|
23
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'monetary_value'
|
3
|
+
|
4
|
+
class MonetaryValueTest < ActiveSupport::TestCase
|
5
|
+
def test_parse
|
6
|
+
valid_strings = {
|
7
|
+
"0" => MonetaryValue.new(0),
|
8
|
+
"00" => MonetaryValue.new(0),
|
9
|
+
"1" => MonetaryValue.new(100),
|
10
|
+
"123" => MonetaryValue.new(12300),
|
11
|
+
|
12
|
+
"$0" => MonetaryValue.new(0),
|
13
|
+
"$00" => MonetaryValue.new(0),
|
14
|
+
"$1" => MonetaryValue.new(100),
|
15
|
+
"$123" => MonetaryValue.new(12300),
|
16
|
+
|
17
|
+
"0.00" => MonetaryValue.new(0),
|
18
|
+
"0.0" => MonetaryValue.new(0),
|
19
|
+
".00" => MonetaryValue.new(0),
|
20
|
+
".0" => MonetaryValue.new(0),
|
21
|
+
"0.12" => MonetaryValue.new(12),
|
22
|
+
"0.10" => MonetaryValue.new(10),
|
23
|
+
"0.1" => MonetaryValue.new(10),
|
24
|
+
".12" => MonetaryValue.new(12),
|
25
|
+
".10" => MonetaryValue.new(10),
|
26
|
+
".1" => MonetaryValue.new(10),
|
27
|
+
"1.23" => MonetaryValue.new(123),
|
28
|
+
"1.20" => MonetaryValue.new(120),
|
29
|
+
"1.2" => MonetaryValue.new(120),
|
30
|
+
|
31
|
+
"$0.00" => MonetaryValue.new(0),
|
32
|
+
"$0.0" => MonetaryValue.new(0),
|
33
|
+
"$.00" => MonetaryValue.new(0),
|
34
|
+
"$.0" => MonetaryValue.new(0),
|
35
|
+
"$0.12" => MonetaryValue.new(12),
|
36
|
+
"$0.10" => MonetaryValue.new(10),
|
37
|
+
"$0.1" => MonetaryValue.new(10),
|
38
|
+
"$.12" => MonetaryValue.new(12),
|
39
|
+
"$.10" => MonetaryValue.new(10),
|
40
|
+
"$.1" => MonetaryValue.new(10),
|
41
|
+
"$1.23" => MonetaryValue.new(123),
|
42
|
+
"$1.20" => MonetaryValue.new(120),
|
43
|
+
"$1.2" => MonetaryValue.new(120),
|
44
|
+
|
45
|
+
"-0" => MonetaryValue.new(0),
|
46
|
+
"-00" => MonetaryValue.new(0),
|
47
|
+
"-1" => MonetaryValue.new(-100),
|
48
|
+
"-123" => MonetaryValue.new(-12300),
|
49
|
+
|
50
|
+
"-$0" => MonetaryValue.new(0),
|
51
|
+
"-$00" => MonetaryValue.new(0),
|
52
|
+
"-$1" => MonetaryValue.new(-100),
|
53
|
+
"-$123" => MonetaryValue.new(-12300),
|
54
|
+
|
55
|
+
"$-0" => MonetaryValue.new(0),
|
56
|
+
"$-00" => MonetaryValue.new(0),
|
57
|
+
"$-1" => MonetaryValue.new(-100),
|
58
|
+
"$-123" => MonetaryValue.new(-12300),
|
59
|
+
|
60
|
+
"-0.00" => MonetaryValue.new(0),
|
61
|
+
"-0.0" => MonetaryValue.new(0),
|
62
|
+
"-.00" => MonetaryValue.new(0),
|
63
|
+
"-.0" => MonetaryValue.new(0),
|
64
|
+
"-0.12" => MonetaryValue.new(-12),
|
65
|
+
"-0.10" => MonetaryValue.new(-10),
|
66
|
+
"-0.1" => MonetaryValue.new(-10),
|
67
|
+
"-.12" => MonetaryValue.new(-12),
|
68
|
+
"-.10" => MonetaryValue.new(-10),
|
69
|
+
"-.1" => MonetaryValue.new(-10),
|
70
|
+
"-1.23" => MonetaryValue.new(-123),
|
71
|
+
"-1.20" => MonetaryValue.new(-120),
|
72
|
+
"-1.2" => MonetaryValue.new(-120),
|
73
|
+
|
74
|
+
"-$0.00" => MonetaryValue.new(0),
|
75
|
+
"-$0.0" => MonetaryValue.new(0),
|
76
|
+
"-$.00" => MonetaryValue.new(0),
|
77
|
+
"-$.0" => MonetaryValue.new(0),
|
78
|
+
"-$0.12" => MonetaryValue.new(-12),
|
79
|
+
"-$0.10" => MonetaryValue.new(-10),
|
80
|
+
"-$0.1" => MonetaryValue.new(-10),
|
81
|
+
"-$.12" => MonetaryValue.new(-12),
|
82
|
+
"-$.10" => MonetaryValue.new(-10),
|
83
|
+
"-$.1" => MonetaryValue.new(-10),
|
84
|
+
"-$1.23" => MonetaryValue.new(-123),
|
85
|
+
"-$1.20" => MonetaryValue.new(-120),
|
86
|
+
"-$1.2" => MonetaryValue.new(-120),
|
87
|
+
|
88
|
+
"$-0.00" => MonetaryValue.new(0),
|
89
|
+
"$-0.0" => MonetaryValue.new(0),
|
90
|
+
"$-.00" => MonetaryValue.new(0),
|
91
|
+
"$-.0" => MonetaryValue.new(0),
|
92
|
+
"$-0.12" => MonetaryValue.new(-12),
|
93
|
+
"$-0.10" => MonetaryValue.new(-10),
|
94
|
+
"$-0.1" => MonetaryValue.new(-10),
|
95
|
+
"$-.12" => MonetaryValue.new(-12),
|
96
|
+
"$-.10" => MonetaryValue.new(-10),
|
97
|
+
"$-.1" => MonetaryValue.new(-10),
|
98
|
+
"$-1.23" => MonetaryValue.new(-123),
|
99
|
+
"$-1.20" => MonetaryValue.new(-120),
|
100
|
+
"$-1.2" => MonetaryValue.new(-120),
|
101
|
+
|
102
|
+
}
|
103
|
+
|
104
|
+
valid_strings.each do |valid_string, result|
|
105
|
+
begin
|
106
|
+
assert_equal result, MonetaryValue.parse(valid_string), valid_string
|
107
|
+
rescue ArgumentError
|
108
|
+
flunk "#{valid_string} should be able to be parsed"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
invalid_strings = [
|
113
|
+
"",
|
114
|
+
"$",
|
115
|
+
".",
|
116
|
+
"$.",
|
117
|
+
|
118
|
+
"-",
|
119
|
+
"-$",
|
120
|
+
"$-",
|
121
|
+
"-.",
|
122
|
+
"-$.",
|
123
|
+
"$-.",
|
124
|
+
|
125
|
+
"$1.234",
|
126
|
+
"a1.23",
|
127
|
+
"1a.23",
|
128
|
+
"1. 23",
|
129
|
+
"1 .23",
|
130
|
+
"1,23",
|
131
|
+
"1.023",
|
132
|
+
"0x1",
|
133
|
+
|
134
|
+
"0.",
|
135
|
+
"1.",
|
136
|
+
"$0.",
|
137
|
+
"$-1.",
|
138
|
+
"-$1.",
|
139
|
+
]
|
140
|
+
|
141
|
+
invalid_strings.each do |invalid_string|
|
142
|
+
assert_raise ArgumentError do
|
143
|
+
MonetaryValue.parse(invalid_string)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: monetary_value
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 23
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
- 0
|
10
|
+
version: 1.0.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Ian James
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-06-06 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: activesupport
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 3
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
version: "0"
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
description: Provides the MonetaryValue and Currency classes.
|
35
|
+
email:
|
36
|
+
- ian@opencuro.com
|
37
|
+
executables: []
|
38
|
+
|
39
|
+
extensions: []
|
40
|
+
|
41
|
+
extra_rdoc_files: []
|
42
|
+
|
43
|
+
files:
|
44
|
+
- .gitignore
|
45
|
+
- Gemfile
|
46
|
+
- README.rdoc
|
47
|
+
- Rakefile
|
48
|
+
- lib/currency.rb
|
49
|
+
- lib/monetary_value.rb
|
50
|
+
- lib/monetary_value/version.rb
|
51
|
+
- monetary_value.gemspec
|
52
|
+
- test/currency_test.rb
|
53
|
+
- test/monetary_value_test.rb
|
54
|
+
- test/test_helper.rb
|
55
|
+
homepage: https://opencuro.com
|
56
|
+
licenses: []
|
57
|
+
|
58
|
+
post_install_message:
|
59
|
+
rdoc_options: []
|
60
|
+
|
61
|
+
require_paths:
|
62
|
+
- lib
|
63
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
hash: 3
|
69
|
+
segments:
|
70
|
+
- 0
|
71
|
+
version: "0"
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
hash: 3
|
78
|
+
segments:
|
79
|
+
- 0
|
80
|
+
version: "0"
|
81
|
+
requirements: []
|
82
|
+
|
83
|
+
rubyforge_project:
|
84
|
+
rubygems_version: 1.8.10
|
85
|
+
signing_key:
|
86
|
+
specification_version: 3
|
87
|
+
summary: Library for working with monetary values
|
88
|
+
test_files: []
|
89
|
+
|