money 6.9.0 → 6.16.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +131 -3
- data/LICENSE +17 -17
- data/README.md +181 -71
- data/config/currency_backwards_compatible.json +65 -0
- data/config/currency_iso.json +119 -56
- data/config/currency_non_iso.json +35 -2
- data/lib/money/bank/variable_exchange.rb +22 -12
- data/lib/money/currency/loader.rb +15 -13
- data/lib/money/currency.rb +38 -39
- data/lib/money/locale_backend/base.rb +7 -0
- data/lib/money/locale_backend/currency.rb +11 -0
- data/lib/money/locale_backend/errors.rb +6 -0
- data/lib/money/locale_backend/i18n.rb +25 -0
- data/lib/money/locale_backend/legacy.rb +28 -0
- data/lib/money/money/allocation.rb +46 -0
- data/lib/money/money/arithmetic.rb +33 -15
- data/lib/money/money/constructors.rb +1 -2
- data/lib/money/money/formatter.rb +399 -0
- data/lib/money/money/formatting_rules.rb +142 -0
- data/lib/money/money/locale_backend.rb +22 -0
- data/lib/money/money.rb +235 -187
- data/lib/money/rates_store/memory.rb +24 -24
- data/lib/money/version.rb +1 -1
- data/money.gemspec +14 -8
- metadata +36 -56
- data/.coveralls.yml +0 -1
- data/.gitignore +0 -23
- data/.rspec +0 -1
- data/.travis.yml +0 -26
- data/AUTHORS +0 -126
- data/CONTRIBUTING.md +0 -17
- data/Gemfile +0 -16
- data/Rakefile +0 -17
- data/lib/money/money/formatting.rb +0 -426
- data/spec/bank/base_spec.rb +0 -79
- data/spec/bank/single_currency_spec.rb +0 -13
- data/spec/bank/variable_exchange_spec.rb +0 -265
- data/spec/currency/heuristics_spec.rb +0 -11
- data/spec/currency/loader_spec.rb +0 -19
- data/spec/currency_spec.rb +0 -359
- data/spec/money/arithmetic_spec.rb +0 -693
- data/spec/money/constructors_spec.rb +0 -103
- data/spec/money/formatting_spec.rb +0 -757
- data/spec/money_spec.rb +0 -778
- data/spec/rates_store/memory_spec.rb +0 -69
- data/spec/spec_helper.rb +0 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 3de47437ec002ed24a400508cac96b2ff6812f484c666fe3db3a82e921a805c0
|
4
|
+
data.tar.gz: f96755602e56ea81d734b7505e7cfc88caaa948d7a8d285eeb470801028c15b9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2f8cd71611e96a80cb733651675cb6fac59d358cb7c9576c8c264abbfec6eb1da11b8cbe2af12cdfb070e5dd01cd74f6fdc70772da16aa4c2abc5248b13fca3c
|
7
|
+
data.tar.gz: '092ba5a188eb29d462431e94420e1c6d7a7f9a4a59c0895f66a4a1cf92cfaa37cbc1bc344a241f5f8cc9fc4e998189164bc2d0ab11480a589fe7bb0e341754ba'
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,133 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 6.16.0
|
4
|
+
|
5
|
+
- Add `Money.from_cents` alias as a more explicit initializer, it's the same as `Money.new`
|
6
|
+
|
7
|
+
## 6.15.0
|
8
|
+
|
9
|
+
- Add :delimiter_pattern option to the Formatter
|
10
|
+
|
11
|
+
## 6.14.1
|
12
|
+
|
13
|
+
- Fix CHF format regression introduced in v6.14.0
|
14
|
+
- Fix deprecation warning in #format_decimal_part
|
15
|
+
|
16
|
+
## 6.14.0
|
17
|
+
|
18
|
+
- Fix Bahraini dinar symbol
|
19
|
+
- Raise exception when default currency is not set or passed as parameter
|
20
|
+
- Allow specifying default_bank as a lambda
|
21
|
+
- Allow passing a default format in currencies definition only valid without symbol_position
|
22
|
+
- Always allow comparison with zero Money
|
23
|
+
- Rename Money.infinite_precision to default_infinite_precision
|
24
|
+
- Add Currency.reset! method to reload all the default currency definitions
|
25
|
+
- Fix edgecase for Money#allocate when applying to array of all zero values
|
26
|
+
|
27
|
+
## 6.13.8
|
28
|
+
- Update symbol for XOF
|
29
|
+
- Update UYU currency symbol
|
30
|
+
- Allow double conversion using same bank
|
31
|
+
- Warn when using unsafe serializer for rate import
|
32
|
+
- Move Icelandic symbol after the amount
|
33
|
+
|
34
|
+
## 6.13.7
|
35
|
+
- Improve deprecation warnings for the upcoming major release
|
36
|
+
|
37
|
+
## 6.13.6
|
38
|
+
- Fix a regression introduced in 6.13.5 that broken RatesStore::Memory subclasses
|
39
|
+
|
40
|
+
## 6.13.5
|
41
|
+
- Raise warning on using Money.default_currency
|
42
|
+
- Raise warning on using default Money.rounding_mode
|
43
|
+
- Add Second Ouguiya MRU 929 to currency iso file
|
44
|
+
- Add symbol for UZS
|
45
|
+
- Use monitor for recursive mutual exclusion in RatesStore::Memory
|
46
|
+
- Allow passing store as a string to Money::Bank::VariableExchange (to support Rails 6)
|
47
|
+
|
48
|
+
## 6.13.4
|
49
|
+
- Update currency config for Zambian Kwacha (ZMW)
|
50
|
+
- Do not modify options passed to FormattingRules
|
51
|
+
|
52
|
+
## 6.13.3
|
53
|
+
- Remove specs from the packaged gem
|
54
|
+
- Use Currency::Loader directly without extending
|
55
|
+
- Add Money.with_rounding_mode as a replacement for calling Money.rounding_mode with a block
|
56
|
+
- Fix currency search for two digit ISO numbers
|
57
|
+
- Add description to TypeError raised by +/- operations
|
58
|
+
|
59
|
+
## 6.13.2
|
60
|
+
- Prevent Money initialization with non-finite amounts
|
61
|
+
- Convert the fractional value of a Money object to BigDecimal when initializing
|
62
|
+
- Offer replacements for currency position deprecations
|
63
|
+
- Fix Peruvian Sol symbol
|
64
|
+
- Lock i18n to <= 1.2.0 for older (< 2.3) rubies
|
65
|
+
- Prevent Divide By Zero in `Money#allocate`
|
66
|
+
|
67
|
+
## 6.13.1
|
68
|
+
- Add bolívar soberano (VES)
|
69
|
+
- Deprecate bolívar fuerte (VEF)
|
70
|
+
- Deprecate old `#format` rules passed as a symbol
|
71
|
+
- Clarify `use_i18n` deprecation
|
72
|
+
- Add `:currency` locale_backend for explicit per-currency localization
|
73
|
+
|
74
|
+
## 6.13.0
|
75
|
+
- Add :format option to the Formatter
|
76
|
+
- Add ruby 2.6.0 support
|
77
|
+
- Performance improvement (lazy stringify currency keys)
|
78
|
+
- Add `Money.locale_backend` for translation lookups
|
79
|
+
- Deprecate `use_i18n` flag in favour of `locale_backend = :i18n`
|
80
|
+
- Deprecate old formatting rules in favour of `:format`
|
81
|
+
- LVL and LTL are no longer used
|
82
|
+
- Add `Currency#iso?` for checking if currency is iso or not
|
83
|
+
- Relax versions-lock of `i18n` and `rspec` dependencies
|
84
|
+
- Add Bitcoin Cash
|
85
|
+
- Fix incorrect behaviour of `Currency#find_by_currency_iso` when given empty input
|
86
|
+
|
87
|
+
## 6.12.0
|
88
|
+
- Remove caching of `.empty`/`.zero`
|
89
|
+
- Preserve assigned bank when rounding
|
90
|
+
- Always round the fractional part when calling `#round`
|
91
|
+
- Wrap all amount parts when `:html_wrap` option is used
|
92
|
+
- Deprecate `#currency_as_string` and `#currency_as_string=` (in favour of `#with_currency`)
|
93
|
+
- Add `#with_currency` for swapping the currency
|
94
|
+
- Rewrite allocate/split (fixing some penny losing issues)
|
95
|
+
|
96
|
+
## 6.11.3
|
97
|
+
- Fix regression: if enabled use i18n locales in Money#to_s
|
98
|
+
|
99
|
+
## 6.11.2
|
100
|
+
- Fix regression: ignore formatting defaults for Money#to_s
|
101
|
+
|
102
|
+
## 6.11.1
|
103
|
+
- Fix issue with adding non-USD money to zero (used when calling `.sum` on an array)
|
104
|
+
|
105
|
+
## 6.11.0
|
106
|
+
- Support i18n 1.0
|
107
|
+
- Update yard dependency to 0.9.11
|
108
|
+
- Support for ruby 2.5.0
|
109
|
+
- Add inheritance for currency definitions
|
110
|
+
- Added new symbol for bitcoin denomination
|
111
|
+
- Specify custom rounding precision when using `infinite_precision`
|
112
|
+
- Allow splits with sums greater than 1
|
113
|
+
- Prevent arithmetic methods from losing reference to the bank
|
114
|
+
- Fix coerced zero numeric subtraction
|
115
|
+
- Fix south asian formatting to support whole numbers
|
116
|
+
- Refactor formatting logic
|
117
|
+
|
118
|
+
## 6.10.1
|
119
|
+
- Fix an issue with Money.empty memoization
|
120
|
+
|
121
|
+
## 6.10.0
|
122
|
+
- Added support for i18n version 0.9
|
123
|
+
- Disabled rounding when verifying allocation splits
|
124
|
+
- Added Chinese Yuan Offshore (CNH)
|
125
|
+
- Fixed html_entity for ARS
|
126
|
+
- Fixed KZT symbol
|
127
|
+
- Allowed comparing cross currency when both are zero
|
128
|
+
- Fixed memory rate store
|
129
|
+
- Corrected HUF subunit and thousands separator config
|
130
|
+
|
3
131
|
## 6.9.0
|
4
132
|
- Extracted heuristics into money-heuristics gem
|
5
133
|
|
@@ -148,7 +276,7 @@
|
|
148
276
|
- Works on Ruby 1.8.7
|
149
277
|
- Update deps
|
150
278
|
- Depreciate Money.parse
|
151
|
-
- Passing :
|
279
|
+
- Passing symbol: false when formatting 'JPY' currency in :ja locale
|
152
280
|
will work as expected
|
153
281
|
- Divide now obeys the specified rounding mode
|
154
282
|
- Add Money#round method. This is helpful when working in infinite_precision mode and would like to perform rounding at specific points in your work flow.
|
@@ -331,7 +459,7 @@ Features
|
|
331
459
|
|
332
460
|
Bugfixes
|
333
461
|
--------
|
334
|
-
- Fixed issue with #format(:
|
462
|
+
- Fixed issue with #format(no_cents: true) (thanks Romain & Julien)
|
335
463
|
|
336
464
|
Money 3.5.5
|
337
465
|
===========
|
@@ -418,7 +546,7 @@ Features
|
|
418
546
|
- Deprecated `Money#format` with separate params instead of Hash. Deprecation
|
419
547
|
target set to Money 3.5.0.
|
420
548
|
([#issue/31](http://github.com/RubyMoney/money/issues/31))
|
421
|
-
- Deprecated `Money#new(0, :
|
549
|
+
- Deprecated `Money#new(0, currency: "EUR")` in favor of
|
422
550
|
`Money#new(0, "EUR")`. Deprecation target set to Money 3.5.0.
|
423
551
|
([#issue/31](http://github.com/RubyMoney/money/issues/31))
|
424
552
|
- Throw ArgumentError when trying to multiply two Money objects together.
|
data/LICENSE
CHANGED
@@ -1,23 +1,23 @@
|
|
1
|
-
|
1
|
+
MIT License
|
2
2
|
|
3
3
|
Copyright (c) 2005 Tobias Lutke
|
4
4
|
Copyright (c) 2008 Phusion
|
5
|
+
Copyright (c) 2021 Shane Emmons
|
5
6
|
|
6
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
the following conditions:
|
7
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
of this software and associated documentation files (the "Software"), to deal
|
9
|
+
in the Software without restriction, including without limitation the rights
|
10
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
copies of the Software, and to permit persons to whom the Software is
|
12
|
+
furnished to do so, subject to the following conditions:
|
13
13
|
|
14
|
-
The above copyright notice and this permission notice shall be
|
15
|
-
|
14
|
+
The above copyright notice and this permission notice shall be included in all
|
15
|
+
copies or substantial portions of the Software.
|
16
16
|
|
17
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
OF
|
23
|
-
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
23
|
+
SOFTWARE.
|
data/README.md
CHANGED
@@ -3,9 +3,7 @@
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/money.svg)](https://rubygems.org/gems/money)
|
4
4
|
[![Build Status](https://travis-ci.org/RubyMoney/money.svg?branch=master)](https://travis-ci.org/RubyMoney/money)
|
5
5
|
[![Code Climate](https://codeclimate.com/github/RubyMoney/money.svg)](https://codeclimate.com/github/RubyMoney/money)
|
6
|
-
[![Coverage Status](https://coveralls.io/repos/RubyMoney/money/badge.svg?branch=master)](https://coveralls.io/r/RubyMoney/money?branch=master)
|
7
6
|
[![Inline docs](https://inch-ci.org/github/RubyMoney/money.svg)](https://inch-ci.org/github/RubyMoney/money)
|
8
|
-
[![Dependency Status](https://gemnasium.com/RubyMoney/money.svg)](https://gemnasium.com/RubyMoney/money)
|
9
7
|
[![License](https://img.shields.io/github/license/RubyMoney/money.svg)](https://opensource.org/licenses/MIT)
|
10
8
|
|
11
9
|
:warning: Please read the [migration notes](#migration-notes) before upgrading to a new major version.
|
@@ -22,7 +20,7 @@ A Ruby Library for dealing with money and currency conversion.
|
|
22
20
|
|
23
21
|
### Features
|
24
22
|
|
25
|
-
- Provides a `Money` class which encapsulates all information about
|
23
|
+
- Provides a `Money` class which encapsulates all information about a certain
|
26
24
|
amount of money, such as its value and its currency.
|
27
25
|
- Provides a `Money::Currency` class which encapsulates all information about
|
28
26
|
a monetary unit.
|
@@ -63,35 +61,38 @@ The development version (hosted on Github) can be installed with:
|
|
63
61
|
require 'money'
|
64
62
|
|
65
63
|
# 10.00 USD
|
66
|
-
money = Money.
|
64
|
+
money = Money.from_cents(1000, "USD")
|
67
65
|
money.cents #=> 1000
|
68
66
|
money.currency #=> Currency.new("USD")
|
69
67
|
|
70
68
|
# Comparisons
|
71
|
-
Money.
|
72
|
-
Money.
|
73
|
-
Money.
|
74
|
-
Money.
|
69
|
+
Money.from_cents(1000, "USD") == Money.from_cents(1000, "USD") #=> true
|
70
|
+
Money.from_cents(1000, "USD") == Money.from_cents(100, "USD") #=> false
|
71
|
+
Money.from_cents(1000, "USD") == Money.from_cents(1000, "EUR") #=> false
|
72
|
+
Money.from_cents(1000, "USD") != Money.from_cents(1000, "EUR") #=> true
|
75
73
|
|
76
74
|
# Arithmetic
|
77
|
-
Money.
|
78
|
-
Money.
|
79
|
-
Money.
|
80
|
-
Money.
|
75
|
+
Money.from_cents(1000, "USD") + Money.from_cents(500, "USD") == Money.from_cents(1500, "USD")
|
76
|
+
Money.from_cents(1000, "USD") - Money.from_cents(200, "USD") == Money.from_cents(800, "USD")
|
77
|
+
Money.from_cents(1000, "USD") / 5 == Money.from_cents(200, "USD")
|
78
|
+
Money.from_cents(1000, "USD") * 5 == Money.from_cents(5000, "USD")
|
81
79
|
|
82
80
|
# Unit to subunit conversions
|
83
|
-
Money.from_amount(5, "USD") == Money.
|
84
|
-
Money.from_amount(5, "JPY") == Money.
|
85
|
-
Money.from_amount(5, "TND") == Money.
|
81
|
+
Money.from_amount(5, "USD") == Money.from_cents(500, "USD") # 5 USD
|
82
|
+
Money.from_amount(5, "JPY") == Money.from_cents(5, "JPY") # 5 JPY
|
83
|
+
Money.from_amount(5, "TND") == Money.from_cents(5000, "TND") # 5 TND
|
86
84
|
|
87
85
|
# Currency conversions
|
88
86
|
some_code_to_setup_exchange_rates
|
89
|
-
Money.
|
87
|
+
Money.from_cents(1000, "USD").exchange_to("EUR") == Money.from_cents(some_value, "EUR")
|
88
|
+
|
89
|
+
# Swap currency
|
90
|
+
Money.from_cents(1000, "USD").with_currency("EUR") == Money.from_cents(1000, "EUR")
|
90
91
|
|
91
92
|
# Formatting (see Formatting section for more options)
|
92
|
-
Money.
|
93
|
-
Money.
|
94
|
-
Money.
|
93
|
+
Money.from_cents(100, "USD").format #=> "$1.00"
|
94
|
+
Money.from_cents(100, "GBP").format #=> "£1.00"
|
95
|
+
Money.from_cents(100, "EUR").format #=> "€1.00"
|
95
96
|
```
|
96
97
|
|
97
98
|
## Currency
|
@@ -101,15 +102,15 @@ The most part of `Money` APIs allows you to supply either a `String` or a
|
|
101
102
|
`Money::Currency`.
|
102
103
|
|
103
104
|
``` ruby
|
104
|
-
Money.
|
105
|
-
Money.
|
105
|
+
Money.from_cents(1000, "USD") == Money.from_cents(1000, Money::Currency.new("USD"))
|
106
|
+
Money.from_cents(1000, "EUR").currency == Money::Currency.new("EUR")
|
106
107
|
```
|
107
108
|
|
108
109
|
A `Money::Currency` instance holds all the information about the currency,
|
109
110
|
including the currency symbol, name and much more.
|
110
111
|
|
111
112
|
``` ruby
|
112
|
-
currency = Money.
|
113
|
+
currency = Money.from_cents(1000, "USD").currency
|
113
114
|
currency.iso_code #=> "USD"
|
114
115
|
currency.name #=> "United States Dollar"
|
115
116
|
```
|
@@ -119,15 +120,15 @@ below.
|
|
119
120
|
|
120
121
|
``` ruby
|
121
122
|
curr = {
|
122
|
-
:
|
123
|
-
:
|
124
|
-
:
|
125
|
-
:
|
126
|
-
:
|
127
|
-
:
|
128
|
-
:
|
129
|
-
:
|
130
|
-
:
|
123
|
+
priority: 1,
|
124
|
+
iso_code: "USD",
|
125
|
+
iso_numeric: "840",
|
126
|
+
name: "United States Dollar",
|
127
|
+
symbol: "$",
|
128
|
+
subunit: "Cent",
|
129
|
+
subunit_to_unit: 100,
|
130
|
+
decimal_mark: ".",
|
131
|
+
thousands_separator: ","
|
131
132
|
}
|
132
133
|
|
133
134
|
Money::Currency.register(curr)
|
@@ -142,8 +143,8 @@ The pre-defined set of attributes includes:
|
|
142
143
|
- `:symbol` the currency symbol (UTF-8 encoded)
|
143
144
|
- `:subunit` the name of the fractional monetary unit
|
144
145
|
- `:subunit_to_unit` the proportion between the unit and the subunit
|
145
|
-
- `:
|
146
|
-
- `:
|
146
|
+
- `:decimal_mark` character between the whole and fraction amounts
|
147
|
+
- `:thousands_separator` character between each thousands place
|
147
148
|
|
148
149
|
All attributes except `:iso_code` are optional. Some attributes, such as
|
149
150
|
`:symbol`, are used by the Money class to print out a representation of the
|
@@ -196,7 +197,7 @@ using:
|
|
196
197
|
Money.default_currency = Money::Currency.new("CAD")
|
197
198
|
```
|
198
199
|
|
199
|
-
If you use Rails, then `
|
200
|
+
If you use [Rails](https://github.com/RubyMoney/money/tree/master#ruby-on-rails), then `config/initializers/money.rb` is a very good place to put this.
|
200
201
|
|
201
202
|
### Currency Exponent
|
202
203
|
|
@@ -229,18 +230,18 @@ an example of how it works:
|
|
229
230
|
Money.add_rate("USD", "CAD", 1.24515)
|
230
231
|
Money.add_rate("CAD", "USD", 0.803115)
|
231
232
|
|
232
|
-
Money.us_dollar(100).exchange_to("CAD") # => Money.
|
233
|
-
Money.ca_dollar(100).exchange_to("USD") # => Money.
|
233
|
+
Money.us_dollar(100).exchange_to("CAD") # => Money.from_cents(124, "CAD")
|
234
|
+
Money.ca_dollar(100).exchange_to("USD") # => Money.from_cents(80, "USD")
|
234
235
|
```
|
235
236
|
|
236
237
|
Comparison and arithmetic operations work as expected:
|
237
238
|
|
238
239
|
``` ruby
|
239
|
-
Money.
|
240
|
-
Money.
|
240
|
+
Money.from_cents(1000, "USD") <=> Money.from_cents(900, "USD") # => 1; 9.00 USD is smaller
|
241
|
+
Money.from_cents(1000, "EUR") + Money.from_cents(10, "EUR") == Money.from_cents(1010, "EUR")
|
241
242
|
|
242
243
|
Money.add_rate("USD", "EUR", 0.5)
|
243
|
-
Money.
|
244
|
+
Money.from_cents(1000, "EUR") + Money.from_cents(1000, "USD") == Money.from_cents(1500, "EUR")
|
244
245
|
```
|
245
246
|
|
246
247
|
### Exchange rate stores
|
@@ -251,7 +252,7 @@ The default bank is initialized with an in-memory store for exchange rates.
|
|
251
252
|
Money.default_bank = Money::Bank::VariableExchange.new(Money::RatesStore::Memory.new)
|
252
253
|
```
|
253
254
|
|
254
|
-
You can pass
|
255
|
+
You can pass your own store implementation, i.e. for storing and retrieving rates off a database, file, cache, etc.
|
255
256
|
|
256
257
|
```ruby
|
257
258
|
Money.default_bank = Money::Bank::VariableExchange.new(MyCustomStore.new)
|
@@ -268,7 +269,7 @@ Stores must implement the following interface:
|
|
268
269
|
# @return [Numeric] rate.
|
269
270
|
def add_rate(iso_from, iso_to, rate); end
|
270
271
|
|
271
|
-
# Get rate. Must be idempotent.
|
272
|
+
# Get rate. Must be idempotent. i.e. adding the same rate must not produce duplicates.
|
272
273
|
# @param [String] iso_from Currency ISO code. ex. 'USD'
|
273
274
|
# @param [String] iso_to Currency ISO code. ex. 'CAD'
|
274
275
|
#
|
@@ -312,25 +313,35 @@ def marshal_dump; end
|
|
312
313
|
The following example implements an `ActiveRecord` store to save exchange rates to a database.
|
313
314
|
|
314
315
|
```ruby
|
315
|
-
#
|
316
|
+
# rails g model exchange_rate from:string to:string rate:float
|
316
317
|
|
317
|
-
class ExchangeRate <
|
318
|
+
class ExchangeRate < ApplicationRecord
|
318
319
|
def self.get_rate(from_iso_code, to_iso_code)
|
319
|
-
rate = find_by(:
|
320
|
-
rate
|
320
|
+
rate = find_by(from: from_iso_code, to: to_iso_code)
|
321
|
+
rate&.rate
|
321
322
|
end
|
322
323
|
|
323
324
|
def self.add_rate(from_iso_code, to_iso_code, rate)
|
324
|
-
exrate = find_or_initialize_by(:
|
325
|
+
exrate = find_or_initialize_by(from: from_iso_code, to: to_iso_code)
|
325
326
|
exrate.rate = rate
|
326
327
|
exrate.save!
|
327
328
|
end
|
329
|
+
|
330
|
+
def self.each_rate
|
331
|
+
return find_each unless block_given?
|
332
|
+
|
333
|
+
find_each do |rate|
|
334
|
+
yield rate.from, rate.to, rate.rate
|
335
|
+
end
|
336
|
+
end
|
328
337
|
end
|
329
338
|
```
|
330
339
|
|
331
340
|
Now you can use it with the default bank.
|
332
341
|
|
333
342
|
```ruby
|
343
|
+
# For Rails 6 pass model name as a string to make it compatible with zeitwerk
|
344
|
+
# Money.default_bank = Money::Bank::VariableExchange.new("ExchangeRate")
|
334
345
|
Money.default_bank = Money::Bank::VariableExchange.new(ExchangeRate)
|
335
346
|
|
336
347
|
# Add to the underlying store
|
@@ -338,7 +349,7 @@ Money.default_bank.add_rate('USD', 'CAD', 0.9)
|
|
338
349
|
# Retrieve from the underlying store
|
339
350
|
Money.default_bank.get_rate('USD', 'CAD') # => 0.9
|
340
351
|
# Exchanging amounts just works.
|
341
|
-
Money.
|
352
|
+
Money.from_cents(1000, 'USD').exchange_to('CAD') #=> #<Money fractional:900 currency:CAD>
|
342
353
|
```
|
343
354
|
|
344
355
|
There is nothing stopping you from creating store objects which scrapes
|
@@ -378,61 +389,160 @@ implementations.
|
|
378
389
|
- [russian_central_bank](https://github.com/rmustafin/russian_central_bank)
|
379
390
|
- [money-uphold-bank](https://github.com/subvisual/money-uphold-bank)
|
380
391
|
|
392
|
+
## Formatting
|
393
|
+
|
394
|
+
There are several formatting rules for when `Money#format` is called. For more information, check out the [formatting module source](https://github.com/RubyMoney/money/blob/master/lib/money/money/formatter.rb), or read the latest release's [rdoc version](http://www.rubydoc.info/gems/money/Money/Formatter).
|
395
|
+
|
396
|
+
If you wish to format money according to the EU's [Rules for expressing monetary units](http://publications.europa.eu/code/en/en-370303.htm#position) in either English, Irish, Latvian or Maltese:
|
397
|
+
|
398
|
+
```ruby
|
399
|
+
m = Money.from_cents('123', :gbp) # => #<Money fractional:123 currency:GBP>
|
400
|
+
m.format(symbol: m.currency.to_s + ' ') # => "GBP 1.23"
|
401
|
+
```
|
402
|
+
|
403
|
+
## Rounding
|
404
|
+
|
405
|
+
By default, `Money` objects are rounded to the nearest cent and the additional precision is not preserved:
|
406
|
+
|
407
|
+
```ruby
|
408
|
+
Money.from_amount(2.34567).format #=> "$2.35"
|
409
|
+
```
|
410
|
+
|
411
|
+
To retain the additional precision, you will also need to set `infinite_precision` to `true`.
|
412
|
+
|
413
|
+
```ruby
|
414
|
+
Money.default_infinite_precision = true
|
415
|
+
Money.from_amount(2.34567).format #=> "$2.34567"
|
416
|
+
```
|
417
|
+
|
418
|
+
To round to the nearest cent (or anything more precise), you can use the `round` method. However, note that the `round` method on a `Money` object does not work the same way as a normal Ruby `Float` object. Money's `round` method accepts different arguments. The first argument to the round method is the rounding mode, while the second argument is the level of precision relative to the cent.
|
419
|
+
|
420
|
+
```
|
421
|
+
# Float
|
422
|
+
2.34567.round #=> 2
|
423
|
+
2.34567.round(2) #=> 2.35
|
424
|
+
|
425
|
+
# Money
|
426
|
+
Money.default_infinite_precision = true
|
427
|
+
Money.from_cents(2.34567).format #=> "$0.0234567"
|
428
|
+
Money.from_cents(2.34567).round.format #=> "$0.02"
|
429
|
+
Money.from_cents(2.34567).round(BigDecimal::ROUND_HALF_UP, 2).format #=> "$0.0235"
|
430
|
+
```
|
431
|
+
|
432
|
+
You can set the default rounding mode by passing one of the `BigDecimal` mode enumerables like so:
|
433
|
+
```ruby
|
434
|
+
Money.rounding_mode = BigDecimal::ROUND_HALF_EVEN
|
435
|
+
```
|
436
|
+
See [BigDecimal::ROUND_MODE](https://ruby-doc.org/stdlib-2.5.1/libdoc/bigdecimal/rdoc/BigDecimal.html#ROUND_MODE) for more information
|
437
|
+
|
381
438
|
## Ruby on Rails
|
382
439
|
|
383
440
|
To integrate money in a Rails application use [money-rails](https://github.com/RubyMoney/money-rails).
|
384
441
|
|
385
442
|
For deprecated methods of integrating with Rails, check [the wiki](https://github.com/RubyMoney/money/wiki).
|
386
443
|
|
387
|
-
##
|
444
|
+
## Localization
|
388
445
|
|
389
|
-
|
390
|
-
currencies this can be defined in your `I18n` translation files.
|
446
|
+
In order to localize formatting you can use `I18n` gem:
|
391
447
|
|
392
|
-
|
448
|
+
```ruby
|
449
|
+
Money.locale_backend = :i18n
|
450
|
+
```
|
451
|
+
|
452
|
+
With this enabled a thousands seperator and a decimal mark will get looked up in your `I18n` translation files. In a Rails application this may look like:
|
393
453
|
|
394
454
|
```yml
|
395
455
|
# config/locale/en.yml
|
396
456
|
en:
|
397
|
-
number:
|
398
|
-
format:
|
399
|
-
delimiter: ","
|
400
|
-
separator: "."
|
401
|
-
# or
|
402
457
|
number:
|
403
458
|
currency:
|
404
459
|
format:
|
405
460
|
delimiter: ","
|
406
461
|
separator: "."
|
462
|
+
# falling back to
|
463
|
+
number:
|
464
|
+
format:
|
465
|
+
delimiter: ","
|
466
|
+
separator: "."
|
407
467
|
```
|
408
468
|
|
409
|
-
For this example `Money.
|
410
|
-
kr` which otherwise
|
469
|
+
For this example `Money.from_cents(123456789, "SEK").format` will return `1,234,567.89
|
470
|
+
kr` which otherwise would have returned `1 234 567,89 kr`.
|
471
|
+
|
472
|
+
This will work seamlessly with [rails-i18n](https://github.com/svenfuchs/rails-i18n) gem that already has a lot of locales defined.
|
473
|
+
|
474
|
+
If you wish to disable this feature and use defaults instead:
|
411
475
|
|
412
|
-
If you wish to disable this feature:
|
413
476
|
``` ruby
|
414
|
-
Money.
|
477
|
+
Money.locale_backend = nil
|
415
478
|
```
|
416
479
|
|
417
|
-
###
|
480
|
+
### Deprecation
|
418
481
|
|
419
|
-
|
482
|
+
The current default behaviour always checks the I18n locale first, falling back to "per currency"
|
483
|
+
localization. This is now deprecated and will be removed in favour of explicitly defined behaviour
|
484
|
+
in the next major release.
|
420
485
|
|
421
|
-
|
486
|
+
If you would like to use I18n localization (formatting depends on the locale):
|
422
487
|
|
423
|
-
|
424
|
-
|
425
|
-
|
488
|
+
```ruby
|
489
|
+
Money.locale_backend = :i18n
|
490
|
+
|
491
|
+
# example (using default localization from rails-i18n):
|
492
|
+
I18n.locale = :en
|
493
|
+
Money.from_cents(10_000_00, 'USD').format # => $10,000.00
|
494
|
+
Money.from_cents(10_000_00, 'EUR').format # => €10,000.00
|
495
|
+
|
496
|
+
I18n.locale = :es
|
497
|
+
Money.from_cents(10_000_00, 'USD').format # => $10.000,00
|
498
|
+
Money.from_cents(10_000_00, 'EUR').format # => €10.000,00
|
426
499
|
```
|
427
500
|
|
428
|
-
|
501
|
+
If you need to localize the position of the currency symbol, you
|
502
|
+
have to pass it manually. *Note: this will become the default formatting
|
503
|
+
behavior in the next version.*
|
429
504
|
|
430
|
-
|
505
|
+
```ruby
|
506
|
+
I18n.locale = :fr
|
507
|
+
format = I18n.t :format, scope: 'number.currency.format'
|
508
|
+
Money.from_cents(10_00, 'EUR').format(format: format) # => 10,00 €
|
509
|
+
```
|
510
|
+
|
511
|
+
For the legacy behaviour of "per currency" localization (formatting depends only on currency):
|
431
512
|
|
432
|
-
If you wish to format money according to the EU's [Rules for expressing monetary units](http://publications.europa.eu/code/en/en-370303.htm#position) in either English, Irish, Latvian or Maltese:
|
433
513
|
```ruby
|
434
|
-
|
435
|
-
|
514
|
+
Money.locale_backend = :currency
|
515
|
+
|
516
|
+
# example:
|
517
|
+
Money.from_cents(10_000_00, 'USD').format # => $10,000.00
|
518
|
+
Money.from_cents(10_000_00, 'EUR').format # => €10.000,00
|
519
|
+
```
|
520
|
+
|
521
|
+
In case you don't need localization and would like to use default values (can be redefined using
|
522
|
+
`Money.default_formatting_rules`):
|
523
|
+
|
524
|
+
```ruby
|
525
|
+
Money.locale_backend = nil
|
526
|
+
|
527
|
+
# example:
|
528
|
+
Money.from_cents(10_000_00, 'USD').format # => $10000.00
|
529
|
+
Money.from_cents(10_000_00, 'EUR').format # => €10000.00
|
530
|
+
```
|
531
|
+
|
532
|
+
## Collection
|
533
|
+
|
534
|
+
In case you're working with collections of `Money` instances, have a look at [money-collection](https://github.com/RubyMoney/money-collection)
|
535
|
+
for improved performance and accuracy.
|
536
|
+
|
537
|
+
### Troubleshooting
|
538
|
+
|
539
|
+
If you don't have some locale and don't want to get a runtime error such as:
|
540
|
+
|
541
|
+
I18n::InvalidLocale: :en is not a valid locale
|
542
|
+
|
543
|
+
Set the following:
|
544
|
+
``` ruby
|
545
|
+
I18n.enforce_available_locales = false
|
436
546
|
```
|
437
547
|
|
438
548
|
## Heuristics
|