money 6.12.0 → 6.13.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Code Climate](https://codeclimate.com/github/RubyMoney/money.svg)](https://codeclimate.com/github/RubyMoney/money)
|
6
6
|
[![Coverage Status](https://coveralls.io/repos/RubyMoney/money/badge.svg?branch=master)](https://coveralls.io/r/RubyMoney/money?branch=master)
|
7
7
|
[![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
8
|
[![License](https://img.shields.io/github/license/RubyMoney/money.svg)](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
|