nofxx-money 2.3.6 → 2.3.8
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest.txt +0 -1
- data/README.rdoc +38 -26
- data/VERSION +1 -1
- data/lib/money/core_extensions.rb +30 -17
- data/lib/money/exchange_bank.rb +17 -6
- data/lib/money/money.rb +1 -0
- data/money.gemspec +5 -5
- data/spec/money/core_extensions_spec.rb +39 -21
- data/spec/money/exchange_bank_spec.rb +18 -2
- metadata +4 -4
data/Manifest.txt
CHANGED
data/README.rdoc
CHANGED
@@ -10,28 +10,14 @@ This library aids one in handling money and different currencies. Features:
|
|
10
10
|
- Has the ability to parse a money string into a Money object.
|
11
11
|
- Provides ActiveRecord "has_money" method.
|
12
12
|
|
13
|
-
Resources:
|
14
|
-
|
15
|
-
- Website: http://money.rubyforge.org
|
16
|
-
- RDoc API: http://money.rubyforge.org
|
17
|
-
- This fork: http://github.com/ShadowBelmolve/money
|
18
|
-
- Forked from: http://github.com/nofxx/money
|
19
|
-
- Git repository: http://github.com/FooBarWidget/money/tree/master
|
20
|
-
|
21
|
-
|
22
|
-
== Download
|
23
|
-
|
24
|
-
Install stable releases with the following command:
|
25
|
-
|
26
|
-
gem install money
|
27
13
|
|
28
|
-
|
14
|
+
== Install
|
29
15
|
|
30
16
|
gem sources -a http://gems.github.com
|
31
|
-
gem install
|
17
|
+
gem install <this-fork>-money
|
32
18
|
|
33
19
|
|
34
|
-
==
|
20
|
+
== Use
|
35
21
|
|
36
22
|
=== Synopsis
|
37
23
|
|
@@ -51,6 +37,14 @@ The development version (hosted on Github) can be installed with:
|
|
51
37
|
Money.new(1000, "USD") == Money.new(1000, "EUR") # => false
|
52
38
|
|
53
39
|
|
40
|
+
=== Rounding
|
41
|
+
|
42
|
+
You can use round_to_coin when you don't have currency with coins for cents.
|
43
|
+
E.g. if the smallest coin is 0.50, then
|
44
|
+
|
45
|
+
Money.new(1448, 'CZK').round_to_coin(50).to_s # => "14.50"
|
46
|
+
|
47
|
+
|
54
48
|
=== Currency Exchange
|
55
49
|
|
56
50
|
Exchanging money is performed through an exchange bank object. The default
|
@@ -88,6 +82,17 @@ www.xe.com for the current rates or just returns <tt>rand(2)</tt>:
|
|
88
82
|
Money.default_bank = ExchangeBankWhichScrapesXeDotCom.new
|
89
83
|
|
90
84
|
|
85
|
+
=== Default Currency
|
86
|
+
|
87
|
+
By default Money defaults to USD as its currency. This can be overwritten using:
|
88
|
+
|
89
|
+
Money.default_currency = "CAD"
|
90
|
+
|
91
|
+
If you use Rails, then environment.rb is a very good place to put this.
|
92
|
+
|
93
|
+
|
94
|
+
== Webapps
|
95
|
+
|
91
96
|
=== Ruby on Rails
|
92
97
|
|
93
98
|
Use the +has_money+ method to embed the money object in your models.
|
@@ -96,7 +101,7 @@ fields on the database.
|
|
96
101
|
|
97
102
|
config/enviroment.rb
|
98
103
|
|
99
|
-
require.gem '
|
104
|
+
require.gem 'bobek-money', :lib => 'money'
|
100
105
|
|
101
106
|
app/models/product.rb
|
102
107
|
|
@@ -115,18 +120,25 @@ migration:
|
|
115
120
|
end
|
116
121
|
|
117
122
|
|
118
|
-
===
|
123
|
+
=== jQuery
|
119
124
|
|
120
|
-
|
125
|
+
Check out http://meiaduzia.com.br/cuducos2/priceformat for a nice
|
126
|
+
mask for webapp's textfields.
|
121
127
|
|
122
|
-
Money.default_currency = "CAD"
|
123
128
|
|
124
|
-
|
129
|
+
== About
|
130
|
+
|
131
|
+
Resources:
|
125
132
|
|
133
|
+
Orinally developed by:
|
134
|
+
|
135
|
+
- Forked from: http://github.com/FooBarWidget/money
|
136
|
+
- Website: http://money.rubyforge.org
|
137
|
+
- RDoc API: http://money.rubyforge.org
|
126
138
|
|
127
|
-
== TODO
|
128
139
|
|
129
|
-
|
130
|
-
* Interest (almost there..)
|
131
|
-
* Remote rate fetching
|
140
|
+
This branch is part of:
|
132
141
|
|
142
|
+
:: http://github.com/bobek/money
|
143
|
+
:: http://github.com/nofxx/money
|
144
|
+
:: http://github.com/ShadowBelmove/money
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.3.
|
1
|
+
2.3.8
|
@@ -13,7 +13,7 @@ class Numeric
|
|
13
13
|
Money.new(self.to_s.gsub(/\./,'').to_i)
|
14
14
|
end
|
15
15
|
else
|
16
|
-
Money.new(self * 100)
|
16
|
+
Money.new((self * 100).round)
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
@@ -22,12 +22,12 @@ class String
|
|
22
22
|
# Parses the current string and converts it to a Money object.
|
23
23
|
# Excess characters will be discarded.
|
24
24
|
#
|
25
|
-
# '100'.to_money # => #<Money @cents=
|
25
|
+
# '100'.to_money # => #<Money @cents=10000>
|
26
26
|
# '100.37'.to_money # => #<Money @cents=10037>
|
27
|
-
# '100 USD'.to_money # => #<Money @cents=
|
28
|
-
# 'USD 100'.to_money # => #<Money @cents=
|
29
|
-
# '$100 USD'.to_money
|
30
|
-
# '
|
27
|
+
# '100 USD'.to_money # => #<Money @cents=10000, @currency="USD">
|
28
|
+
# 'USD 100'.to_money # => #<Money @cents=10000, @currency="USD">
|
29
|
+
# '$100 USD'.to_money # => #<Money @cents=10000, @currency="USD">
|
30
|
+
# 'hello 2000 world'.to_money # => #<Money @cents=200000 @currency="USD")>
|
31
31
|
def to_money(with_cents = false)
|
32
32
|
# Get the currency.
|
33
33
|
matches = scan /([A-Z]{2,3})/
|
@@ -38,7 +38,7 @@ class String
|
|
38
38
|
|
39
39
|
private
|
40
40
|
|
41
|
-
def calculate_cents(number, with_cents
|
41
|
+
def calculate_cents(number, with_cents)
|
42
42
|
# remove anything that's not a number, potential delimiter, or minus sign
|
43
43
|
num = number.gsub(/[^\d|\.|,|\'|\s|\-]/, '').strip
|
44
44
|
|
@@ -89,12 +89,14 @@ class String
|
|
89
89
|
# ex: 1,000 - 1.0000 - 10001.000
|
90
90
|
# split number into possible major (dollars) and minor (cents) values
|
91
91
|
possible_major, possible_minor = num.split(separator)
|
92
|
+
possible_major ||= "0"
|
93
|
+
possible_minor ||= "00"
|
92
94
|
|
93
95
|
# if the minor (cents) length isn't 3, assign major/minor from the possibles
|
94
96
|
# e.g.
|
95
|
-
#
|
96
|
-
#
|
97
|
-
#
|
97
|
+
# 1,00 => 1.00
|
98
|
+
# 1.0000 => 1.00
|
99
|
+
# 1.2 => 1.20
|
98
100
|
if possible_minor.length != 3 # delimiter
|
99
101
|
major, minor = possible_major, possible_minor
|
100
102
|
else
|
@@ -104,8 +106,8 @@ class String
|
|
104
106
|
# the major length is greater than three, which means
|
105
107
|
# the comma or period is used as a delimiter
|
106
108
|
# e.g.
|
107
|
-
#
|
108
|
-
#
|
109
|
+
# 1000,000
|
110
|
+
# 100000,000
|
109
111
|
if possible_major.length > 3
|
110
112
|
major, minor = possible_major, possible_minor
|
111
113
|
else
|
@@ -124,16 +126,27 @@ class String
|
|
124
126
|
end
|
125
127
|
|
126
128
|
# build the string based on major/minor since separator/delimiters have been removed
|
127
|
-
#
|
128
|
-
if with_cents and minor == 0
|
129
|
-
cents =
|
129
|
+
# avoiding floating point arithmetic here to ensure accuracy
|
130
|
+
if with_cents #and minor == 0
|
131
|
+
cents = major.to_i
|
130
132
|
else
|
131
|
-
cents =
|
133
|
+
cents = major.to_i * 100
|
134
|
+
# add the minor number as well. this may have any number of digits,
|
135
|
+
# so we treat minor as a string and truncate or right-fill it with zeroes
|
136
|
+
# until it becomes a two-digit number string, which we add to cents.
|
137
|
+
minor = minor.to_s
|
138
|
+
truncated_minor = minor[0..1]
|
139
|
+
truncated_minor << "0" * (2 - truncated_minor.size) if truncated_minor.size < 2
|
140
|
+
cents += truncated_minor.to_i
|
141
|
+
# respect rounding rules
|
142
|
+
if minor.size >= 3 && minor[2..2].to_i >= 5
|
143
|
+
cents += 1
|
144
|
+
end
|
132
145
|
end
|
133
146
|
|
134
|
-
|
135
147
|
# if negative, multiply by -1; otherwise, return positive cents
|
136
148
|
negative ? cents * -1 : cents
|
137
149
|
end
|
138
150
|
|
139
151
|
end
|
152
|
+
|
data/lib/money/exchange_bank.rb
CHANGED
@@ -26,6 +26,10 @@ end
|
|
26
26
|
# bank.exchange(100_00, "USD", "CAD") # => 6450
|
27
27
|
class Money
|
28
28
|
class ExchangeBank
|
29
|
+
#
|
30
|
+
# Rates to be autofetched
|
31
|
+
attr_accessor :default_rates
|
32
|
+
|
29
33
|
# Returns the singleton instance of ExchangeBank.
|
30
34
|
#
|
31
35
|
# By default, <tt>Money.default_bank</tt> returns the same object.
|
@@ -51,6 +55,7 @@ class Money
|
|
51
55
|
@mutex.synchronize do
|
52
56
|
@rates["#{from}<>#{to}".upcase] = rate
|
53
57
|
@rates["#{to}<>#{from}".upcase] = 1.0/rate
|
58
|
+
@rates["sync_at"] = Time.now.to_i
|
54
59
|
end
|
55
60
|
end
|
56
61
|
|
@@ -74,21 +79,27 @@ class Money
|
|
74
79
|
# Returns the amount of cents in +to_currency+ as an integer, rounded down.
|
75
80
|
#
|
76
81
|
# If the conversion rate is unknown, then Money::UnknownRate will be raised.
|
77
|
-
def exchange(cents,
|
78
|
-
rate =
|
79
|
-
|
80
|
-
raise Money::UnknownRate, "No conversion rate known for '#{from_currency}' -> '#{to_currency}'"
|
81
|
-
end
|
82
|
+
def exchange(cents, from, to)
|
83
|
+
rate = get_rate(from, to)
|
84
|
+
raise(Money::UnknownRate, "No conversion rate for #{from} -> #{to}") unless rate
|
82
85
|
(cents * rate).floor
|
83
86
|
end
|
84
87
|
|
88
|
+
def fetch_rate(from, to)
|
89
|
+
|
90
|
+
end
|
91
|
+
|
85
92
|
# Fetch rates
|
86
93
|
def fetch_rates
|
87
94
|
xml = Parser::XML(Net::HTTP.get(URI.parse('http://www.ecb.int/stats/eurofxref/eurofxref-daily.xml')))
|
88
95
|
curr = (xml/:Cube).select { |r| r["currency"] == Money.default_currency }.first
|
89
96
|
diff = Money.default_currency == "EUR" || !curr ? 1 : curr["rate"].to_f
|
90
97
|
(xml/:Cube).each do |x|
|
91
|
-
|
98
|
+
r = x['rate'].to_f
|
99
|
+
c = x['currency'] || ""
|
100
|
+
unless default_rates && !default_rates.include?(c)
|
101
|
+
parse_rate r / diff, curr ? Money.default_currency : "EUR", c.upcase
|
102
|
+
end
|
92
103
|
end
|
93
104
|
parse_rate diff, Money.default_currency, "EUR" if curr
|
94
105
|
self
|
data/lib/money/money.rb
CHANGED
data/money.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{money}
|
5
|
-
s.version = "2.3.
|
5
|
+
s.version = "2.3.8"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Money Team"]
|
9
|
-
s.date = %q{2009-
|
9
|
+
s.date = %q{2009-06-20}
|
10
10
|
s.description = %q{This library aids one in handling money and different currencies.}
|
11
11
|
s.email = %q{see@reame}
|
12
12
|
s.extra_rdoc_files = [
|
@@ -41,14 +41,14 @@ Gem::Specification.new do |s|
|
|
41
41
|
s.homepage = %q{http://github.com/nofxx/money}
|
42
42
|
s.rdoc_options = ["--charset=UTF-8"]
|
43
43
|
s.require_paths = ["lib"]
|
44
|
-
s.rubygems_version = %q{1.3.
|
44
|
+
s.rubygems_version = %q{1.3.4}
|
45
45
|
s.summary = %q{This library aids one in handling money and different currencies.}
|
46
46
|
s.test_files = [
|
47
|
-
"spec/
|
47
|
+
"spec/db/schema.rb",
|
48
48
|
"spec/money/acts_as_money_spec.rb",
|
49
|
+
"spec/money/exchange_bank_spec.rb",
|
49
50
|
"spec/money/money_spec.rb",
|
50
51
|
"spec/money/core_extensions_spec.rb",
|
51
|
-
"spec/db/schema.rb",
|
52
52
|
"spec/spec_helper.rb"
|
53
53
|
]
|
54
54
|
|
@@ -15,30 +15,48 @@ describe "Money core extensions" do
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
describe "String#to_money
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
18
|
+
describe "String#to_money" do
|
19
|
+
EXAMPLES = {
|
20
|
+
"20.15" => {:cents => Money.new(20_15), :no_cents => Money.new(20)},
|
21
|
+
"100" => {:cents => Money.new(100_00), :no_cents => Money.new(100)},
|
22
|
+
"100.37" => {:cents => Money.new(100_37), :no_cents => Money.new(100)},
|
23
|
+
"100,37" => {:cents => Money.new(100_37), :no_cents => Money.new(100)},
|
24
|
+
"100 000" => {:cents => Money.new(100_000_00), :no_cents => Money.new(100_000)},
|
25
|
+
"100 USD" => {:cents => Money.new(100_00, "USD"), :no_cents => Money.new(100, "USD")},
|
26
|
+
"-100 USD" => {:cents => Money.new(-100_00, "USD"), :no_cents => Money.new(-100, "USD")},
|
27
|
+
"100 EUR" => {:cents => Money.new(100_00, "EUR"), :no_cents => Money.new(100, "EUR")},
|
28
|
+
"$100 USD" => {:cents => Money.new(100_00, "USD"), :no_cents => Money.new(100, "USD")},
|
29
|
+
"USD 100" => {:cents => Money.new(100_00, "USD"), :no_cents => Money.new(100, "USD")},
|
30
|
+
"EUR 100" => {:cents => Money.new(100_00, "EUR"), :no_cents => Money.new(100, "EUR")},
|
31
|
+
"1,000.5" => {:cents => Money.new(1_000_50), :no_cents => Money.new(1_000) },
|
32
|
+
"1,000.51" => {:cents => Money.new(1_000_51), :no_cents => Money.new(1_000) },
|
33
|
+
"100.000,45" => {:cents => Money.new(100_000_45), :no_cents => Money.new(100_000)},
|
34
|
+
"-100.100,45" => {:cents => Money.new(-100_100_45), :no_cents => Money.new(-100_100)},
|
35
|
+
"1,000.505" => {:cents => Money.new(1_000_51), :no_cents => Money.new(1_000) },
|
36
|
+
"1,000.504" => {:cents => Money.new(1_000_50), :no_cents => Money.new(1_000) },
|
37
|
+
"100.37 EUR" => {:cents => Money.new(100_37, "EUR"), :no_cents => Money.new(100, "EUR")},
|
38
|
+
"100,37 EUR" => {:cents => Money.new(100_37, "EUR"), :no_cents => Money.new(100, "EUR")},
|
39
|
+
"EUR 100.37" => {:cents => Money.new(100_37, "EUR"), :no_cents => Money.new(100, "EUR")},
|
40
|
+
"CAD -100.37" => {:cents => Money.new(-100_37, "CAD"), :no_cents => Money.new(-100, "CAD")},
|
41
|
+
"EUR 100,37" => {:cents => Money.new(100_37, "EUR"), :no_cents => Money.new(100, "EUR")},
|
42
|
+
"EUR -100,37" => {:cents => Money.new(-100_37, "EUR"), :no_cents => Money.new(-100, "EUR")},
|
43
|
+
"BRL 100,37" => {:cents => Money.new(100_37, "BRL"), :no_cents => Money.new(100, "BRL")},
|
44
|
+
"BRL -100,37" => {:cents => Money.new(-100_37, "BRL"), :no_cents => Money.new(-100, "BRL")}
|
25
45
|
|
26
|
-
|
27
|
-
it { "-100 USD".to_money.should == Money.new(-100_00, "USD") }
|
28
|
-
it { "100 EUR".to_money.should == Money.new(100_00, "EUR") }
|
29
|
-
it { "100.37 EUR".to_money.should == Money.new(100_37, "EUR") }
|
30
|
-
it { "100,37 EUR".to_money.should == Money.new(100_37, "EUR") }
|
46
|
+
}
|
31
47
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
it { "EUR 100,37".to_money.should == Money.new(100_37, "EUR") }
|
37
|
-
it { "EUR -100,37".to_money.should == Money.new(-100_37, "EUR") }
|
48
|
+
EXAMPLES.each_pair do |string, expected_money|
|
49
|
+
it "should convert '#{string}' with cents by default" do
|
50
|
+
string.to_money.should == expected_money[:cents]
|
51
|
+
end
|
38
52
|
|
39
|
-
|
40
|
-
|
53
|
+
it "should convert '#{string}' without cents" do
|
54
|
+
string.to_money(true).should == expected_money[:no_cents]
|
55
|
+
end
|
41
56
|
|
42
|
-
|
57
|
+
it "should convert '#{string}' with cents" do
|
58
|
+
string.to_money(false).should == expected_money[:cents]
|
59
|
+
end
|
60
|
+
end
|
43
61
|
end
|
44
62
|
end
|
@@ -88,8 +88,7 @@ describe Money::ExchangeBank do
|
|
88
88
|
end
|
89
89
|
|
90
90
|
it "raises Money::UnknownRate upon conversion if the conversion rate is unknown" do
|
91
|
-
|
92
|
-
block.should raise_error(Money::UnknownRate)
|
91
|
+
lambda { @bank.exchange(10, "USD", "ABC") }.should raise_error(Money::UnknownRate)
|
93
92
|
end
|
94
93
|
|
95
94
|
describe "Fetching Data" do
|
@@ -122,6 +121,23 @@ describe Money::ExchangeBank do
|
|
122
121
|
@bank.get_rate("EUR", "USD").should be_close(1.4098, 0.001)
|
123
122
|
end
|
124
123
|
|
124
|
+
it "should fetch only what I want" do
|
125
|
+
Money.stub!(:default_currency).and_return("BRL")
|
126
|
+
@bank.default_rates = ["BRL", "EUR"]
|
127
|
+
@bank.fetch_rates
|
128
|
+
@bank.get_rate("DKK").should be_nil
|
129
|
+
@bank.get_rate("USD").should be_nil
|
130
|
+
@bank.get_rate("EUR").should be_close(2.832, 0.001)
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should be convert EUR to BRL with default USD" do
|
134
|
+
Money.stub!(:default_currency).and_return("USD")
|
135
|
+
@bank.default_rates = ["BRL", "EUR", "USD"]
|
136
|
+
@bank.fetch_rates
|
137
|
+
@bank.exchange(100, "BRL", "EUR").should be_close(2,2)
|
138
|
+
@bank.exchange(100, "EUR", "BRL")
|
139
|
+
end
|
140
|
+
|
125
141
|
end
|
126
142
|
|
127
143
|
describe "Live Fetching" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nofxx-money
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.3.
|
4
|
+
version: 2.3.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Money Team
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-06-20 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -73,9 +73,9 @@ signing_key:
|
|
73
73
|
specification_version: 3
|
74
74
|
summary: This library aids one in handling money and different currencies.
|
75
75
|
test_files:
|
76
|
-
- spec/
|
76
|
+
- spec/db/schema.rb
|
77
77
|
- spec/money/acts_as_money_spec.rb
|
78
|
+
- spec/money/exchange_bank_spec.rb
|
78
79
|
- spec/money/money_spec.rb
|
79
80
|
- spec/money/core_extensions_spec.rb
|
80
|
-
- spec/db/schema.rb
|
81
81
|
- spec/spec_helper.rb
|