money 2.1.1 → 2.1.2
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/lib/money/core_extensions.rb +95 -9
- data/lib/money/money.rb +6 -6
- data/money.gemspec +1 -1
- data/test/core_extensions_spec.rb +25 -0
- metadata +2 -2
@@ -20,19 +20,105 @@ class String
|
|
20
20
|
# '$100 USD'.to_money # => #<Money @cents=10000, @currency="USD">
|
21
21
|
def to_money
|
22
22
|
# Get the currency.
|
23
|
-
matches = scan /([A-Z]{2,3})/
|
23
|
+
matches = scan /([A-Z]{2,3})/
|
24
24
|
currency = matches[0] ? matches[0][0] : Money.default_currency
|
25
|
+
cents = calculate_cents(self)
|
26
|
+
Money.new(cents, currency)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def calculate_cents(number)
|
32
|
+
# remove anything that's not a number, potential delimiter, or minus sign
|
33
|
+
num = number.gsub(/[^\d|\.|,|\'|\s|\-]/, '').strip
|
34
|
+
|
35
|
+
# set a boolean flag for if the number is negative or not
|
36
|
+
negative = num.split(//).first == "-"
|
37
|
+
|
38
|
+
# if negative, remove the minus sign from the number
|
39
|
+
num = num.gsub(/^-/, '') if negative
|
25
40
|
|
26
|
-
#
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
41
|
+
# gather all separators within the result number
|
42
|
+
used_separators = num.scan /[^\d]/
|
43
|
+
|
44
|
+
# determine the number of unique separators within the number
|
45
|
+
#
|
46
|
+
# e.g.
|
47
|
+
# $1,234,567.89 would return 2 (, and .)
|
48
|
+
# $125,00 would return 1
|
49
|
+
# $199 would return 0
|
50
|
+
# $1 234,567.89 would raise an error (separators are space, comma, and period)
|
51
|
+
case used_separators.uniq.length
|
52
|
+
# no separator or delimiter; major (dollars) is the number, and minor (cents) is 0
|
53
|
+
when 0 then major, minor = num, 0
|
54
|
+
|
55
|
+
# two separators, so we know the last item in this array is the
|
56
|
+
# major/minor delimiter and the rest are separators
|
57
|
+
when 2
|
58
|
+
separator, delimiter = used_separators.uniq
|
59
|
+
# remove all separators, split on the delimiter
|
60
|
+
major, minor = num.gsub(separator, '').split(delimiter)
|
61
|
+
min = 0 unless min
|
62
|
+
when 1
|
63
|
+
# we can't determine if the comma or period is supposed to be a separator or a delimiter
|
64
|
+
# e.g.
|
65
|
+
# 1,00 - comma is a delimiter
|
66
|
+
# 1.000 - period is a delimiter
|
67
|
+
# 1,000 - comma is a separator
|
68
|
+
# 1,000,000 - comma is a separator
|
69
|
+
# 10000,00 - comma is a delimiter
|
70
|
+
# 1000,000 - comma is a delimiter
|
71
|
+
|
72
|
+
# assign first separator for reusability
|
73
|
+
separator = used_separators.first
|
74
|
+
|
75
|
+
# separator is used as a separator when there are multiple instances, always
|
76
|
+
if num.scan(separator).length > 1 # multiple matches; treat as separator
|
77
|
+
major, minor = num.gsub(separator, ''), 0
|
78
|
+
else
|
79
|
+
# ex: 1,000 - 1.0000 - 10001.000
|
80
|
+
# split number into possible major (dollars) and minor (cents) values
|
81
|
+
possible_major, possible_minor = num.split(separator)
|
82
|
+
|
83
|
+
# if the minor (cents) length isn't 3, assign major/minor from the possibles
|
84
|
+
# e.g.
|
85
|
+
# 1,00 => 1.00
|
86
|
+
# 1.0000 => 1.00
|
87
|
+
# 1.2 => 1.20
|
88
|
+
if possible_minor.length != 3 # delimiter
|
89
|
+
major, minor = possible_major, possible_minor
|
90
|
+
else
|
91
|
+
# minor length is three
|
92
|
+
# let's try to figure out intent of the delimiter
|
93
|
+
|
94
|
+
# the major length is greater than three, which means
|
95
|
+
# the comma or period is used as a delimiter
|
96
|
+
# e.g.
|
97
|
+
# 1000,000
|
98
|
+
# 100000,000
|
99
|
+
if possible_major.length > 3
|
100
|
+
major, minor = possible_major, possible_minor
|
101
|
+
else
|
102
|
+
# number is in format ###{sep}### or ##{sep}### or #{sep}###
|
103
|
+
# handle as , is sep, . is delimiter
|
104
|
+
if separator == '.'
|
105
|
+
major, minor = possible_major, possible_minor
|
32
106
|
else
|
33
|
-
0
|
107
|
+
major, minor = "#{possible_major}#{possible_minor}", 0
|
34
108
|
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
else
|
113
|
+
raise ArgumentError, "Invalid currency amount"
|
114
|
+
end
|
35
115
|
|
36
|
-
|
116
|
+
# build the string based on major/minor since separator/delimiters have been removed
|
117
|
+
# transform to a float, multiply by 100 to convert to cents
|
118
|
+
cents = "#{major}.#{minor}".to_f * 100
|
119
|
+
|
120
|
+
# if negative, multiply by -1; otherwise, return positive cents
|
121
|
+
negative ? cents * -1 : cents
|
37
122
|
end
|
123
|
+
|
38
124
|
end
|
data/lib/money/money.rb
CHANGED
@@ -95,7 +95,7 @@ class Money
|
|
95
95
|
Money.new(cents + other_money.cents, other_money.currency)
|
96
96
|
else
|
97
97
|
Money.new(cents + other_money.exchange_to(currency).cents,currency)
|
98
|
-
end
|
98
|
+
end
|
99
99
|
end
|
100
100
|
|
101
101
|
def -(other_money)
|
@@ -103,7 +103,7 @@ class Money
|
|
103
103
|
Money.new(cents - other_money.cents, other_money.currency)
|
104
104
|
else
|
105
105
|
Money.new(cents - other_money.exchange_to(currency).cents, currency)
|
106
|
-
end
|
106
|
+
end
|
107
107
|
end
|
108
108
|
|
109
109
|
# get the cents value of the object
|
@@ -113,17 +113,17 @@ class Money
|
|
113
113
|
|
114
114
|
# multiply money by fixnum
|
115
115
|
def *(fixnum)
|
116
|
-
Money.new(cents * fixnum, currency)
|
116
|
+
Money.new(cents * fixnum, currency)
|
117
117
|
end
|
118
118
|
|
119
119
|
# divide money by fixnum
|
120
120
|
def /(fixnum)
|
121
|
-
Money.new(cents / fixnum, currency)
|
121
|
+
Money.new(cents / fixnum, currency)
|
122
122
|
end
|
123
123
|
|
124
124
|
# Test if the money amount is zero
|
125
125
|
def zero?
|
126
|
-
cents == 0
|
126
|
+
cents == 0
|
127
127
|
end
|
128
128
|
|
129
129
|
|
@@ -220,7 +220,7 @@ class Money
|
|
220
220
|
# Conversation to self
|
221
221
|
def to_money
|
222
222
|
self
|
223
|
-
end
|
223
|
+
end
|
224
224
|
|
225
225
|
private
|
226
226
|
|
data/money.gemspec
CHANGED
@@ -17,12 +17,25 @@ describe "Money core extensions" do
|
|
17
17
|
"100.37".to_money.should == Money.new(100_37)
|
18
18
|
"100,37".to_money.should == Money.new(100_37)
|
19
19
|
"100 000".to_money.should == Money.new(100_000_00)
|
20
|
+
"100,000.00".to_money.should == Money.new(100_000_00)
|
21
|
+
"1,000".to_money.should == Money.new(1_000_00)
|
22
|
+
"-1,000".to_money.should == Money.new(-1_000_00)
|
23
|
+
"1,000.0000".to_money.should == Money.new(1_000_00)
|
24
|
+
"1,000.5000".to_money.should == Money.new(1_000_50)
|
25
|
+
"1.550".to_money.should == Money.new(1_55)
|
20
26
|
|
21
27
|
"100 USD".to_money.should == Money.new(100_00, "USD")
|
22
28
|
"-100 USD".to_money.should == Money.new(-100_00, "USD")
|
23
29
|
"100 EUR".to_money.should == Money.new(100_00, "EUR")
|
24
30
|
"100.37 EUR".to_money.should == Money.new(100_37, "EUR")
|
25
31
|
"100,37 EUR".to_money.should == Money.new(100_37, "EUR")
|
32
|
+
"100,000.00 USD".to_money.should == Money.new(100_000_00, "USD")
|
33
|
+
"100.000,00 EUR".to_money.should == Money.new(100_000_00, "EUR")
|
34
|
+
"1,000 USD".to_money.should == Money.new(1_000_00, "USD")
|
35
|
+
"-1,000 USD".to_money.should == Money.new(-1_000_00, "USD")
|
36
|
+
"1,000.5500 USD".to_money.should == Money.new(1_000_55, "USD")
|
37
|
+
"-1,000.6500 USD".to_money.should == Money.new(-1_000_65, "USD")
|
38
|
+
"1.550 USD".to_money.should == Money.new(1_55, "USD")
|
26
39
|
|
27
40
|
"USD 100".to_money.should == Money.new(100_00, "USD")
|
28
41
|
"EUR 100".to_money.should == Money.new(100_00, "EUR")
|
@@ -30,7 +43,19 @@ describe "Money core extensions" do
|
|
30
43
|
"CAD -100.37".to_money.should == Money.new(-100_37, "CAD")
|
31
44
|
"EUR 100,37".to_money.should == Money.new(100_37, "EUR")
|
32
45
|
"EUR -100,37".to_money.should == Money.new(-100_37, "EUR")
|
46
|
+
"USD 100,000.00".to_money.should == Money.new(100_000_00, "USD")
|
47
|
+
"EUR 100.000,00".to_money.should == Money.new(100_000_00, "EUR")
|
48
|
+
"USD 1,000".to_money.should == Money.new(1_000_00, "USD")
|
49
|
+
"USD -1,000".to_money.should == Money.new(-1_000_00, "USD")
|
50
|
+
"USD 1,000.9000".to_money.should == Money.new(1_000_90, "USD")
|
51
|
+
"USD -1,000.090".to_money.should == Money.new(-1_000_09, "USD")
|
52
|
+
"USD 1.5500".to_money.should == Money.new(1_55, "USD")
|
33
53
|
|
34
54
|
"$100 USD".to_money.should == Money.new(100_00, "USD")
|
55
|
+
"$1,194.59 USD".to_money.should == Money.new(1_194_59, "USD")
|
56
|
+
"$-1,955 USD".to_money.should == Money.new(-1_955_00, "USD")
|
57
|
+
"$1,194.5900 USD".to_money.should == Money.new(1_194_59, "USD")
|
58
|
+
"$-1,955.000 USD".to_money.should == Money.new(-1_955_00, "USD")
|
59
|
+
"$1.99000 USD".to_money.should == Money.new(1_99, "USD")
|
35
60
|
end
|
36
61
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: money
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tobias Luetke
|
@@ -11,7 +11,7 @@ autorequire:
|
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
13
|
|
14
|
-
date: 2009-02-
|
14
|
+
date: 2009-02-21 00:00:00 +01:00
|
15
15
|
default_executable:
|
16
16
|
dependencies: []
|
17
17
|
|