money 3.7.1 → 4.0.0

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