money 3.7.1 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +384 -351
- data/LICENSE +21 -21
- data/README.md +243 -214
- data/Rakefile +49 -49
- data/lib/money.rb +28 -27
- data/lib/money/bank/base.rb +131 -131
- data/lib/money/bank/variable_exchange.rb +252 -252
- data/lib/money/core_extensions.rb +82 -82
- data/lib/money/currency.rb +263 -422
- data/lib/money/currency_loader.rb +19 -0
- data/lib/money/money.rb +405 -405
- data/lib/money/money/arithmetic.rb +246 -246
- data/lib/money/money/formatting.rb +260 -244
- data/lib/money/money/parsing.rb +350 -350
- data/money.gemspec +29 -35
- data/spec/bank/base_spec.rb +72 -72
- data/spec/bank/variable_exchange_spec.rb +238 -238
- data/spec/core_extensions_spec.rb +158 -158
- data/spec/currency_spec.rb +120 -133
- data/spec/money/arithmetic_spec.rb +479 -479
- data/spec/money/formatting_spec.rb +383 -375
- data/spec/money/parsing_spec.rb +197 -197
- data/spec/money_spec.rb +292 -292
- data/spec/spec_helper.rb +28 -28
- metadata +54 -126
- data/lib/money.rbc +0 -184
- data/lib/money/bank/base.rbc +0 -818
- data/lib/money/bank/variable_exchange.rbc +0 -2550
- data/lib/money/core_extensions.rbc +0 -664
- data/lib/money/currency.rbc +0 -22708
- data/lib/money/money.rbc +0 -3861
- data/lib/money/money/arithmetic.rbc +0 -2778
- data/lib/money/money/formatting.rbc +0 -2265
- data/lib/money/money/parsing.rbc +0 -2737
- data/spec/bank/base_spec.rbc +0 -2461
- data/spec/bank/variable_exchange_spec.rbc +0 -7541
- data/spec/core_extensions_spec.rbc +0 -5921
- data/spec/currency_spec.rbc +0 -4535
- data/spec/money/arithmetic_spec.rbc +0 -25140
- data/spec/money/formatting_spec.rbc +0 -12545
- data/spec/money/parsing_spec.rbc +0 -6511
- data/spec/money_spec.rbc +0 -9824
- data/spec/spec_helper.rbc +0 -575
data/LICENSE
CHANGED
@@ -1,21 +1,21 @@
|
|
1
|
-
Copyright (c) 2005 Tobias Lutke
|
2
|
-
Copyright (c) 2008 Phusion
|
3
|
-
|
4
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
5
|
-
a copy of this software and associated documentation files (the
|
6
|
-
"Software"), to deal in the Software without restriction, including
|
7
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
8
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
-
permit persons to whom the Software is furnished to do so, subject to
|
10
|
-
the following conditions:
|
11
|
-
|
12
|
-
The above copyright notice and this permission notice shall be
|
13
|
-
included in all copies or substantial portions of the Software.
|
14
|
-
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
1
|
+
Copyright (c) 2005 Tobias Lutke
|
2
|
+
Copyright (c) 2008 Phusion
|
3
|
+
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
a copy of this software and associated documentation files (the
|
6
|
+
"Software"), to deal in the Software without restriction, including
|
7
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -1,214 +1,243 @@
|
|
1
|
-
# RubyMoney - Money
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
- Provides a `Money
|
12
|
-
|
13
|
-
-
|
14
|
-
|
15
|
-
- Represents
|
16
|
-
|
17
|
-
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
- [
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
`
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
1
|
+
# RubyMoney - Money
|
2
|
+
|
3
|
+
[![Build Status](http://travis-ci.org/RubyMoney/money.png)](http://travis-ci.org/RubyMoney/money)
|
4
|
+
|
5
|
+
## Introduction
|
6
|
+
|
7
|
+
This library aids one in handling money and different currencies.
|
8
|
+
|
9
|
+
### Features
|
10
|
+
|
11
|
+
- Provides a `Money` class which encapsulates all information about an certain
|
12
|
+
amount of money, such as its value and its currency.
|
13
|
+
- Provides a `Money::Currency` class which encapsulates all information about
|
14
|
+
a monetary unit.
|
15
|
+
- Represents monetary values as integers, in cents. This avoids floating point
|
16
|
+
rounding errors.
|
17
|
+
- Represents currency as `Money::Currency` instances providing an high level of
|
18
|
+
flexibility.
|
19
|
+
- Provides APIs for exchanging money from one currency to another.
|
20
|
+
- Has the ability to parse a money and currency strings
|
21
|
+
into the corresponding Money/Currency object.
|
22
|
+
|
23
|
+
### Resources
|
24
|
+
|
25
|
+
- [Website](http://money.rubyforge.org)
|
26
|
+
- [API Documentation](http://money.rubyforge.org)
|
27
|
+
- [Git Repository](http://github.com/RubyMoney/money)
|
28
|
+
|
29
|
+
## Downloading
|
30
|
+
|
31
|
+
Install stable releases with the following command:
|
32
|
+
|
33
|
+
gem install money
|
34
|
+
|
35
|
+
The development version (hosted on Github) can be installed with:
|
36
|
+
|
37
|
+
git clone git://github.com/RubyMoney/money.git
|
38
|
+
cd money
|
39
|
+
rake install
|
40
|
+
|
41
|
+
## Usage
|
42
|
+
|
43
|
+
``` ruby
|
44
|
+
require 'money'
|
45
|
+
|
46
|
+
# 10.00 USD
|
47
|
+
money = Money.new(1000, "USD")
|
48
|
+
money.cents #=> 1000
|
49
|
+
money.currency #=> Currency.new("USD")
|
50
|
+
|
51
|
+
# Comparisons
|
52
|
+
Money.new(1000, "USD") == Money.new(1000, "USD") #=> true
|
53
|
+
Money.new(1000, "USD") == Money.new(100, "USD") #=> false
|
54
|
+
Money.new(1000, "USD") == Money.new(1000, "EUR") #=> false
|
55
|
+
Money.new(1000, "USD") != Money.new(1000, "EUR") #=> true
|
56
|
+
|
57
|
+
# Arithmetic
|
58
|
+
Money.new(1000, "USD") + Money.new(500, "USD") == Money.new(1500, "USD")
|
59
|
+
Money.new(1000, "USD") - Money.new(200, "USD") == Money.new(800, "USD")
|
60
|
+
Money.new(1000, "USD") / 5 == Money.new(200, "USD")
|
61
|
+
Money.new(1000, "USD") * 5 == Money.new(5000, "USD")
|
62
|
+
|
63
|
+
# Currency conversions
|
64
|
+
some_code_to_setup_exchange_rates
|
65
|
+
Money.new(1000, "USD").exchange_to("EUR") == Money.new(some_value, "EUR")
|
66
|
+
```
|
67
|
+
|
68
|
+
## Currency
|
69
|
+
|
70
|
+
Currencies are consistently represented as instances of `Money::Currency`.
|
71
|
+
The most part of `Money` APIs allows you to supply either a `String` or a
|
72
|
+
`Money::Currency`.
|
73
|
+
|
74
|
+
``` ruby
|
75
|
+
Money.new(1000, "USD") == Money.new(1000, Currency.new("USD"))
|
76
|
+
Money.new(1000, "EUR").currency == Currency.new("EUR")
|
77
|
+
```
|
78
|
+
|
79
|
+
A `Money::Currency` instance holds all the information about the currency,
|
80
|
+
including the currency symbol, name and much more.
|
81
|
+
|
82
|
+
``` ruby
|
83
|
+
currency = Money.new(1000, "USD").currency
|
84
|
+
currency.iso_code #=> "USD"
|
85
|
+
currency.name #=> "United States Dollar"
|
86
|
+
```
|
87
|
+
|
88
|
+
To define a new `Money::Currency` simply add a new item to the
|
89
|
+
`Money::Currency::TABLE` hash, where the key is the identifier for the currency
|
90
|
+
object and the value is a hash containing all the currency attributes.
|
91
|
+
|
92
|
+
``` ruby
|
93
|
+
Money::Currency::TABLE[:usd] = {
|
94
|
+
:priority => 1,
|
95
|
+
:iso_code => "USD",
|
96
|
+
:iso_numeric => "840",
|
97
|
+
:name => "United States Dollar",
|
98
|
+
:symbol => "$",
|
99
|
+
:subunit => "Cent"
|
100
|
+
:subunit_to_unit => 100,
|
101
|
+
:separator => ".",
|
102
|
+
:delimiter => ","
|
103
|
+
}
|
104
|
+
```
|
105
|
+
|
106
|
+
The pre-defined set of attributes includes:
|
107
|
+
|
108
|
+
- `:priority` a numerical value you can use to sort/group the currency list
|
109
|
+
- `:iso_code` the international 3-letter code as defined by the ISO 4217 standard
|
110
|
+
- `:iso_numeric` the international 3-digit code as defined by the ISO 4217 standard
|
111
|
+
- `:name` the currency name
|
112
|
+
- `:symbol` the currency symbol (UTF-8 encoded)
|
113
|
+
- `:subunit` the name of the fractional monetary unit
|
114
|
+
- `:subunit_to_unit` the proportion between the unit and the subunit
|
115
|
+
- `:separator` character between the whole and fraction amounts
|
116
|
+
- `:delimiter` character between each thousands place
|
117
|
+
|
118
|
+
All attributes are optional. Some attributes, such as `:symbol`, are used by
|
119
|
+
the Money class to print out a representation of the object. Other attributes,
|
120
|
+
such as `:name` or `:priority`, exist to provide a basic API you can take
|
121
|
+
advantage of to build your application.
|
122
|
+
|
123
|
+
### :priority
|
124
|
+
|
125
|
+
The priority attribute is an arbitrary numerical value you can assign to the
|
126
|
+
`Money::Currency` and use in sorting/grouping operation.
|
127
|
+
|
128
|
+
For instance, let's assume your Rails application needs to render a currency
|
129
|
+
selector like the one available
|
130
|
+
[here](http://finance.yahoo.com/currency-converter/). You can create a couple of
|
131
|
+
custom methods to return the list of major currencies and all currencies as
|
132
|
+
follows:
|
133
|
+
|
134
|
+
``` ruby
|
135
|
+
# Returns an array of currency id where
|
136
|
+
# priority < 10
|
137
|
+
def major_currencies(hash)
|
138
|
+
hash.inject([]) do |array, (id, attributes)|
|
139
|
+
priority = attributes[:priority]
|
140
|
+
if priority && priority < 10
|
141
|
+
array[priority] ||= []
|
142
|
+
array[priority] << id
|
143
|
+
end
|
144
|
+
array
|
145
|
+
end.compact.flatten
|
146
|
+
end
|
147
|
+
|
148
|
+
# Returns an array of all currency id
|
149
|
+
def all_currencies(hash)
|
150
|
+
hash.keys
|
151
|
+
end
|
152
|
+
|
153
|
+
major_currencies(Money::Currency::TABLE)
|
154
|
+
# => [ :usd, :eur, :bgp, :cad ]
|
155
|
+
|
156
|
+
all_currencies(Money::Currency::TABLE)
|
157
|
+
# => [ :aed, :afn, all, ... ]
|
158
|
+
```
|
159
|
+
|
160
|
+
### Default Currency
|
161
|
+
|
162
|
+
By default `Money` defaults to USD as its currency. This can be overwritten
|
163
|
+
using:
|
164
|
+
|
165
|
+
``` ruby
|
166
|
+
Money.default_currency = Money::Currency.new("CAD")
|
167
|
+
```
|
168
|
+
|
169
|
+
If you use Rails, then `environment.rb` is a very good place to put this.
|
170
|
+
|
171
|
+
## Currency Exchange
|
172
|
+
|
173
|
+
Exchanging money is performed through an exchange bank object. The default
|
174
|
+
exchange bank object requires one to manually specify the exchange rate. Here's
|
175
|
+
an example of how it works:
|
176
|
+
|
177
|
+
``` ruby
|
178
|
+
Money.add_rate("USD", "CAD", 1.24515)
|
179
|
+
Money.add_rate("CAD", "USD", 0.803115)
|
180
|
+
|
181
|
+
Money.us_dollar(100).exchange_to("CAD") # => Money.new(124, "CAD")
|
182
|
+
Money.ca_dollar(100).exchange_to("USD") # => Money.new(80, "USD")
|
183
|
+
```
|
184
|
+
|
185
|
+
Comparison and arithmetic operations work as expected:
|
186
|
+
|
187
|
+
``` ruby
|
188
|
+
Money.new(1000, "USD") <=> Money.new(900, "USD") # => 1; 9.00 USD is smaller
|
189
|
+
Money.new(1000, "EUR") + Money.new(10, "EUR") == Money.new(1010, "EUR")
|
190
|
+
|
191
|
+
Money.add_rate("USD", "EUR", 0.5)
|
192
|
+
Money.new(1000, "EUR") + Money.new(1000, "USD") == Money.new(1500, "EUR")
|
193
|
+
```
|
194
|
+
|
195
|
+
There is nothing stopping you from creating bank objects which scrapes
|
196
|
+
[XE](http://www.xe.com) for the current rates or just returns `rand(2)`:
|
197
|
+
|
198
|
+
``` ruby
|
199
|
+
Money.default_bank = ExchangeBankWhichScrapesXeDotCom.new
|
200
|
+
```
|
201
|
+
|
202
|
+
### Implementations
|
203
|
+
|
204
|
+
The following is a list of Money.gem compatible currency exchange rate
|
205
|
+
implementations.
|
206
|
+
|
207
|
+
- [eu_central_bank](http://github.com/RubyMoney/eu_central_bank)
|
208
|
+
- [google_currency](http://github.com/RubyMoney/google_currency)
|
209
|
+
- [nordea](https://github.com/k33l0r/nordea)
|
210
|
+
- [nbrb_currency](https://github.com/slbug/nbrb_currency)
|
211
|
+
|
212
|
+
## Ruby on Rails
|
213
|
+
|
214
|
+
Use the `composed_of` helper to let Active Record deal with embedding the money
|
215
|
+
object in your models. The following example requires 2 columns:
|
216
|
+
|
217
|
+
``` ruby
|
218
|
+
:price_cents, :integer, :default => 0, :null => false
|
219
|
+
:currency, :string
|
220
|
+
```
|
221
|
+
|
222
|
+
Then in your model file:
|
223
|
+
|
224
|
+
``` ruby
|
225
|
+
composed_of :price,
|
226
|
+
:class_name => "Money",
|
227
|
+
:mapping => [%w(price_cents cents), %w(currency currency_as_string)],
|
228
|
+
:constructor => Proc.new { |cents, currency| Money.new(cents || 0, currency || Money.default_currency) },
|
229
|
+
:converter => Proc.new { |value| value.respond_to?(:to_money) ? value.to_money : raise(ArgumentError, "Can't convert #{value.class} to Money") }
|
230
|
+
```
|
231
|
+
|
232
|
+
For Money 2.2.x and previous versions, simply use the following `composed_of`
|
233
|
+
definition:
|
234
|
+
|
235
|
+
``` ruby
|
236
|
+
composed_of :price,
|
237
|
+
:class_name => "Money",
|
238
|
+
:mapping => [%w(cents cents), %w(currency currency)],
|
239
|
+
:constructor => Proc.new { |cents, currency| Money.new(cents || 0, currency || Money.default_currency) }
|
240
|
+
```
|
241
|
+
|
242
|
+
Note the difference in the currency column mapping (currency_as_string vs. currency) - this matters! For further details read the full discussion
|
243
|
+
[here](http://github.com/RubyMoney/money/issues/4#comment_224880).
|