money 6.12.0 → 6.13.0
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.
- checksums.yaml +4 -4
- data/.travis.yml +3 -1
- data/AUTHORS +1 -0
- data/CHANGELOG.md +13 -0
- data/README.md +20 -15
- data/config/currency_backwards_compatible.json +30 -0
- data/config/currency_iso.json +0 -30
- data/config/currency_non_iso.json +16 -0
- data/lib/money/currency.rb +16 -5
- data/lib/money/locale_backend/base.rb +7 -0
- data/lib/money/locale_backend/errors.rb +6 -0
- data/lib/money/locale_backend/i18n.rb +24 -0
- data/lib/money/locale_backend/legacy.rb +28 -0
- data/lib/money/money.rb +28 -5
- data/lib/money/money/formatter.rb +54 -77
- data/lib/money/money/formatting_rules.rb +51 -2
- data/lib/money/money/locale_backend.rb +20 -0
- data/lib/money/version.rb +1 -1
- data/money.gemspec +8 -2
- data/spec/currency_spec.rb +15 -0
- data/spec/locale_backend/i18n_spec.rb +62 -0
- data/spec/locale_backend/legacy_spec.rb +74 -0
- data/spec/money/formatting_spec.rb +60 -0
- data/spec/money/locale_backend_spec.rb +14 -0
- data/spec/money_spec.rb +16 -0
- metadata +23 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7929d62cf482b5ad0876b0ff4950440cec3051ff
|
4
|
+
data.tar.gz: 8b40765349b517c8182f20de9378ad14b76eb863
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1bc3a9c7fc84b6c4cd7e78d2dbe7bd666ab25f0715523953751984405f0ae858396e20e7bf0d8199b50c1d94d5947a1d3b0308094f3f2b347f07c93b655b28f1
|
7
|
+
data.tar.gz: 1a1dae32b195ccb6a93125fd2526e1c60e24c794cdd26fc08eb6254a1e6f8f4c0aef270ac215d1606b5163f7a1690443230161a75a5e522f72aa824b1f6f2efd
|
data/.travis.yml
CHANGED
data/AUTHORS
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 6.13.0
|
4
|
+
- Add :format option to the Formatter
|
5
|
+
- Add ruby 2.6.0 support
|
6
|
+
- Performance improvement (lazy stringify currency keys)
|
7
|
+
- Add `Money.locale_backend` for translation lookups
|
8
|
+
- Deprecate `use_i18n` flag in favour of `locale_backend = :i18n`
|
9
|
+
- Deprecate old formatting rules in favour of `:format`
|
10
|
+
- LVL and LTL are no longer used
|
11
|
+
- Add `Currency#iso?` for checking if currency is iso or not
|
12
|
+
- Relax versions-lock of `i18n` and `rspec` dependencies
|
13
|
+
- Add Bitcoin Cash
|
14
|
+
- Fix incorrect behaviour of `Currency#find_by_currency_iso` when given empty input
|
15
|
+
|
3
16
|
## 6.12.0
|
4
17
|
- Remove caching of `.empty`/`.zero`
|
5
18
|
- Preserve assigned bank when rounding
|
data/README.md
CHANGED
@@ -5,7 +5,6 @@
|
|
5
5
|
[](https://codeclimate.com/github/RubyMoney/money)
|
6
6
|
[](https://coveralls.io/r/RubyMoney/money?branch=master)
|
7
7
|
[](https://inch-ci.org/github/RubyMoney/money)
|
8
|
-
[](https://gemnasium.com/RubyMoney/money)
|
9
8
|
[](https://opensource.org/licenses/MIT)
|
10
9
|
|
11
10
|
:warning: Please read the [migration notes](#migration-notes) before upgrading to a new major version.
|
@@ -199,7 +198,7 @@ using:
|
|
199
198
|
Money.default_currency = Money::Currency.new("CAD")
|
200
199
|
```
|
201
200
|
|
202
|
-
If you use Rails, then `
|
201
|
+
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.
|
203
202
|
|
204
203
|
### Currency Exponent
|
205
204
|
|
@@ -399,34 +398,40 @@ To integrate money in a Rails application use [money-rails](https://github.com/R
|
|
399
398
|
|
400
399
|
For deprecated methods of integrating with Rails, check [the wiki](https://github.com/RubyMoney/money/wiki).
|
401
400
|
|
402
|
-
##
|
401
|
+
## Localization
|
403
402
|
|
404
|
-
|
405
|
-
currencies this can be defined in your `I18n` translation files.
|
403
|
+
In order to localize formatting you can use `I18n` gem:
|
406
404
|
|
407
|
-
|
405
|
+
```ruby
|
406
|
+
Money.locale_backend = :i18n
|
407
|
+
```
|
408
|
+
|
409
|
+
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:
|
408
410
|
|
409
411
|
```yml
|
410
412
|
# config/locale/en.yml
|
411
413
|
en:
|
412
|
-
number:
|
413
|
-
format:
|
414
|
-
delimiter: ","
|
415
|
-
separator: "."
|
416
|
-
# or
|
417
414
|
number:
|
418
415
|
currency:
|
419
416
|
format:
|
420
417
|
delimiter: ","
|
421
418
|
separator: "."
|
419
|
+
# falling back to
|
420
|
+
number:
|
421
|
+
format:
|
422
|
+
delimiter: ","
|
423
|
+
separator: "."
|
422
424
|
```
|
423
425
|
|
424
426
|
For this example `Money.new(123456789, "SEK").format` will return `1,234,567.89
|
425
|
-
kr` which otherwise
|
427
|
+
kr` which otherwise would have returned `1 234 567,89 kr`.
|
428
|
+
|
429
|
+
This will work seamlessly with [rails-i18n](https://github.com/svenfuchs/rails-i18n) gem that already has a lot of locales defined.
|
430
|
+
|
431
|
+
If you wish to disable this feature and use defaults instead:
|
426
432
|
|
427
|
-
If you wish to disable this feature:
|
428
433
|
``` ruby
|
429
|
-
Money.
|
434
|
+
Money.locale_backend = nil
|
430
435
|
```
|
431
436
|
|
432
437
|
## Collection
|
@@ -436,7 +441,7 @@ for improved performance and accuracy.
|
|
436
441
|
|
437
442
|
### Troubleshooting
|
438
443
|
|
439
|
-
If you get a runtime error such as:
|
444
|
+
If you don't have some locale and don't want to get a runtime error such as:
|
440
445
|
|
441
446
|
I18n::InvalidLocale: :en is not a valid locale
|
442
447
|
|
@@ -30,6 +30,36 @@
|
|
30
30
|
"iso_numeric": "288",
|
31
31
|
"smallest_denomination": 1
|
32
32
|
},
|
33
|
+
"ltl": {
|
34
|
+
"priority": 100,
|
35
|
+
"iso_code": "LTL",
|
36
|
+
"name": "Lithuanian Litas",
|
37
|
+
"symbol": "Lt",
|
38
|
+
"alternate_symbols": [],
|
39
|
+
"subunit": "Centas",
|
40
|
+
"subunit_to_unit": 100,
|
41
|
+
"symbol_first": false,
|
42
|
+
"html_entity": "",
|
43
|
+
"decimal_mark": ".",
|
44
|
+
"thousands_separator": ",",
|
45
|
+
"iso_numeric": "440",
|
46
|
+
"smallest_denomination": 1
|
47
|
+
},
|
48
|
+
"lvl": {
|
49
|
+
"priority": 100,
|
50
|
+
"iso_code": "LVL",
|
51
|
+
"name": "Latvian Lats",
|
52
|
+
"symbol": "Ls",
|
53
|
+
"alternate_symbols": [],
|
54
|
+
"subunit": "Santīms",
|
55
|
+
"subunit_to_unit": 100,
|
56
|
+
"symbol_first": true,
|
57
|
+
"html_entity": "",
|
58
|
+
"decimal_mark": ".",
|
59
|
+
"thousands_separator": ",",
|
60
|
+
"iso_numeric": "428",
|
61
|
+
"smallest_denomination": 1
|
62
|
+
},
|
33
63
|
"mtl": {
|
34
64
|
"priority": 100,
|
35
65
|
"iso_code": "MTL",
|
data/config/currency_iso.json
CHANGED
@@ -1291,36 +1291,6 @@
|
|
1291
1291
|
"iso_numeric": "426",
|
1292
1292
|
"smallest_denomination": 1
|
1293
1293
|
},
|
1294
|
-
"ltl": {
|
1295
|
-
"priority": 100,
|
1296
|
-
"iso_code": "LTL",
|
1297
|
-
"name": "Lithuanian Litas",
|
1298
|
-
"symbol": "Lt",
|
1299
|
-
"alternate_symbols": [],
|
1300
|
-
"subunit": "Centas",
|
1301
|
-
"subunit_to_unit": 100,
|
1302
|
-
"symbol_first": false,
|
1303
|
-
"html_entity": "",
|
1304
|
-
"decimal_mark": ".",
|
1305
|
-
"thousands_separator": ",",
|
1306
|
-
"iso_numeric": "440",
|
1307
|
-
"smallest_denomination": 1
|
1308
|
-
},
|
1309
|
-
"lvl": {
|
1310
|
-
"priority": 100,
|
1311
|
-
"iso_code": "LVL",
|
1312
|
-
"name": "Latvian Lats",
|
1313
|
-
"symbol": "Ls",
|
1314
|
-
"alternate_symbols": [],
|
1315
|
-
"subunit": "Santīms",
|
1316
|
-
"subunit_to_unit": 100,
|
1317
|
-
"symbol_first": true,
|
1318
|
-
"html_entity": "",
|
1319
|
-
"decimal_mark": ".",
|
1320
|
-
"thousands_separator": ",",
|
1321
|
-
"iso_numeric": "428",
|
1322
|
-
"smallest_denomination": 1
|
1323
|
-
},
|
1324
1294
|
"lyd": {
|
1325
1295
|
"priority": 100,
|
1326
1296
|
"iso_code": "LYD",
|
@@ -1,4 +1,20 @@
|
|
1
1
|
{
|
2
|
+
"bch": {
|
3
|
+
"priority": 100,
|
4
|
+
"iso_code": "BCH",
|
5
|
+
"name": "Bitcoin Cash",
|
6
|
+
"symbol": "₿",
|
7
|
+
"disambiguate_symbol": "₿CH",
|
8
|
+
"alternate_symbols": ["BCH"],
|
9
|
+
"subunit": "Satoshi",
|
10
|
+
"subunit_to_unit": 100000000,
|
11
|
+
"symbol_first": false,
|
12
|
+
"html_entity": "₿",
|
13
|
+
"decimal_mark": ".",
|
14
|
+
"thousands_separator": ",",
|
15
|
+
"iso_numeric": "",
|
16
|
+
"smallest_denomination": 1
|
17
|
+
},
|
2
18
|
"btc": {
|
3
19
|
"priority": 100,
|
4
20
|
"iso_code": "BTC",
|
data/lib/money/currency.rb
CHANGED
@@ -79,7 +79,8 @@ class Money
|
|
79
79
|
# Money::Currency.find_by_iso_numeric('001') #=> nil
|
80
80
|
def find_by_iso_numeric(num)
|
81
81
|
num = num.to_s
|
82
|
-
|
82
|
+
return if num.empty?
|
83
|
+
id, _ = self.table.find { |key, currency| currency[:iso_numeric] == num }
|
83
84
|
new(id)
|
84
85
|
rescue UnknownCurrency
|
85
86
|
nil
|
@@ -170,13 +171,13 @@ class Money
|
|
170
171
|
key = curr.fetch(:iso_code).downcase.to_sym
|
171
172
|
@@mutex.synchronize { _instances.delete(key.to_s) }
|
172
173
|
@table[key] = curr
|
173
|
-
@stringified_keys =
|
174
|
+
@stringified_keys = nil
|
174
175
|
end
|
175
176
|
|
176
177
|
# Inherit a new currency from existing one
|
177
178
|
#
|
178
179
|
# @param parent_iso_code [String] the international 3-letter code as defined
|
179
|
-
# @param curr [Hash] See {register} method for hash structure
|
180
|
+
# @param curr [Hash] See {register} method for hash structure
|
180
181
|
def inherit(parent_iso_code, curr)
|
181
182
|
parent_iso_code = parent_iso_code.downcase.to_sym
|
182
183
|
curr = @table.fetch(parent_iso_code, {}).merge(curr)
|
@@ -197,11 +198,10 @@ class Money
|
|
197
198
|
key = curr.downcase.to_sym
|
198
199
|
end
|
199
200
|
existed = @table.delete(key)
|
200
|
-
@stringified_keys =
|
201
|
+
@stringified_keys = nil if existed
|
201
202
|
existed ? true : false
|
202
203
|
end
|
203
204
|
|
204
|
-
|
205
205
|
def each
|
206
206
|
all.each { |c| yield(c) }
|
207
207
|
end
|
@@ -401,6 +401,17 @@ class Money
|
|
401
401
|
!!@symbol_first
|
402
402
|
end
|
403
403
|
|
404
|
+
# Returns if a code currency is ISO.
|
405
|
+
#
|
406
|
+
# @return [Boolean]
|
407
|
+
#
|
408
|
+
# @example
|
409
|
+
# Money::Currency.new(:usd).iso?
|
410
|
+
#
|
411
|
+
def iso?
|
412
|
+
iso_numeric && iso_numeric != ''
|
413
|
+
end
|
414
|
+
|
404
415
|
# Returns the relation between subunit and unit as a base 10 exponent.
|
405
416
|
#
|
406
417
|
# Note that MGA and MRO are exceptions and are rounded to 1
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'money/locale_backend/base'
|
2
|
+
|
3
|
+
class Money
|
4
|
+
module LocaleBackend
|
5
|
+
class I18n < Base
|
6
|
+
KEY_MAP = {
|
7
|
+
thousands_separator: :delimiter,
|
8
|
+
decimal_mark: :separator
|
9
|
+
}.freeze
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
raise NotSupported, 'I18n not found' unless defined?(::I18n)
|
13
|
+
end
|
14
|
+
|
15
|
+
def lookup(key, _)
|
16
|
+
i18n_key = KEY_MAP[key]
|
17
|
+
|
18
|
+
::I18n.t i18n_key, scope: 'number.currency.format', raise: true
|
19
|
+
rescue ::I18n::MissingTranslationData
|
20
|
+
::I18n.t i18n_key, scope: 'number.format', default: nil
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'money/locale_backend/base'
|
2
|
+
require 'money/locale_backend/i18n'
|
3
|
+
|
4
|
+
class Money
|
5
|
+
module LocaleBackend
|
6
|
+
class Legacy < Base
|
7
|
+
def initialize
|
8
|
+
raise NotSupported, 'I18n not found' if Money.use_i18n && !defined?(::I18n)
|
9
|
+
end
|
10
|
+
|
11
|
+
def lookup(key, currency)
|
12
|
+
if Money.use_i18n
|
13
|
+
warn '[DEPRECATION] `use_i18n` is deprecated - use `Money.locale_backend = :i18n` instead'
|
14
|
+
|
15
|
+
i18n_backend.lookup(key, nil) || currency.public_send(key)
|
16
|
+
else
|
17
|
+
currency.public_send(key)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def i18n_backend
|
24
|
+
@i18n_backend ||= Money::LocaleBackend::I18n.new
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/money/money.rb
CHANGED
@@ -5,6 +5,7 @@ require "money/money/arithmetic"
|
|
5
5
|
require "money/money/constructors"
|
6
6
|
require "money/money/formatter"
|
7
7
|
require "money/money/allocation"
|
8
|
+
require "money/money/locale_backend"
|
8
9
|
|
9
10
|
# "Money is any object or record that is generally accepted as payment for
|
10
11
|
# goods and services and repayment of debts in a given socio-economic context
|
@@ -120,7 +121,8 @@ class Money
|
|
120
121
|
# @return [Integer] Use this to specify precision for converting Rational
|
121
122
|
# to BigDecimal
|
122
123
|
attr_accessor :default_bank, :default_formatting_rules,
|
123
|
-
:use_i18n, :infinite_precision, :conversion_precision
|
124
|
+
:use_i18n, :infinite_precision, :conversion_precision,
|
125
|
+
:locale_backend
|
124
126
|
|
125
127
|
# @attr_writer rounding_mode Use this to specify the rounding mode
|
126
128
|
#
|
@@ -141,6 +143,18 @@ class Money
|
|
141
143
|
end
|
142
144
|
end
|
143
145
|
|
146
|
+
def self.locale_backend=(value)
|
147
|
+
@locale_backend = value ? LocaleBackend.find(value) : nil
|
148
|
+
end
|
149
|
+
|
150
|
+
def self.use_i18n=(value)
|
151
|
+
if value
|
152
|
+
warn '[DEPRECATION] `use_i18n` is deprecated - use `Money.locale_backend = :i18n` instead'
|
153
|
+
end
|
154
|
+
|
155
|
+
@use_i18n = value
|
156
|
+
end
|
157
|
+
|
144
158
|
def self.setup_defaults
|
145
159
|
# Set the default bank for creating new +Money+ objects.
|
146
160
|
self.default_bank = Bank::VariableExchange.instance
|
@@ -149,7 +163,10 @@ class Money
|
|
149
163
|
self.default_currency = Currency.new("USD")
|
150
164
|
|
151
165
|
# Default to using i18n
|
152
|
-
|
166
|
+
@use_i18n = true
|
167
|
+
|
168
|
+
# Default to using legacy locale backend
|
169
|
+
self.locale_backend = :legacy
|
153
170
|
|
154
171
|
# Default to not using infinite precision cents
|
155
172
|
self.infinite_precision = false
|
@@ -179,7 +196,7 @@ class Money
|
|
179
196
|
# fee = Money.rounding_mode(BigDecimal::ROUND_HALF_UP) do
|
180
197
|
# Money.new(1200) * BigDecimal('0.029')
|
181
198
|
# end
|
182
|
-
def self.rounding_mode(mode=nil)
|
199
|
+
def self.rounding_mode(mode = nil)
|
183
200
|
if mode.nil?
|
184
201
|
Thread.current[:money_rounding_mode] || @rounding_mode
|
185
202
|
else
|
@@ -540,7 +557,8 @@ class Money
|
|
540
557
|
# @return [String]
|
541
558
|
#
|
542
559
|
def thousands_separator
|
543
|
-
|
560
|
+
(locale_backend && locale_backend.lookup(:thousands_separator, currency)) ||
|
561
|
+
Money::Formatter::DEFAULTS[:thousands_separator]
|
544
562
|
end
|
545
563
|
|
546
564
|
# Returns a decimal mark according to the locale
|
@@ -548,7 +566,8 @@ class Money
|
|
548
566
|
# @return [String]
|
549
567
|
#
|
550
568
|
def decimal_mark
|
551
|
-
|
569
|
+
(locale_backend && locale_backend.lookup(:decimal_mark, currency)) ||
|
570
|
+
Money::Formatter::DEFAULTS[:decimal_mark]
|
552
571
|
end
|
553
572
|
|
554
573
|
private
|
@@ -568,4 +587,8 @@ class Money
|
|
568
587
|
value.round(0, self.class.rounding_mode).to_i
|
569
588
|
end
|
570
589
|
end
|
590
|
+
|
591
|
+
def locale_backend
|
592
|
+
self.class.locale_backend
|
593
|
+
end
|
571
594
|
end
|
@@ -3,6 +3,11 @@ require 'money/money/formatting_rules'
|
|
3
3
|
|
4
4
|
class Money
|
5
5
|
class Formatter
|
6
|
+
DEFAULTS = {
|
7
|
+
thousands_separator: '',
|
8
|
+
decimal_mark: '.'
|
9
|
+
}.freeze
|
10
|
+
|
6
11
|
# Creates a formatted price string according to several rules.
|
7
12
|
#
|
8
13
|
# @param [Hash] rules The options used to format the string.
|
@@ -203,6 +208,13 @@ class Money
|
|
203
208
|
# Money.new(89000, :btc).format(drop_trailing_zeros: true) #=> B⃦0.00089
|
204
209
|
# Money.new(110, :usd).format(drop_trailing_zeros: true) #=> $1.1
|
205
210
|
#
|
211
|
+
# @option rules [String] :format (nil) Provide a template for formatting. `%u` will be replaced
|
212
|
+
# with the symbol (if present) and `%n` will be replaced with the number.
|
213
|
+
#
|
214
|
+
# @example
|
215
|
+
# Money.new(10000, "USD").format(format: '%u %n') #=> "$ 100.00"
|
216
|
+
# Money.new(10000, "USD").format(format: '<span>%u%n</span>') #=> "<span>$100.00</span>"
|
217
|
+
#
|
206
218
|
# Note that the default rules can be defined through {Money.default_formatting_rules} hash.
|
207
219
|
#
|
208
220
|
# @see Money.default_formatting_rules Money.default_formatting_rules for more information.
|
@@ -214,15 +226,27 @@ class Money
|
|
214
226
|
|
215
227
|
def to_s
|
216
228
|
return free_text if show_free_text?
|
229
|
+
result = format_number
|
230
|
+
formatted = append_sign(result)
|
231
|
+
append_currency_symbol(formatted)
|
232
|
+
end
|
217
233
|
|
218
|
-
|
219
|
-
|
220
|
-
|
234
|
+
def thousands_separator
|
235
|
+
lookup :thousands_separator
|
236
|
+
end
|
221
237
|
|
222
|
-
|
223
|
-
|
224
|
-
|
238
|
+
def decimal_mark
|
239
|
+
lookup :decimal_mark
|
240
|
+
end
|
225
241
|
|
242
|
+
alias_method :delimiter, :thousands_separator
|
243
|
+
alias_method :separator, :decimal_mark
|
244
|
+
|
245
|
+
private
|
246
|
+
|
247
|
+
attr_reader :money, :currency, :rules
|
248
|
+
|
249
|
+
def format_number
|
226
250
|
whole_part, decimal_part = extract_whole_and_decimal_parts
|
227
251
|
|
228
252
|
# Format whole and decimal parts separately
|
@@ -230,16 +254,22 @@ class Money
|
|
230
254
|
whole_part = format_whole_part(whole_part)
|
231
255
|
|
232
256
|
# Assemble the final formatted amount
|
233
|
-
|
257
|
+
if rules[:html_wrap]
|
234
258
|
if decimal_part.nil?
|
235
259
|
html_wrap(whole_part, "whole")
|
236
260
|
else
|
237
|
-
[
|
261
|
+
[
|
262
|
+
html_wrap(whole_part, "whole"),
|
263
|
+
html_wrap(decimal_mark, "decimal-mark"),
|
264
|
+
html_wrap(decimal_part, "decimal")
|
265
|
+
].join
|
238
266
|
end
|
239
267
|
else
|
240
268
|
[whole_part, decimal_part].compact.join(decimal_mark)
|
241
269
|
end
|
270
|
+
end
|
242
271
|
|
272
|
+
def append_sign(formatted_number)
|
243
273
|
sign = money.negative? ? '-' : ''
|
244
274
|
|
245
275
|
if rules[:sign_positive] == true && money.positive?
|
@@ -259,56 +289,30 @@ class Money
|
|
259
289
|
elsif rules[:html_wrap]
|
260
290
|
symbol_value = html_wrap(symbol_value, "currency-symbol")
|
261
291
|
end
|
262
|
-
symbol_position = symbol_position_from(rules)
|
263
292
|
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
else
|
268
|
-
symbol_space = rules[:symbol_after_without_space] ? "" : " "
|
269
|
-
"#{sign_before}#{sign}#{formatted}#{symbol_space}#{symbol_value}"
|
270
|
-
end
|
293
|
+
rules[:format]
|
294
|
+
.gsub('%u', [sign_before, symbol_value].join)
|
295
|
+
.gsub('%n', [sign, formatted_number].join)
|
271
296
|
else
|
272
|
-
|
297
|
+
formatted_number = "#{sign_before}#{sign}#{formatted_number}"
|
273
298
|
end
|
299
|
+
end
|
274
300
|
|
301
|
+
def append_currency_symbol(formatted_number)
|
275
302
|
if rules[:with_currency]
|
276
|
-
|
303
|
+
formatted_number << " "
|
277
304
|
|
278
305
|
if rules[:html]
|
279
|
-
|
306
|
+
formatted_number << "<span class=\"currency\">#{currency.to_s}</span>"
|
280
307
|
elsif rules[:html_wrap]
|
281
|
-
|
308
|
+
formatted_number << html_wrap(currency.to_s, "currency")
|
282
309
|
else
|
283
|
-
|
310
|
+
formatted_number << currency.to_s
|
284
311
|
end
|
285
312
|
end
|
286
|
-
|
287
|
-
end
|
288
|
-
|
289
|
-
def thousands_separator
|
290
|
-
if rules.has_key?(:thousands_separator)
|
291
|
-
rules[:thousands_separator] || ''
|
292
|
-
else
|
293
|
-
i18n_format_for(:thousands_separator, :delimiter, ',')
|
294
|
-
end
|
295
|
-
end
|
296
|
-
|
297
|
-
def decimal_mark
|
298
|
-
if rules.has_key?(:decimal_mark)
|
299
|
-
rules[:decimal_mark] || '.'
|
300
|
-
else
|
301
|
-
i18n_format_for(:decimal_mark, :separator, '.')
|
302
|
-
end
|
313
|
+
formatted_number
|
303
314
|
end
|
304
315
|
|
305
|
-
alias_method :delimiter, :thousands_separator
|
306
|
-
alias_method :separator, :decimal_mark
|
307
|
-
|
308
|
-
private
|
309
|
-
|
310
|
-
attr_reader :money, :currency, :rules
|
311
|
-
|
312
316
|
def show_free_text?
|
313
317
|
money.zero? && rules[:display_free]
|
314
318
|
end
|
@@ -322,15 +326,8 @@ class Money
|
|
322
326
|
end
|
323
327
|
|
324
328
|
def format_whole_part(value)
|
325
|
-
# Determine thousands_separator
|
326
|
-
thousands_separator_value = if rules.has_key?(:thousands_separator)
|
327
|
-
rules[:thousands_separator] || ''
|
328
|
-
else
|
329
|
-
thousands_separator
|
330
|
-
end
|
331
|
-
|
332
329
|
# Apply thousands_separator
|
333
|
-
value.gsub regexp_format, "\\1#{
|
330
|
+
value.gsub regexp_format, "\\1#{thousands_separator}"
|
334
331
|
end
|
335
332
|
|
336
333
|
def extract_whole_and_decimal_parts
|
@@ -360,16 +357,10 @@ class Money
|
|
360
357
|
value.empty? ? nil : value
|
361
358
|
end
|
362
359
|
|
363
|
-
def
|
364
|
-
if
|
365
|
-
|
366
|
-
|
367
|
-
rescue I18n::MissingTranslationData
|
368
|
-
I18n.t name, scope: "number.format", default: (currency.send(method) || character)
|
369
|
-
end
|
370
|
-
else
|
371
|
-
currency.send(method) || character
|
372
|
-
end
|
360
|
+
def lookup(key)
|
361
|
+
return rules[key] || DEFAULTS[key] if rules.has_key?(key)
|
362
|
+
|
363
|
+
(Money.locale_backend && Money.locale_backend.lookup(key, currency)) || DEFAULTS[key]
|
373
364
|
end
|
374
365
|
|
375
366
|
def regexp_format
|
@@ -402,19 +393,5 @@ class Money
|
|
402
393
|
money.symbol
|
403
394
|
end
|
404
395
|
end
|
405
|
-
|
406
|
-
def symbol_position_from(rules)
|
407
|
-
if rules.has_key?(:symbol_position)
|
408
|
-
if [:before, :after].include?(rules[:symbol_position])
|
409
|
-
return rules[:symbol_position]
|
410
|
-
else
|
411
|
-
raise ArgumentError, ":symbol_position must be ':before' or ':after'"
|
412
|
-
end
|
413
|
-
elsif currency.symbol_first?
|
414
|
-
:before
|
415
|
-
else
|
416
|
-
:after
|
417
|
-
end
|
418
|
-
end
|
419
396
|
end
|
420
397
|
end
|
@@ -11,6 +11,9 @@ class Money
|
|
11
11
|
@rules = default_formatting_rules.merge(@rules) unless @rules[:ignore_defaults]
|
12
12
|
@rules = localize_formatting_rules(@rules)
|
13
13
|
@rules = translate_formatting_rules(@rules) if @rules[:translate]
|
14
|
+
@rules[:format] ||= determine_format_from_formatting_rules(@rules)
|
15
|
+
|
16
|
+
warn_about_deprecated_rules(@rules)
|
14
17
|
end
|
15
18
|
|
16
19
|
def [](key)
|
@@ -62,10 +65,56 @@ class Money
|
|
62
65
|
def localize_formatting_rules(rules)
|
63
66
|
if currency.iso_code == "JPY" && I18n.locale == :ja
|
64
67
|
rules[:symbol] = "円" unless rules[:symbol] == false
|
65
|
-
rules[:
|
66
|
-
rules[:symbol_after_without_space] = true
|
68
|
+
rules[:format] = '%n%u'
|
67
69
|
end
|
68
70
|
rules
|
69
71
|
end
|
72
|
+
|
73
|
+
def determine_format_from_formatting_rules(rules)
|
74
|
+
symbol_position = symbol_position_from(rules)
|
75
|
+
|
76
|
+
if symbol_position == :before
|
77
|
+
rules.fetch(:symbol_before_without_space, true) ? '%u%n' : '%u %n'
|
78
|
+
else
|
79
|
+
rules[:symbol_after_without_space] ? '%n%u' : '%n %u'
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def symbol_position_from(rules)
|
84
|
+
if rules.has_key?(:symbol_position)
|
85
|
+
if [:before, :after].include?(rules[:symbol_position])
|
86
|
+
return rules[:symbol_position]
|
87
|
+
else
|
88
|
+
raise ArgumentError, ":symbol_position must be ':before' or ':after'"
|
89
|
+
end
|
90
|
+
elsif currency.symbol_first?
|
91
|
+
:before
|
92
|
+
else
|
93
|
+
:after
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def warn_about_deprecated_rules(rules)
|
98
|
+
if rules.has_key?(:symbol_position)
|
99
|
+
warn '[DEPRECATION] `symbol_position:` option is deprecated - use `format` to specify the formatting template.'
|
100
|
+
end
|
101
|
+
|
102
|
+
if rules.has_key?(:symbol_before_without_space)
|
103
|
+
warn '[DEPRECATION] `symbol_before_without_space:` option is deprecated - use `format` to specify the formatting template.'
|
104
|
+
end
|
105
|
+
|
106
|
+
if rules.has_key?(:symbol_after_without_space)
|
107
|
+
warn '[DEPRECATION] `symbol_after_without_space:` option is deprecated - use `format` to specify the formatting template.'
|
108
|
+
end
|
109
|
+
|
110
|
+
if rules.has_key?(:html)
|
111
|
+
warn "[DEPRECATION] `html` is deprecated - use `html_wrap` instead. Please note that `html_wrap` will wrap all parts of currency and if you use `with_currency` option, currency element class changes from `currency` to `money-currency`."
|
112
|
+
end
|
113
|
+
|
114
|
+
if rules.has_key?(:html_wrap_symbol)
|
115
|
+
warn "[DEPRECATION] `html_wrap_symbol` is deprecated - use `html_wrap` instead. Please note that `html_wrap` will wrap all parts of currency."
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
70
119
|
end
|
71
120
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'money/locale_backend/errors'
|
4
|
+
require 'money/locale_backend/legacy'
|
5
|
+
require 'money/locale_backend/i18n'
|
6
|
+
|
7
|
+
class Money
|
8
|
+
module LocaleBackend
|
9
|
+
BACKENDS = {
|
10
|
+
legacy: Money::LocaleBackend::Legacy,
|
11
|
+
i18n: Money::LocaleBackend::I18n
|
12
|
+
}.freeze
|
13
|
+
|
14
|
+
def self.find(name)
|
15
|
+
raise Unknown, "Unknown locale backend: #{name}" unless BACKENDS.key?(name)
|
16
|
+
|
17
|
+
BACKENDS[name].new
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/money/version.rb
CHANGED
data/money.gemspec
CHANGED
@@ -14,11 +14,11 @@ Gem::Specification.new do |s|
|
|
14
14
|
s.description = "A Ruby Library for dealing with money and currency conversion."
|
15
15
|
s.license = "MIT"
|
16
16
|
|
17
|
-
s.add_dependency 'i18n', [">= 0.6.4", '
|
17
|
+
s.add_dependency 'i18n', [">= 0.6.4", '<= 2']
|
18
18
|
|
19
19
|
s.add_development_dependency "bundler", "~> 1.3"
|
20
20
|
s.add_development_dependency "rake"
|
21
|
-
s.add_development_dependency "rspec", "~> 3.4
|
21
|
+
s.add_development_dependency "rspec", "~> 3.4"
|
22
22
|
s.add_development_dependency "yard", "~> 0.9.11"
|
23
23
|
s.add_development_dependency "kramdown", "~> 1.1"
|
24
24
|
|
@@ -26,4 +26,10 @@ Gem::Specification.new do |s|
|
|
26
26
|
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
27
27
|
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
28
28
|
s.require_paths = ["lib"]
|
29
|
+
|
30
|
+
if s.respond_to?(:metadata)
|
31
|
+
s.metadata['changelog_uri'] = 'https://github.com/RubyMoney/money/blob/master/CHANGELOG.md'
|
32
|
+
s.metadata['source_code_uri'] = 'https://github.com/RubyMoney/money/'
|
33
|
+
s.metadata['bug_tracker_uri'] = 'https://github.com/RubyMoney/money/issues'
|
34
|
+
end
|
29
35
|
end
|
data/spec/currency_spec.rb
CHANGED
@@ -59,6 +59,11 @@ class Money
|
|
59
59
|
expect(Currency.find_by_iso_numeric('non iso 4217 numeric code')).to be_nil
|
60
60
|
expect(Currency.find_by_iso_numeric(0)).to be_nil
|
61
61
|
end
|
62
|
+
|
63
|
+
it "returns nil when given empty input" do
|
64
|
+
expect(Currency.find_by_iso_numeric('')).to be_nil
|
65
|
+
expect(Currency.find_by_iso_numeric(nil)).to be_nil
|
66
|
+
end
|
62
67
|
end
|
63
68
|
|
64
69
|
describe ".wrap" do
|
@@ -321,6 +326,16 @@ class Money
|
|
321
326
|
end
|
322
327
|
end
|
323
328
|
|
329
|
+
describe "#iso?" do
|
330
|
+
it "returns true for iso currency" do
|
331
|
+
expect(Money::Currency.new(:eur).iso?).to be true
|
332
|
+
end
|
333
|
+
|
334
|
+
it "returns false if the currency is not iso" do
|
335
|
+
expect(Money::Currency.new(:btc).iso?).to be false
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
324
339
|
describe "#to_s" do
|
325
340
|
it "works as documented" do
|
326
341
|
expect(Currency.new(:usd).to_s).to eq("USD")
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
describe Money::LocaleBackend::I18n do
|
4
|
+
describe '#initialize' do
|
5
|
+
it 'raises an error when I18n is not defined' do
|
6
|
+
hide_const('I18n')
|
7
|
+
|
8
|
+
expect { described_class.new }.to raise_error(Money::LocaleBackend::NotSupported)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '#lookup' do
|
13
|
+
after do
|
14
|
+
reset_i18n
|
15
|
+
I18n.locale = :en
|
16
|
+
end
|
17
|
+
|
18
|
+
subject { described_class.new }
|
19
|
+
|
20
|
+
context 'with number.currency.format defined' do
|
21
|
+
before do
|
22
|
+
I18n.locale = :de
|
23
|
+
I18n.backend.store_translations(:de, number: {
|
24
|
+
currency: { format: { delimiter: '.', separator: ',' } }
|
25
|
+
})
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'returns thousands_separator based on the current locale' do
|
29
|
+
expect(subject.lookup(:thousands_separator, nil)).to eq('.')
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'returns decimal_mark based on the current locale' do
|
33
|
+
expect(subject.lookup(:decimal_mark, nil)).to eq(',')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'with number.format defined' do
|
38
|
+
before do
|
39
|
+
I18n.locale = :de
|
40
|
+
I18n.backend.store_translations(:de, number: { format: { delimiter: '.', separator: ',' } })
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'returns thousands_separator based on the current locale' do
|
44
|
+
expect(subject.lookup(:thousands_separator, nil)).to eq('.')
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'returns decimal_mark based on the current locale' do
|
48
|
+
expect(subject.lookup(:decimal_mark, nil)).to eq(',')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'with no translation defined' do
|
53
|
+
it 'returns thousands_separator based on the current locale' do
|
54
|
+
expect(subject.lookup(:thousands_separator, nil)).to eq(nil)
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'returns decimal_mark based on the current locale' do
|
58
|
+
expect(subject.lookup(:decimal_mark, nil)).to eq(nil)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
describe Money::LocaleBackend::Legacy do
|
4
|
+
after { Money.use_i18n = true }
|
5
|
+
|
6
|
+
describe '#initialize' do
|
7
|
+
it 'raises an error when use_i18n is true and I18n is not defined' do
|
8
|
+
Money.use_i18n = true
|
9
|
+
hide_const('I18n')
|
10
|
+
|
11
|
+
expect { described_class.new }.to raise_error(Money::LocaleBackend::NotSupported)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'does not raise error when use_i18n is false and I18n is not defined' do
|
15
|
+
Money.use_i18n = false
|
16
|
+
hide_const('I18n')
|
17
|
+
|
18
|
+
expect { described_class.new }.not_to raise_error
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#lookup' do
|
23
|
+
subject { described_class.new }
|
24
|
+
let(:currency) { Money::Currency.new('USD') }
|
25
|
+
|
26
|
+
context 'use_i18n is true and i18n lookup is successful' do
|
27
|
+
before do
|
28
|
+
allow(subject.send(:i18n_backend))
|
29
|
+
.to receive(:lookup)
|
30
|
+
.with(:thousands_separator, nil)
|
31
|
+
.and_return('.')
|
32
|
+
|
33
|
+
allow(subject.send(:i18n_backend))
|
34
|
+
.to receive(:lookup)
|
35
|
+
.with(:decimal_mark, nil)
|
36
|
+
.and_return(',')
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'returns thousands_separator from I18n' do
|
40
|
+
expect(subject.lookup(:thousands_separator, currency)).to eq('.')
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'returns decimal_mark based from I18n' do
|
44
|
+
expect(subject.lookup(:decimal_mark, currency)).to eq(',')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'use_i18n is true but i18n lookup is unsuccessful' do
|
49
|
+
before do
|
50
|
+
allow(subject.send(:i18n_backend)).to receive(:lookup).and_return(nil)
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'returns thousands_separator as defined in currency' do
|
54
|
+
expect(subject.lookup(:thousands_separator, currency)).to eq(',')
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'returns decimal_mark based as defined in currency' do
|
58
|
+
expect(subject.lookup(:decimal_mark, currency)).to eq('.')
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context 'use_i18n is false' do
|
63
|
+
before { Money.use_i18n = false }
|
64
|
+
|
65
|
+
it 'returns thousands_separator as defined in currency' do
|
66
|
+
expect(subject.lookup(:thousands_separator, currency)).to eq(',')
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'returns decimal_mark based as defined in currency' do
|
70
|
+
expect(subject.lookup(:decimal_mark, currency)).to eq('.')
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -18,6 +18,19 @@ describe Money, "formatting" do
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
+
context 'without locale_backend' do
|
22
|
+
before { Money.locale_backend = nil }
|
23
|
+
after { Money.locale_backend = :legacy }
|
24
|
+
|
25
|
+
subject(:money) { Money.new(1099_99, 'USD') }
|
26
|
+
|
27
|
+
it 'falls back to using defaults' do
|
28
|
+
expect(money.thousands_separator).to eq('')
|
29
|
+
expect(money.decimal_mark).to eq('.')
|
30
|
+
expect(money.format).to eq('$1099.99')
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
21
34
|
context "with i18n but use_i18n = false" do
|
22
35
|
before :each do
|
23
36
|
reset_i18n
|
@@ -661,6 +674,42 @@ describe Money, "formatting" do
|
|
661
674
|
end
|
662
675
|
end
|
663
676
|
|
677
|
+
describe ':format option' do
|
678
|
+
let(:money) { Money.new(99_99, 'USD') }
|
679
|
+
|
680
|
+
it 'uses provided format as a template' do
|
681
|
+
expect(money.format(format: '%n')).to eq('99.99')
|
682
|
+
expect(money.format(format: '%u')).to eq('$')
|
683
|
+
expect(money.format(format: '%u%n')).to eq('$99.99')
|
684
|
+
expect(money.format(format: '%n%u')).to eq('99.99$')
|
685
|
+
expect(money.format(format: '%u %n')).to eq('$ 99.99')
|
686
|
+
expect(money.format(format: 'Your balance is: %u%n')).to eq('Your balance is: $99.99')
|
687
|
+
end
|
688
|
+
|
689
|
+
it 'ignores :symbol_position in favour of format' do
|
690
|
+
expect(money.format(format: '%u%n', symbol_position: :after)).to eq('$99.99')
|
691
|
+
expect(money.format(format: '%n%u', symbol_position: :before)).to eq('99.99$')
|
692
|
+
end
|
693
|
+
|
694
|
+
it 'ignores :symbol_before_without_space in favour of format' do
|
695
|
+
expect(money.format(format: '%u %n', symbol_position: :before, symbol_before_without_space: true)).to eq('$ 99.99')
|
696
|
+
expect(money.format(format: '%u%n', symbol_position: :before, symbol_before_without_space: false)).to eq('$99.99')
|
697
|
+
end
|
698
|
+
|
699
|
+
it 'ignores :symbol_after_without_space in favour of format' do
|
700
|
+
expect(money.format(format: '%n %u', symbol_position: :after, symbol_after_without_space: true)).to eq('99.99 $')
|
701
|
+
expect(money.format(format: '%n%u', symbol_position: :after, symbol_after_without_space: false)).to eq('99.99$')
|
702
|
+
end
|
703
|
+
|
704
|
+
it 'works with sign' do
|
705
|
+
money = Money.new(-99_99, 'USD')
|
706
|
+
|
707
|
+
expect(money.format(format: '%n%u', sign_before_symbol: false)).to eq('-99.99$')
|
708
|
+
expect(money.format(format: '%u%n', sign_before_symbol: false)).to eq('$-99.99')
|
709
|
+
expect(money.format(format: '%u%n', sign_before_symbol: true)).to eq('-$99.99')
|
710
|
+
end
|
711
|
+
end
|
712
|
+
|
664
713
|
context "when the monetary value is 0" do
|
665
714
|
let(:money) { Money.us_dollar(0) }
|
666
715
|
|
@@ -730,6 +779,7 @@ describe Money, "formatting" do
|
|
730
779
|
expect(Money.new(1999_98, "DKK").format).to eq("1.999,98 kr.")
|
731
780
|
expect(Money.new(1999_98, "NOK").format).to eq("1.999,98 kr")
|
732
781
|
expect(Money.new(1999_98, "SEK").format).to eq("1 999,98 kr")
|
782
|
+
expect(Money.new(1999_98, "BCH").format).to eq("0.00199998 ₿")
|
733
783
|
end
|
734
784
|
|
735
785
|
it "returns ambiguous signs when disambiguate is false" do
|
@@ -738,6 +788,7 @@ describe Money, "formatting" do
|
|
738
788
|
expect(Money.new(1999_98, "DKK").format(disambiguate: false)).to eq("1.999,98 kr.")
|
739
789
|
expect(Money.new(1999_98, "NOK").format(disambiguate: false)).to eq("1.999,98 kr")
|
740
790
|
expect(Money.new(1999_98, "SEK").format(disambiguate: false)).to eq("1 999,98 kr")
|
791
|
+
expect(Money.new(1999_98, "BCH").format(disambiguate: false)).to eq("0.00199998 ₿")
|
741
792
|
end
|
742
793
|
|
743
794
|
it "returns disambiguate signs when disambiguate: true" do
|
@@ -746,6 +797,7 @@ describe Money, "formatting" do
|
|
746
797
|
expect(Money.new(1999_98, "DKK").format(disambiguate: true)).to eq("1.999,98 DKK")
|
747
798
|
expect(Money.new(1999_98, "NOK").format(disambiguate: true)).to eq("1.999,98 NOK")
|
748
799
|
expect(Money.new(1999_98, "SEK").format(disambiguate: true)).to eq("1 999,98 SEK")
|
800
|
+
expect(Money.new(1999_98, "BCH").format(disambiguate: true)).to eq("0.00199998 ₿CH")
|
749
801
|
end
|
750
802
|
|
751
803
|
it "returns disambiguate signs when disambiguate: true and symbol: true" do
|
@@ -754,6 +806,7 @@ describe Money, "formatting" do
|
|
754
806
|
expect(Money.new(1999_98, "DKK").format(disambiguate: true, symbol: true)).to eq("1.999,98 DKK")
|
755
807
|
expect(Money.new(1999_98, "NOK").format(disambiguate: true, symbol: true)).to eq("1.999,98 NOK")
|
756
808
|
expect(Money.new(1999_98, "SEK").format(disambiguate: true, symbol: true)).to eq("1 999,98 SEK")
|
809
|
+
expect(Money.new(1999_98, "BCH").format(disambiguate: true, symbol: true)).to eq("0.00199998 ₿CH")
|
757
810
|
end
|
758
811
|
|
759
812
|
it "returns no signs when disambiguate: true and symbol: false" do
|
@@ -762,6 +815,7 @@ describe Money, "formatting" do
|
|
762
815
|
expect(Money.new(1999_98, "DKK").format(disambiguate: true, symbol: false)).to eq("1.999,98")
|
763
816
|
expect(Money.new(1999_98, "NOK").format(disambiguate: true, symbol: false)).to eq("1.999,98")
|
764
817
|
expect(Money.new(1999_98, "SEK").format(disambiguate: true, symbol: false)).to eq("1 999,98")
|
818
|
+
expect(Money.new(1999_98, "BCH").format(disambiguate: true, symbol: false)).to eq("0.00199998")
|
765
819
|
end
|
766
820
|
|
767
821
|
it "should never return an ambiguous format with disambiguate: true" do
|
@@ -779,15 +833,21 @@ describe Money, "formatting" do
|
|
779
833
|
describe ":drop_trailing_zeros option" do
|
780
834
|
specify "(drop_trailing_zeros: true) works as documented" do
|
781
835
|
expect(Money.new(89000, "BTC").format(drop_trailing_zeros: true, symbol: false)).to eq "0.00089"
|
836
|
+
expect(Money.new(89000, "BCH").format(drop_trailing_zeros: true, symbol: false)).to eq "0.00089"
|
782
837
|
expect(Money.new(100089000, "BTC").format(drop_trailing_zeros: true, symbol: false)).to eq "1.00089"
|
838
|
+
expect(Money.new(100089000, "BCH").format(drop_trailing_zeros: true, symbol: false)).to eq "1.00089"
|
783
839
|
expect(Money.new(100000000, "BTC").format(drop_trailing_zeros: true, symbol: false)).to eq "1"
|
840
|
+
expect(Money.new(100000000, "BCH").format(drop_trailing_zeros: true, symbol: false)).to eq "1"
|
784
841
|
expect(Money.new(110, "AUD").format(drop_trailing_zeros: true, symbol: false)).to eq "1.1"
|
785
842
|
end
|
786
843
|
|
787
844
|
specify "(drop_trailing_zeros: false) works as documented" do
|
788
845
|
expect(Money.new(89000, "BTC").format(drop_trailing_zeros: false, symbol: false)).to eq "0.00089000"
|
846
|
+
expect(Money.new(89000, "BCH").format(drop_trailing_zeros: false, symbol: false)).to eq "0.00089000"
|
789
847
|
expect(Money.new(100089000, "BTC").format(drop_trailing_zeros: false, symbol: false)).to eq "1.00089000"
|
848
|
+
expect(Money.new(100089000, "BCH").format(drop_trailing_zeros: false, symbol: false)).to eq "1.00089000"
|
790
849
|
expect(Money.new(100000000, "BTC").format(drop_trailing_zeros: false, symbol: false)).to eq "1.00000000"
|
850
|
+
expect(Money.new(100000000, "BCH").format(drop_trailing_zeros: false, symbol: false)).to eq "1.00000000"
|
791
851
|
expect(Money.new(110, "AUD").format(drop_trailing_zeros: false, symbol: false)).to eq "1.10"
|
792
852
|
end
|
793
853
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
describe Money::LocaleBackend do
|
4
|
+
describe '.find' do
|
5
|
+
it 'returns an initialized backend' do
|
6
|
+
expect(described_class.find(:legacy)).to be_a(Money::LocaleBackend::Legacy)
|
7
|
+
expect(described_class.find(:i18n)).to be_a(Money::LocaleBackend::I18n)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'raises an error if a backend is unknown' do
|
11
|
+
expect { described_class.find(:foo) }.to raise_error(Money::LocaleBackend::Unknown)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/spec/money_spec.rb
CHANGED
@@ -1,6 +1,22 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
describe Money do
|
4
|
+
describe '.locale_backend' do
|
5
|
+
after { Money.locale_backend = :legacy }
|
6
|
+
|
7
|
+
it 'sets the locale_backend' do
|
8
|
+
Money.locale_backend = :i18n
|
9
|
+
|
10
|
+
expect(Money.locale_backend).to be_a(Money::LocaleBackend::I18n)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'sets the locale_backend to nil' do
|
14
|
+
Money.locale_backend = nil
|
15
|
+
|
16
|
+
expect(Money.locale_backend).to eq(nil)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
4
20
|
describe ".new" do
|
5
21
|
let(:initializing_value) { 1 }
|
6
22
|
subject(:money) { Money.new(initializing_value) }
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: money
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.
|
4
|
+
version: 6.13.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shane Emmons
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-10-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: i18n
|
@@ -17,9 +17,9 @@ dependencies:
|
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 0.6.4
|
20
|
-
- - "
|
20
|
+
- - "<="
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: '
|
22
|
+
version: '2'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -27,9 +27,9 @@ dependencies:
|
|
27
27
|
- - ">="
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: 0.6.4
|
30
|
-
- - "
|
30
|
+
- - "<="
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: '
|
32
|
+
version: '2'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: bundler
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -64,14 +64,14 @@ dependencies:
|
|
64
64
|
requirements:
|
65
65
|
- - "~>"
|
66
66
|
- !ruby/object:Gem::Version
|
67
|
-
version: 3.4
|
67
|
+
version: '3.4'
|
68
68
|
type: :development
|
69
69
|
prerelease: false
|
70
70
|
version_requirements: !ruby/object:Gem::Requirement
|
71
71
|
requirements:
|
72
72
|
- - "~>"
|
73
73
|
- !ruby/object:Gem::Version
|
74
|
-
version: 3.4
|
74
|
+
version: '3.4'
|
75
75
|
- !ruby/object:Gem::Dependency
|
76
76
|
name: yard
|
77
77
|
requirement: !ruby/object:Gem::Requirement
|
@@ -128,12 +128,17 @@ files:
|
|
128
128
|
- lib/money/currency.rb
|
129
129
|
- lib/money/currency/heuristics.rb
|
130
130
|
- lib/money/currency/loader.rb
|
131
|
+
- lib/money/locale_backend/base.rb
|
132
|
+
- lib/money/locale_backend/errors.rb
|
133
|
+
- lib/money/locale_backend/i18n.rb
|
134
|
+
- lib/money/locale_backend/legacy.rb
|
131
135
|
- lib/money/money.rb
|
132
136
|
- lib/money/money/allocation.rb
|
133
137
|
- lib/money/money/arithmetic.rb
|
134
138
|
- lib/money/money/constructors.rb
|
135
139
|
- lib/money/money/formatter.rb
|
136
140
|
- lib/money/money/formatting_rules.rb
|
141
|
+
- lib/money/money/locale_backend.rb
|
137
142
|
- lib/money/rates_store/memory.rb
|
138
143
|
- lib/money/version.rb
|
139
144
|
- money.gemspec
|
@@ -143,10 +148,13 @@ files:
|
|
143
148
|
- spec/currency/heuristics_spec.rb
|
144
149
|
- spec/currency/loader_spec.rb
|
145
150
|
- spec/currency_spec.rb
|
151
|
+
- spec/locale_backend/i18n_spec.rb
|
152
|
+
- spec/locale_backend/legacy_spec.rb
|
146
153
|
- spec/money/allocation_spec.rb
|
147
154
|
- spec/money/arithmetic_spec.rb
|
148
155
|
- spec/money/constructors_spec.rb
|
149
156
|
- spec/money/formatting_spec.rb
|
157
|
+
- spec/money/locale_backend_spec.rb
|
150
158
|
- spec/money_spec.rb
|
151
159
|
- spec/rates_store/memory_spec.rb
|
152
160
|
- spec/spec_helper.rb
|
@@ -154,7 +162,10 @@ files:
|
|
154
162
|
homepage: https://rubymoney.github.io/money
|
155
163
|
licenses:
|
156
164
|
- MIT
|
157
|
-
metadata:
|
165
|
+
metadata:
|
166
|
+
changelog_uri: https://github.com/RubyMoney/money/blob/master/CHANGELOG.md
|
167
|
+
source_code_uri: https://github.com/RubyMoney/money/
|
168
|
+
bug_tracker_uri: https://github.com/RubyMoney/money/issues
|
158
169
|
post_install_message:
|
159
170
|
rdoc_options: []
|
160
171
|
require_paths:
|
@@ -182,10 +193,13 @@ test_files:
|
|
182
193
|
- spec/currency/heuristics_spec.rb
|
183
194
|
- spec/currency/loader_spec.rb
|
184
195
|
- spec/currency_spec.rb
|
196
|
+
- spec/locale_backend/i18n_spec.rb
|
197
|
+
- spec/locale_backend/legacy_spec.rb
|
185
198
|
- spec/money/allocation_spec.rb
|
186
199
|
- spec/money/arithmetic_spec.rb
|
187
200
|
- spec/money/constructors_spec.rb
|
188
201
|
- spec/money/formatting_spec.rb
|
202
|
+
- spec/money/locale_backend_spec.rb
|
189
203
|
- spec/money_spec.rb
|
190
204
|
- spec/rates_store/memory_spec.rb
|
191
205
|
- spec/spec_helper.rb
|