money 6.19.0 → 7.0.1
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/CHANGELOG.md +101 -47
- data/LICENSE +1 -1
- data/README.md +57 -54
- data/config/currency_backwards_compatible.json +1 -0
- data/config/currency_iso.json +42 -12
- data/config/currency_non_iso.json +1 -1
- data/lib/money/bank/base.rb +2 -0
- data/lib/money/bank/single_currency.rb +2 -0
- data/lib/money/bank/variable_exchange.rb +2 -0
- data/lib/money/currency/heuristics.rb +1 -1
- data/lib/money/currency/loader.rb +2 -0
- data/lib/money/currency.rb +35 -9
- data/lib/money/locale_backend/base.rb +2 -0
- data/lib/money/locale_backend/currency.rb +2 -0
- data/lib/money/locale_backend/errors.rb +2 -0
- data/lib/money/locale_backend/i18n.rb +4 -1
- data/lib/money/money/allocation.rb +27 -8
- data/lib/money/money/arithmetic.rb +49 -33
- data/lib/money/money/constructors.rb +2 -0
- data/lib/money/money/formatter.rb +14 -63
- data/lib/money/money/formatting_rules.rb +9 -59
- data/lib/money/money/locale_backend.rb +1 -3
- data/lib/money/money.rb +105 -119
- data/lib/money/rates_store/memory.rb +2 -0
- data/lib/money/version.rb +3 -1
- data/lib/money.rb +3 -0
- data/money.gemspec +12 -5
- metadata +43 -24
- data/lib/money/locale_backend/legacy.rb +0 -28
data/config/currency_iso.json
CHANGED
|
@@ -52,13 +52,13 @@
|
|
|
52
52
|
"priority": 100,
|
|
53
53
|
"iso_code": "AMD",
|
|
54
54
|
"name": "Armenian Dram",
|
|
55
|
-
"symbol": "
|
|
55
|
+
"symbol": "֏",
|
|
56
56
|
"alternate_symbols": ["dram"],
|
|
57
57
|
"subunit": "Luma",
|
|
58
58
|
"subunit_to_unit": 100,
|
|
59
59
|
"symbol_first": false,
|
|
60
60
|
"format": "%n %u",
|
|
61
|
-
"html_entity": "",
|
|
61
|
+
"html_entity": "֏",
|
|
62
62
|
"decimal_mark": ".",
|
|
63
63
|
"thousands_separator": ",",
|
|
64
64
|
"iso_numeric": "051",
|
|
@@ -455,7 +455,7 @@
|
|
|
455
455
|
"format": "%u %n",
|
|
456
456
|
"html_entity": "",
|
|
457
457
|
"decimal_mark": ".",
|
|
458
|
-
"thousands_separator": "
|
|
458
|
+
"thousands_separator": "'",
|
|
459
459
|
"iso_numeric": "756",
|
|
460
460
|
"smallest_denomination": 5
|
|
461
461
|
},
|
|
@@ -972,7 +972,7 @@
|
|
|
972
972
|
"ils": {
|
|
973
973
|
"priority": 100,
|
|
974
974
|
"iso_code": "ILS",
|
|
975
|
-
"name": "Israeli New
|
|
975
|
+
"name": "Israeli New Shekel",
|
|
976
976
|
"symbol": "₪",
|
|
977
977
|
"alternate_symbols": ["ש״ח", "NIS"],
|
|
978
978
|
"subunit": "Agora",
|
|
@@ -1371,7 +1371,7 @@
|
|
|
1371
1371
|
"symbol": "Ar",
|
|
1372
1372
|
"alternate_symbols": [],
|
|
1373
1373
|
"subunit": "Iraimbilanja",
|
|
1374
|
-
"subunit_to_unit":
|
|
1374
|
+
"subunit_to_unit": 1,
|
|
1375
1375
|
"symbol_first": true,
|
|
1376
1376
|
"html_entity": "",
|
|
1377
1377
|
"decimal_mark": ".",
|
|
@@ -1810,14 +1810,14 @@
|
|
|
1810
1810
|
"priority": 100,
|
|
1811
1811
|
"iso_code": "RSD",
|
|
1812
1812
|
"name": "Serbian Dinar",
|
|
1813
|
-
"symbol": "
|
|
1814
|
-
"alternate_symbols": ["
|
|
1813
|
+
"symbol": "RSD",
|
|
1814
|
+
"alternate_symbols": ["РСД", "din", "дин", "din.", "DIN", "Din", "дин."],
|
|
1815
1815
|
"subunit": "Para",
|
|
1816
1816
|
"subunit_to_unit": 100,
|
|
1817
|
-
"symbol_first":
|
|
1817
|
+
"symbol_first": false,
|
|
1818
1818
|
"html_entity": "",
|
|
1819
|
-
"decimal_mark": "
|
|
1820
|
-
"thousands_separator": "
|
|
1819
|
+
"decimal_mark": ",",
|
|
1820
|
+
"thousands_separator": ".",
|
|
1821
1821
|
"iso_numeric": "941",
|
|
1822
1822
|
"smallest_denomination": 100
|
|
1823
1823
|
},
|
|
@@ -2180,13 +2180,13 @@
|
|
|
2180
2180
|
"priority": 100,
|
|
2181
2181
|
"iso_code": "TMT",
|
|
2182
2182
|
"name": "Turkmenistani Manat",
|
|
2183
|
-
"symbol": "
|
|
2183
|
+
"symbol": "m",
|
|
2184
2184
|
"alternate_symbols": [],
|
|
2185
2185
|
"subunit": "Tenge",
|
|
2186
2186
|
"subunit_to_unit": 100,
|
|
2187
2187
|
"symbol_first": false,
|
|
2188
2188
|
"format": "%n %u",
|
|
2189
|
-
"html_entity": "",
|
|
2189
|
+
"html_entity": "m",
|
|
2190
2190
|
"decimal_mark": ".",
|
|
2191
2191
|
"thousands_separator": ",",
|
|
2192
2192
|
"iso_numeric": "934",
|
|
@@ -2557,6 +2557,21 @@
|
|
|
2557
2557
|
"iso_numeric": "951",
|
|
2558
2558
|
"smallest_denomination": 1
|
|
2559
2559
|
},
|
|
2560
|
+
"xcg": {
|
|
2561
|
+
"priority": 100,
|
|
2562
|
+
"iso_code": "XCG",
|
|
2563
|
+
"name": "Caribbean Guilder",
|
|
2564
|
+
"symbol": "Cg",
|
|
2565
|
+
"alternate_symbols": [],
|
|
2566
|
+
"subunit": "Cent",
|
|
2567
|
+
"subunit_to_unit": 100,
|
|
2568
|
+
"symbol_first": true,
|
|
2569
|
+
"html_entity": "",
|
|
2570
|
+
"decimal_mark": ",",
|
|
2571
|
+
"thousands_separator": ".",
|
|
2572
|
+
"iso_numeric": "532",
|
|
2573
|
+
"smallest_denomination": 1
|
|
2574
|
+
},
|
|
2560
2575
|
"xdr": {
|
|
2561
2576
|
"priority": 100,
|
|
2562
2577
|
"iso_code": "XDR",
|
|
@@ -2716,5 +2731,20 @@
|
|
|
2716
2731
|
"thousands_separator": ",",
|
|
2717
2732
|
"iso_numeric": "967",
|
|
2718
2733
|
"smallest_denomination": 5
|
|
2734
|
+
},
|
|
2735
|
+
"zwg": {
|
|
2736
|
+
"priority": 100,
|
|
2737
|
+
"iso_code": "ZWG",
|
|
2738
|
+
"name": "Zimbabwe Gold",
|
|
2739
|
+
"symbol": "ZiG",
|
|
2740
|
+
"alternate_symbols": [],
|
|
2741
|
+
"subunit": "cent",
|
|
2742
|
+
"subunit_to_unit": 100,
|
|
2743
|
+
"symbol_first": false,
|
|
2744
|
+
"html_entity": "",
|
|
2745
|
+
"decimal_mark": ".",
|
|
2746
|
+
"thousands_separator": ",",
|
|
2747
|
+
"iso_numeric": "924",
|
|
2748
|
+
"smallest_denomination": 1
|
|
2719
2749
|
}
|
|
2720
2750
|
}
|
data/lib/money/bank/base.rb
CHANGED
data/lib/money/currency.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "json"
|
|
4
4
|
require "money/currency/loader"
|
|
@@ -9,7 +9,7 @@ class Money
|
|
|
9
9
|
# Represents a specific currency unit.
|
|
10
10
|
#
|
|
11
11
|
# @see https://en.wikipedia.org/wiki/Currency
|
|
12
|
-
# @see
|
|
12
|
+
# @see https://www.iso.org/iso-4217-currency-codes.html
|
|
13
13
|
class Currency
|
|
14
14
|
include Comparable
|
|
15
15
|
extend Enumerable
|
|
@@ -33,6 +33,9 @@ class Money
|
|
|
33
33
|
# Thrown when an unknown currency is requested.
|
|
34
34
|
class UnknownCurrency < ArgumentError; end
|
|
35
35
|
|
|
36
|
+
# Thrown when currency is not provided.
|
|
37
|
+
class NoCurrency < ArgumentError; end
|
|
38
|
+
|
|
36
39
|
class << self
|
|
37
40
|
def new(id)
|
|
38
41
|
id = id.to_s.downcase
|
|
@@ -80,8 +83,8 @@ class Money
|
|
|
80
83
|
def find_by_iso_numeric(num)
|
|
81
84
|
num = num.to_s.rjust(3, '0')
|
|
82
85
|
return if num.empty?
|
|
83
|
-
id
|
|
84
|
-
new(id)
|
|
86
|
+
id = iso_numeric_index[num]
|
|
87
|
+
new(id) if id
|
|
85
88
|
rescue UnknownCurrency
|
|
86
89
|
nil
|
|
87
90
|
end
|
|
@@ -113,13 +116,13 @@ class Money
|
|
|
113
116
|
#
|
|
114
117
|
# == monetary unit
|
|
115
118
|
# The standard unit of value of a currency, as the dollar in the United States or the peso in Mexico.
|
|
116
|
-
# https://www.answers.com/
|
|
119
|
+
# https://www.answers.com/redirectSearch?query=monetary-unit
|
|
117
120
|
# == fractional monetary unit, subunit
|
|
118
121
|
# A monetary unit that is valued at a fraction (usually one hundredth) of the basic monetary unit
|
|
119
|
-
# https://www.answers.com/
|
|
122
|
+
# https://www.answers.com/redirectSearch?query=fractional-monetary-unit-subunit
|
|
120
123
|
#
|
|
121
124
|
# See https://en.wikipedia.org/wiki/List_of_circulating_currencies and
|
|
122
|
-
#
|
|
125
|
+
# https://metacpan.org/release/TNGUYEN/Locale-Currency-Format-1.28/view/Format.pm
|
|
123
126
|
def table
|
|
124
127
|
@table ||= Loader.load_currencies
|
|
125
128
|
end
|
|
@@ -142,7 +145,7 @@ class Money
|
|
|
142
145
|
|
|
143
146
|
# We need a string-based validator before creating an unbounded number of
|
|
144
147
|
# symbols.
|
|
145
|
-
# http://www.randomhacks.net/
|
|
148
|
+
# http://www.randomhacks.net.s3-website-us-east-1.amazonaws.com/2007/01/20/13-ways-of-looking-at-a-ruby-symbol/#11
|
|
146
149
|
# https://github.com/RubyMoney/money/issues/132
|
|
147
150
|
#
|
|
148
151
|
# @return [Set]
|
|
@@ -172,6 +175,7 @@ class Money
|
|
|
172
175
|
@@mutex.synchronize { _instances.delete(key.to_s) }
|
|
173
176
|
@table[key] = curr
|
|
174
177
|
@stringified_keys = nil
|
|
178
|
+
clear_iso_numeric_cache
|
|
175
179
|
end
|
|
176
180
|
|
|
177
181
|
# Inherit a new currency from existing one
|
|
@@ -209,10 +213,21 @@ class Money
|
|
|
209
213
|
def reset!
|
|
210
214
|
@@instances = {}
|
|
211
215
|
@table = Loader.load_currencies
|
|
216
|
+
clear_iso_numeric_cache
|
|
212
217
|
end
|
|
213
218
|
|
|
214
219
|
private
|
|
215
220
|
|
|
221
|
+
def iso_numeric_index
|
|
222
|
+
@iso_numeric_index ||= table.each_with_object({}) do |(id, attrs), index|
|
|
223
|
+
index[attrs[:iso_numeric]] = id
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def clear_iso_numeric_cache
|
|
228
|
+
@iso_numeric_index = nil
|
|
229
|
+
end
|
|
230
|
+
|
|
216
231
|
def stringify_keys
|
|
217
232
|
table.keys.each_with_object(Set.new) { |k, set| set.add(k.to_s.downcase) }
|
|
218
233
|
end
|
|
@@ -405,7 +420,7 @@ class Money
|
|
|
405
420
|
!!@symbol_first
|
|
406
421
|
end
|
|
407
422
|
|
|
408
|
-
# Returns if a code currency is ISO.
|
|
423
|
+
# Returns true if a code currency is ISO.
|
|
409
424
|
#
|
|
410
425
|
# @return [Boolean]
|
|
411
426
|
#
|
|
@@ -416,6 +431,17 @@ class Money
|
|
|
416
431
|
iso_numeric && iso_numeric != ''
|
|
417
432
|
end
|
|
418
433
|
|
|
434
|
+
# Returns true if a subunit is cents-based.
|
|
435
|
+
#
|
|
436
|
+
# @return [Boolean]
|
|
437
|
+
#
|
|
438
|
+
# @example
|
|
439
|
+
# Money::Currency.new(:usd).cents_based?
|
|
440
|
+
#
|
|
441
|
+
def cents_based?
|
|
442
|
+
subunit_to_unit == 100
|
|
443
|
+
end
|
|
444
|
+
|
|
419
445
|
# Returns the relation between subunit and unit as a base 10 exponent.
|
|
420
446
|
#
|
|
421
447
|
# Note that MGA and MRU are exceptions and are rounded to 1
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'money/locale_backend/base'
|
|
2
4
|
|
|
3
5
|
class Money
|
|
@@ -6,7 +8,8 @@ class Money
|
|
|
6
8
|
KEY_MAP = {
|
|
7
9
|
thousands_separator: :delimiter,
|
|
8
10
|
decimal_mark: :separator,
|
|
9
|
-
symbol: :unit
|
|
11
|
+
symbol: :unit,
|
|
12
|
+
format: :format,
|
|
10
13
|
}.freeze
|
|
11
14
|
|
|
12
15
|
def initialize
|
|
@@ -1,19 +1,27 @@
|
|
|
1
|
-
#
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
class Money
|
|
4
4
|
class Allocation
|
|
5
|
-
#
|
|
6
|
-
#
|
|
5
|
+
# Allocates a specified amount into parts based on their proportions or distributes
|
|
6
|
+
# it evenly when the number of parts is specified numerically.
|
|
7
7
|
#
|
|
8
|
-
# The
|
|
8
|
+
# The total of the allocated amounts will always equal the original amount.
|
|
9
|
+
#
|
|
10
|
+
# The parts can be specified as:
|
|
11
|
+
# Numeric — performs the split between a given number of parties evenly
|
|
12
|
+
# Array<Numeric> — allocates the amounts proportionally to the given array
|
|
9
13
|
#
|
|
10
14
|
# @param amount [Numeric] The total amount to be allocated.
|
|
11
15
|
# @param parts [Numeric, Array<Numeric>] Number of parts to split into or an array (proportions for allocation)
|
|
12
|
-
# @param
|
|
16
|
+
# @param decimal_cutoff [Boolean, Integer] Controls per-split precision:
|
|
17
|
+
# - When true, splits are truncated to whole amounts.
|
|
18
|
+
# - When an Integer N, splits are rounded to N decimal places.
|
|
19
|
+
# - When false or nil, no rounding/truncation is applied.
|
|
20
|
+
# Defaults to true (whole amounts).
|
|
13
21
|
#
|
|
14
22
|
# @return [Array<Numeric>] An array containing the allocated amounts.
|
|
15
23
|
# @raise [ArgumentError] If parts is empty or not provided.
|
|
16
|
-
def self.generate(amount, parts,
|
|
24
|
+
def self.generate(amount, parts, decimal_cutoff = true)
|
|
17
25
|
parts = if parts.is_a?(Numeric)
|
|
18
26
|
Array.new(parts, 1)
|
|
19
27
|
elsif parts.all?(&:zero?)
|
|
@@ -31,19 +39,30 @@ class Money
|
|
|
31
39
|
|
|
32
40
|
result = []
|
|
33
41
|
remaining_amount = amount
|
|
42
|
+
round_to_whole = decimal_cutoff.is_a?(TrueClass)
|
|
43
|
+
round_to_precision = decimal_cutoff.is_a?(Integer)
|
|
44
|
+
|
|
45
|
+
parts_sum = parts.sum
|
|
34
46
|
|
|
35
47
|
until parts.empty? do
|
|
36
|
-
parts_sum = parts.inject(0, :+)
|
|
37
48
|
part = parts.pop
|
|
38
49
|
|
|
39
50
|
current_split = 0
|
|
40
51
|
if parts_sum > 0
|
|
41
52
|
current_split = remaining_amount * part / parts_sum
|
|
42
|
-
current_split =
|
|
53
|
+
current_split =
|
|
54
|
+
if round_to_whole
|
|
55
|
+
current_split.truncate
|
|
56
|
+
elsif round_to_precision
|
|
57
|
+
current_split.round(decimal_cutoff)
|
|
58
|
+
else
|
|
59
|
+
current_split
|
|
60
|
+
end
|
|
43
61
|
end
|
|
44
62
|
|
|
45
63
|
result.unshift current_split
|
|
46
64
|
remaining_amount -= current_split
|
|
65
|
+
parts_sum -= part
|
|
47
66
|
end
|
|
48
67
|
|
|
49
68
|
result
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
class Money
|
|
2
4
|
module Arithmetic
|
|
3
5
|
# Wrapper for coerced numeric values to distinguish
|
|
@@ -20,24 +22,32 @@ class Money
|
|
|
20
22
|
end
|
|
21
23
|
|
|
22
24
|
# Checks whether two Money objects have the same currency and the same
|
|
23
|
-
# amount.
|
|
24
|
-
#
|
|
25
|
-
# a subclass will always return false.
|
|
25
|
+
# amount. Checks against objects that are not Money or a subclass will
|
|
26
|
+
# always return false.
|
|
26
27
|
#
|
|
27
28
|
# @param [Money] other_money Value to compare with.
|
|
28
29
|
#
|
|
29
30
|
# @return [Boolean]
|
|
30
31
|
#
|
|
31
32
|
# @example
|
|
32
|
-
# Money.new(
|
|
33
|
-
# Money.new(
|
|
34
|
-
# Money.new(
|
|
35
|
-
# Money.new(0, "USD").eql?(Money.new(0, "EUR"))
|
|
36
|
-
# Money.new(
|
|
33
|
+
# Money.new(1_00).eql?(Money.new(1_00)) #=> true
|
|
34
|
+
# Money.new(1_00).eql?(Money.new(1_01)) #=> false
|
|
35
|
+
# Money.new(1_00, "USD").eql?(Money.new(1_00, "GBP")) #=> false
|
|
36
|
+
# Money.new(0, "USD").eql?(Money.new(0, "EUR")) #=> false
|
|
37
|
+
# Money.new(1_00).eql?("1.00") #=> false
|
|
38
|
+
#
|
|
39
|
+
# @see Money.strict_eql_compare
|
|
37
40
|
def eql?(other_money)
|
|
38
41
|
if other_money.is_a?(Money)
|
|
39
|
-
|
|
40
|
-
|
|
42
|
+
if !Money.strict_eql_compare && fractional == 0 && other_money.fractional == 0
|
|
43
|
+
warn "[DEPRECATION] Comparing 0 #{currency} with 0 " \
|
|
44
|
+
"#{other_money.currency} using `#eql?` will return false in " \
|
|
45
|
+
"future versions of Money. Opt-in to the new behavior by " \
|
|
46
|
+
"setting `Money.strict_eql_compare = true`."
|
|
47
|
+
return true
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
fractional == other_money.fractional && currency == other_money.currency
|
|
41
51
|
else
|
|
42
52
|
false
|
|
43
53
|
end
|
|
@@ -103,30 +113,28 @@ class Money
|
|
|
103
113
|
fractional < 0
|
|
104
114
|
end
|
|
105
115
|
|
|
106
|
-
#
|
|
107
|
-
#
|
|
108
|
-
#
|
|
109
|
-
#
|
|
116
|
+
# @!method +(other)
|
|
117
|
+
# Returns a new Money object containing the sum of the two operands' monetary
|
|
118
|
+
# values. If +other_money+ has a different currency then its monetary value
|
|
119
|
+
# is automatically exchanged to this object's currency using +exchange_to+.
|
|
110
120
|
#
|
|
111
|
-
#
|
|
121
|
+
# @param [Money] other Other +Money+ object to add.
|
|
122
|
+
# @return [Money]
|
|
112
123
|
#
|
|
113
|
-
#
|
|
114
|
-
#
|
|
115
|
-
|
|
116
|
-
#
|
|
117
|
-
#
|
|
118
|
-
#
|
|
119
|
-
#
|
|
120
|
-
#
|
|
121
|
-
# its monetary value is automatically exchanged to this object's currency
|
|
122
|
-
# using +exchange_to+.
|
|
123
|
-
#
|
|
124
|
-
# @param [Money] other Other +Money+ object to subtract.
|
|
124
|
+
# @example
|
|
125
|
+
# Money.new(100) + Money.new(100) #=> #<Money @fractional=200>
|
|
126
|
+
|
|
127
|
+
# @!method -(other)
|
|
128
|
+
# Returns a new Money object containing the difference between the two
|
|
129
|
+
# operands' monetary values. If +other_money+ has a different currency then
|
|
130
|
+
# its monetary value is automatically exchanged to this object's currency
|
|
131
|
+
# using +exchange_to+.
|
|
125
132
|
#
|
|
126
|
-
#
|
|
133
|
+
# @param [Money] other Other +Money+ object to subtract.
|
|
134
|
+
# @return [Money]
|
|
127
135
|
#
|
|
128
|
-
#
|
|
129
|
-
#
|
|
136
|
+
# @example
|
|
137
|
+
# Money.new(100) - Money.new(99) #=> #<Money @fractional=1>
|
|
130
138
|
[:+, :-].each do |op|
|
|
131
139
|
non_zero_message = lambda do |value|
|
|
132
140
|
"Can't add or subtract a non-zero #{value.class.name} value"
|
|
@@ -190,10 +198,15 @@ class Money
|
|
|
190
198
|
#
|
|
191
199
|
def /(value)
|
|
192
200
|
if value.is_a?(self.class)
|
|
193
|
-
|
|
201
|
+
exchanged = value.exchange_to(currency)
|
|
202
|
+
raise ZeroDivisionError, "divided by Money(0)" if exchanged.zero?
|
|
203
|
+
fractional / as_d(exchanged.fractional).to_f
|
|
194
204
|
else
|
|
195
205
|
raise TypeError, 'Can not divide by Money' if value.is_a?(CoercedNumeric)
|
|
196
|
-
|
|
206
|
+
|
|
207
|
+
value = as_d(value)
|
|
208
|
+
raise ZeroDivisionError, "divided by zero" if value.zero?
|
|
209
|
+
dup_with(fractional: fractional / value)
|
|
197
210
|
end
|
|
198
211
|
end
|
|
199
212
|
|
|
@@ -230,13 +243,16 @@ class Money
|
|
|
230
243
|
|
|
231
244
|
def divmod_money(val)
|
|
232
245
|
cents = val.exchange_to(currency).cents
|
|
246
|
+
raise ZeroDivisionError, "divided by Money(0)" if cents == 0
|
|
233
247
|
quotient, remainder = fractional.divmod(cents)
|
|
234
248
|
[quotient, dup_with(fractional: remainder)]
|
|
235
249
|
end
|
|
236
250
|
private :divmod_money
|
|
237
251
|
|
|
238
252
|
def divmod_other(val)
|
|
239
|
-
|
|
253
|
+
val = as_d(val)
|
|
254
|
+
raise ZeroDivisionError, "divided by zero" if val.zero?
|
|
255
|
+
quotient, remainder = fractional.divmod(val)
|
|
240
256
|
[dup_with(fractional: quotient), dup_with(fractional: remainder)]
|
|
241
257
|
end
|
|
242
258
|
private :divmod_other
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
#
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require 'money/money/formatting_rules'
|
|
3
4
|
|
|
4
5
|
class Money
|
|
@@ -31,7 +32,7 @@ class Money
|
|
|
31
32
|
# Money.us_dollar(85).format(with_currency: true) #=> "$0.85 USD"
|
|
32
33
|
#
|
|
33
34
|
# @option rules [Boolean] :rounded_infinite_precision (false) Whether the
|
|
34
|
-
# amount of money should be rounded when using {
|
|
35
|
+
# amount of money should be rounded when using {default_infinite_precision}
|
|
35
36
|
#
|
|
36
37
|
# @example
|
|
37
38
|
# Money.us_dollar(100.1).format #=> "$1.001"
|
|
@@ -82,33 +83,6 @@ class Money
|
|
|
82
83
|
# Money.new(10000000, "INR").format(south_asian_number_formatting: true) #=> "1,00,000.00"
|
|
83
84
|
# Money.new(10000000).format(south_asian_number_formatting: true) #=> "$1,00,000.00"
|
|
84
85
|
#
|
|
85
|
-
# @option rules [Boolean, nil] :symbol_before_without_space (true) Whether
|
|
86
|
-
# a space between the money symbol and the amount should be inserted when
|
|
87
|
-
# +:symbol_position+ is +:before+. The default is true (meaning no space). Ignored
|
|
88
|
-
# if +:symbol+ is false or +:symbol_position+ is not +:before+.
|
|
89
|
-
#
|
|
90
|
-
# @example
|
|
91
|
-
# # Default is to not insert a space.
|
|
92
|
-
# Money.new(100, "USD").format #=> "$1.00"
|
|
93
|
-
#
|
|
94
|
-
# # Same thing.
|
|
95
|
-
# Money.new(100, "USD").format(symbol_before_without_space: true) #=> "$1.00"
|
|
96
|
-
#
|
|
97
|
-
# # If set to false, will insert a space.
|
|
98
|
-
# Money.new(100, "USD").format(symbol_before_without_space: false) #=> "$ 1.00"
|
|
99
|
-
#
|
|
100
|
-
# @option rules [Boolean, nil] :symbol_after_without_space (false) Whether
|
|
101
|
-
# a space between the amount and the money symbol should be inserted when
|
|
102
|
-
# +:symbol_position+ is +:after+. The default is false (meaning space). Ignored
|
|
103
|
-
# if +:symbol+ is false or +:symbol_position+ is not +:after+.
|
|
104
|
-
#
|
|
105
|
-
# @example
|
|
106
|
-
# # Default is to insert a space.
|
|
107
|
-
# Money.new(100, "USD").format(symbol_position: :after) #=> "1.00 $"
|
|
108
|
-
#
|
|
109
|
-
# # If set to true, will not insert a space.
|
|
110
|
-
# Money.new(100, "USD").format(symbol_position: :after, symbol_after_without_space: true) #=> "1.00$"
|
|
111
|
-
#
|
|
112
86
|
# @option rules [Boolean, String, nil] :decimal_mark (true) Whether the
|
|
113
87
|
# currency should be separated by the specified character or '.'
|
|
114
88
|
#
|
|
@@ -139,13 +113,6 @@ class Money
|
|
|
139
113
|
# # default to "," as thousands_separator.
|
|
140
114
|
# Money.new(100000, "FOO").format #=> "$1,000.00"
|
|
141
115
|
#
|
|
142
|
-
# @option rules [Boolean] :html (false) Whether the currency should be
|
|
143
|
-
# HTML-formatted. Only useful in combination with +:with_currency+.
|
|
144
|
-
#
|
|
145
|
-
# @example
|
|
146
|
-
# Money.ca_dollar(570).format(html: true, with_currency: true)
|
|
147
|
-
# #=> "$5.70 <span class=\"currency\">CAD</span>"
|
|
148
|
-
#
|
|
149
116
|
# @option rules [Boolean] :html_wrap (false) Whether all currency parts should be HTML-formatted.
|
|
150
117
|
#
|
|
151
118
|
# @example
|
|
@@ -181,20 +148,6 @@ class Money
|
|
|
181
148
|
# Money.new(10000, "USD").format(disambiguate: true) #=> "$100.00"
|
|
182
149
|
# Money.new(10000, "CAD").format(disambiguate: true) #=> "C$100.00"
|
|
183
150
|
#
|
|
184
|
-
# @option rules [Boolean] :html_wrap_symbol (false) Wraps the currency symbol
|
|
185
|
-
# in a html <span> tag.
|
|
186
|
-
#
|
|
187
|
-
# @example
|
|
188
|
-
# Money.new(10000, "USD").format(disambiguate: false)
|
|
189
|
-
# #=> "<span class=\"currency_symbol\">$100.00</span>
|
|
190
|
-
#
|
|
191
|
-
# @option rules [Symbol] :symbol_position (:before) `:before` if the currency
|
|
192
|
-
# symbol goes before the amount, `:after` if it goes after.
|
|
193
|
-
#
|
|
194
|
-
# @example
|
|
195
|
-
# Money.new(10000, "USD").format(symbol_position: :before) #=> "$100.00"
|
|
196
|
-
# Money.new(10000, "USD").format(symbol_position: :after) #=> "100.00 $"
|
|
197
|
-
#
|
|
198
151
|
# @option rules [Boolean] :translate (true) `true` Checks for custom
|
|
199
152
|
# symbol definitions using I18n.
|
|
200
153
|
#
|
|
@@ -300,9 +253,7 @@ class Money
|
|
|
300
253
|
symbol_value = symbol_value_from(rules)
|
|
301
254
|
|
|
302
255
|
if symbol_value && !symbol_value.empty?
|
|
303
|
-
if rules[:
|
|
304
|
-
symbol_value = "<span class=\"currency_symbol\">#{symbol_value}</span>"
|
|
305
|
-
elsif rules[:html_wrap]
|
|
256
|
+
if rules[:html_wrap]
|
|
306
257
|
symbol_value = html_wrap(symbol_value, "currency-symbol")
|
|
307
258
|
end
|
|
308
259
|
|
|
@@ -316,17 +267,17 @@ class Money
|
|
|
316
267
|
|
|
317
268
|
def append_currency_symbol(formatted_number)
|
|
318
269
|
if rules[:with_currency]
|
|
319
|
-
|
|
270
|
+
currency_part =
|
|
271
|
+
if rules[:html_wrap]
|
|
272
|
+
html_wrap(currency.to_s, "currency")
|
|
273
|
+
else
|
|
274
|
+
currency.to_s
|
|
275
|
+
end
|
|
320
276
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
formatted_number << html_wrap(currency.to_s, "currency")
|
|
325
|
-
else
|
|
326
|
-
formatted_number << currency.to_s
|
|
327
|
-
end
|
|
277
|
+
"#{formatted_number} #{currency_part}"
|
|
278
|
+
else
|
|
279
|
+
formatted_number
|
|
328
280
|
end
|
|
329
|
-
formatted_number
|
|
330
281
|
end
|
|
331
282
|
|
|
332
283
|
def show_free_text?
|
|
@@ -398,7 +349,7 @@ class Money
|
|
|
398
349
|
else
|
|
399
350
|
""
|
|
400
351
|
end
|
|
401
|
-
elsif rules[:
|
|
352
|
+
elsif rules[:html_wrap]
|
|
402
353
|
currency.html_entity == '' ? currency.symbol : currency.html_entity
|
|
403
354
|
elsif rules[:disambiguate] && currency.disambiguate_symbol
|
|
404
355
|
currency.disambiguate_symbol
|