money 6.13.4 → 6.13.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +23 -2
- data/README.md +20 -1
- data/config/currency_backwards_compatible.json +16 -0
- data/config/currency_iso.json +9 -9
- data/lib/money/bank/variable_exchange.rb +14 -6
- data/lib/money/currency.rb +1 -1
- data/lib/money/money/allocation.rb +3 -3
- data/lib/money/money/arithmetic.rb +3 -3
- data/lib/money/money.rb +78 -39
- data/lib/money/rates_store/memory.rb +24 -23
- data/lib/money/version.rb +1 -1
- metadata +3 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1773172616f278d2f107e19153498c029c5f1b63f4ae68a7468ef66fbbef8991
|
4
|
+
data.tar.gz: 035cd8170e536decc4748cd8a6c2ef1b7a7d5e985e6a2ecba0c989f8cf89096c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5636c6323a8538ccc669a2ecfd07a3108adde4f6315e43d0d2b0bb818fc31d1c230ff0ca9715a2c1ca67edcdfa7cb71c9c4d8405410f0764cc82aaad5d3af4e1
|
7
|
+
data.tar.gz: 4b2532f674ca8b665b43c745f5b8cc2beb3d7d5fda0584273bc53d8a42e8a551037758374b6864cfe4b227d61d043282394ed51b62e27f82b8f374ddb27dbe5b
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,26 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 6.13.8
|
4
|
+
- Update symbol for XOF
|
5
|
+
- Update UYU currency symbol
|
6
|
+
- Allow double conversion using same bank
|
7
|
+
- Warn when using unsafe serializer for rate import
|
8
|
+
- Move Icelandic symbol after the amount
|
9
|
+
|
10
|
+
## 6.13.7
|
11
|
+
- Improve deprecation warnings for the upcoming major release
|
12
|
+
|
13
|
+
## 6.13.6
|
14
|
+
- Fix a regression introduced in 6.13.5 that broken RatesStore::Memory subclasses
|
15
|
+
|
16
|
+
## 6.13.5
|
17
|
+
- Raise warning on using Money.default_currency
|
18
|
+
- Raise warning on using default Money.rounding_mode
|
19
|
+
- Add Second Ouguiya MRU 929 to currency iso file
|
20
|
+
- Add symbol for UZS
|
21
|
+
- Use monitor for recursive mutual exclusion in RatesStore::Memory
|
22
|
+
- Allow passing store as a string to Money::Bank::VariableExchange (to support Rails 6)
|
23
|
+
|
3
24
|
## 6.13.4
|
4
25
|
- Update currency config for Zambian Kwacha (ZMW)
|
5
26
|
- Do not modify options passed to FormattingRules
|
@@ -46,7 +67,7 @@
|
|
46
67
|
- Wrap all amount parts when `:html_wrap` option is used
|
47
68
|
- Deprecate `#currency_as_string` and `#currency_as_string=` (in favour of `#with_currency`)
|
48
69
|
- Add `#with_currency` for swapping the currency
|
49
|
-
- Rewrite allocate/split (fixing some penny
|
70
|
+
- Rewrite allocate/split (fixing some penny losing issues)
|
50
71
|
|
51
72
|
## 6.11.3
|
52
73
|
- Fix regression: if enabled use i18n locales in Money#to_s
|
@@ -65,7 +86,7 @@
|
|
65
86
|
- Added new symbol for bitcoin denomination
|
66
87
|
- Specify custom rounding precision when using `infinite_precision`
|
67
88
|
- Allow splits with sums greater than 1
|
68
|
-
- Prevent arithmetic methods from
|
89
|
+
- Prevent arithmetic methods from losing reference to the bank
|
69
90
|
- Fix coerced zero numeric subtraction
|
70
91
|
- Fix south asian formatting to support whole numbers
|
71
92
|
- Refactor formatting logic
|
data/README.md
CHANGED
@@ -21,7 +21,7 @@ A Ruby Library for dealing with money and currency conversion.
|
|
21
21
|
|
22
22
|
### Features
|
23
23
|
|
24
|
-
- Provides a `Money` class which encapsulates all information about
|
24
|
+
- Provides a `Money` class which encapsulates all information about a certain
|
25
25
|
amount of money, such as its value and its currency.
|
26
26
|
- Provides a `Money::Currency` class which encapsulates all information about
|
27
27
|
a monetary unit.
|
@@ -334,6 +334,8 @@ end
|
|
334
334
|
Now you can use it with the default bank.
|
335
335
|
|
336
336
|
```ruby
|
337
|
+
# For Rails 6 pass model name as a string to make it compatible with zeitwerk
|
338
|
+
# Money.default_bank = Money::Bank::VariableExchange.new("ExchangeRate")
|
337
339
|
Money.default_bank = Money::Bank::VariableExchange.new(ExchangeRate)
|
338
340
|
|
339
341
|
# Add to the underlying store
|
@@ -421,6 +423,13 @@ Money.new(2.34567).round.format #=> "$0.02"
|
|
421
423
|
Money.new(2.34567).round(BigDecimal::ROUND_HALF_UP, 2).format #=> "$0.0235"
|
422
424
|
```
|
423
425
|
|
426
|
+
You can set the default rounding mode by passing one of the `BigDecimal` mode enumerables like so:
|
427
|
+
```ruby
|
428
|
+
Money.rounding_mode = BigDecimal::ROUND_HALF_EVEN
|
429
|
+
```
|
430
|
+
See [BigDecimal::ROUND_MODE](https://ruby-doc.org/stdlib-2.5.1/libdoc/bigdecimal/rdoc/BigDecimal.html#ROUND_MODE) for more information
|
431
|
+
|
432
|
+
|
424
433
|
## Ruby on Rails
|
425
434
|
|
426
435
|
To integrate money in a Rails application use [money-rails](https://github.com/RubyMoney/money-rails).
|
@@ -484,6 +493,16 @@ Money.new(10_000_00, 'USD').format # => $10.000,00
|
|
484
493
|
Money.new(10_000_00, 'EUR').format # => €10.000,00
|
485
494
|
```
|
486
495
|
|
496
|
+
If you need to localize the position of the currency symbol, you
|
497
|
+
have to pass it manually. *Note: this will become the default formatting
|
498
|
+
behavior in the next version.*
|
499
|
+
|
500
|
+
```ruby
|
501
|
+
I18n.locale = :fr
|
502
|
+
format = I18n.t :format, scope: 'number.currency.format'
|
503
|
+
Money.new(10_00, 'EUR').format(format: format) # => 10,00 €
|
504
|
+
```
|
505
|
+
|
487
506
|
For the legacy behaviour of "per currency" localization (formatting depends only on currency):
|
488
507
|
|
489
508
|
```ruby
|
@@ -60,6 +60,22 @@
|
|
60
60
|
"iso_numeric": "428",
|
61
61
|
"smallest_denomination": 1
|
62
62
|
},
|
63
|
+
"mro": {
|
64
|
+
"priority": 100,
|
65
|
+
"iso_code": "MRO",
|
66
|
+
"name": "Mauritanian Ouguiya",
|
67
|
+
"symbol": "UM",
|
68
|
+
"disambiguate_symbol": "A-UM",
|
69
|
+
"alternate_symbols": [],
|
70
|
+
"subunit": "Khoums",
|
71
|
+
"subunit_to_unit": 5,
|
72
|
+
"symbol_first": false,
|
73
|
+
"html_entity": "",
|
74
|
+
"decimal_mark": ".",
|
75
|
+
"thousands_separator": ",",
|
76
|
+
"iso_numeric": "478",
|
77
|
+
"smallest_denomination": 1
|
78
|
+
},
|
63
79
|
"mtl": {
|
64
80
|
"priority": 100,
|
65
81
|
"iso_code": "MTL",
|
data/config/currency_iso.json
CHANGED
@@ -1019,11 +1019,11 @@
|
|
1019
1019
|
"priority": 100,
|
1020
1020
|
"iso_code": "ISK",
|
1021
1021
|
"name": "Icelandic Króna",
|
1022
|
-
"symbol": "kr",
|
1022
|
+
"symbol": "kr.",
|
1023
1023
|
"alternate_symbols": ["Íkr"],
|
1024
1024
|
"subunit": null,
|
1025
1025
|
"subunit_to_unit": 1,
|
1026
|
-
"symbol_first":
|
1026
|
+
"symbol_first": false,
|
1027
1027
|
"html_entity": "",
|
1028
1028
|
"decimal_mark": ",",
|
1029
1029
|
"thousands_separator": ".",
|
@@ -1412,9 +1412,9 @@
|
|
1412
1412
|
"iso_numeric": "446",
|
1413
1413
|
"smallest_denomination": 10
|
1414
1414
|
},
|
1415
|
-
"
|
1415
|
+
"mru": {
|
1416
1416
|
"priority": 100,
|
1417
|
-
"iso_code": "
|
1417
|
+
"iso_code": "MRU",
|
1418
1418
|
"name": "Mauritanian Ouguiya",
|
1419
1419
|
"symbol": "UM",
|
1420
1420
|
"alternate_symbols": [],
|
@@ -1424,7 +1424,7 @@
|
|
1424
1424
|
"html_entity": "",
|
1425
1425
|
"decimal_mark": ".",
|
1426
1426
|
"thousands_separator": ",",
|
1427
|
-
"iso_numeric": "
|
1427
|
+
"iso_numeric": "929",
|
1428
1428
|
"smallest_denomination": 1
|
1429
1429
|
},
|
1430
1430
|
"mur": {
|
@@ -2245,12 +2245,12 @@
|
|
2245
2245
|
"priority": 100,
|
2246
2246
|
"iso_code": "UYU",
|
2247
2247
|
"name": "Uruguayan Peso",
|
2248
|
-
"symbol": "$",
|
2248
|
+
"symbol": "$U",
|
2249
2249
|
"alternate_symbols": ["$U"],
|
2250
2250
|
"subunit": "Centésimo",
|
2251
2251
|
"subunit_to_unit": 100,
|
2252
2252
|
"symbol_first": true,
|
2253
|
-
"html_entity": "
|
2253
|
+
"html_entity": "$U",
|
2254
2254
|
"decimal_mark": ",",
|
2255
2255
|
"thousands_separator": ".",
|
2256
2256
|
"iso_numeric": "858",
|
@@ -2260,7 +2260,7 @@
|
|
2260
2260
|
"priority": 100,
|
2261
2261
|
"iso_code": "UZS",
|
2262
2262
|
"name": "Uzbekistan Som",
|
2263
|
-
"symbol": "",
|
2263
|
+
"symbol": "so'm",
|
2264
2264
|
"alternate_symbols": ["so‘m", "сўм", "сум", "s", "с"],
|
2265
2265
|
"subunit": "Tiyin",
|
2266
2266
|
"subunit_to_unit": 100,
|
@@ -2336,7 +2336,7 @@
|
|
2336
2336
|
"priority": 100,
|
2337
2337
|
"iso_code": "XAF",
|
2338
2338
|
"name": "Central African Cfa Franc",
|
2339
|
-
"symbol": "
|
2339
|
+
"symbol": "CFA",
|
2340
2340
|
"disambiguate_symbol": "FCFA",
|
2341
2341
|
"alternate_symbols": ["FCFA"],
|
2342
2342
|
"subunit": "Centime",
|
@@ -42,7 +42,7 @@ class Money
|
|
42
42
|
# bank.get_rate 'USD', 'CAD'
|
43
43
|
class VariableExchange < Base
|
44
44
|
|
45
|
-
attr_reader :mutex
|
45
|
+
attr_reader :mutex
|
46
46
|
|
47
47
|
# Available formats for importing/exporting rates.
|
48
48
|
RATE_FORMATS = [:json, :ruby, :yaml].freeze
|
@@ -61,6 +61,10 @@ class Money
|
|
61
61
|
super(&block)
|
62
62
|
end
|
63
63
|
|
64
|
+
def store
|
65
|
+
@store.is_a?(String) ? Object.const_get(@store) : @store
|
66
|
+
end
|
67
|
+
|
64
68
|
def marshal_dump
|
65
69
|
[store.marshal_dump, @rounding_method]
|
66
70
|
end
|
@@ -110,7 +114,7 @@ class Money
|
|
110
114
|
if rate = get_rate(from.currency, to_currency)
|
111
115
|
fractional = calculate_fractional(from, to_currency)
|
112
116
|
from.class.new(
|
113
|
-
exchange(fractional, rate, &block), to_currency
|
117
|
+
exchange(fractional, rate, &block), to_currency, self
|
114
118
|
)
|
115
119
|
else
|
116
120
|
raise UnknownRate, "No conversion rate known for '#{from.currency.iso_code}' -> '#{to_currency}'"
|
@@ -213,8 +217,7 @@ class Money
|
|
213
217
|
# s = bank.export_rates(:json)
|
214
218
|
# s #=> "{\"USD_TO_CAD\":1.24515,\"CAD_TO_USD\":0.803115}"
|
215
219
|
def export_rates(format, file = nil, opts = {})
|
216
|
-
raise Money::Bank::UnknownRateFormat unless
|
217
|
-
RATE_FORMATS.include? format
|
220
|
+
raise Money::Bank::UnknownRateFormat unless RATE_FORMATS.include?(format)
|
218
221
|
|
219
222
|
store.transaction do
|
220
223
|
s = FORMAT_SERIALIZERS[format].dump(rates)
|
@@ -254,8 +257,13 @@ class Money
|
|
254
257
|
# bank.get_rate("USD", "CAD") #=> 1.24515
|
255
258
|
# bank.get_rate("CAD", "USD") #=> 0.803115
|
256
259
|
def import_rates(format, s, opts = {})
|
257
|
-
raise Money::Bank::UnknownRateFormat unless
|
258
|
-
|
260
|
+
raise Money::Bank::UnknownRateFormat unless RATE_FORMATS.include?(format)
|
261
|
+
|
262
|
+
if format == :ruby
|
263
|
+
warn '[WARNING] Using :ruby format when importing rates is potentially unsafe and ' \
|
264
|
+
'might lead to remote code execution via Marshal.load deserializer. Consider using ' \
|
265
|
+
'safe alternatives such as :json and :yaml.'
|
266
|
+
end
|
259
267
|
|
260
268
|
store.transaction do
|
261
269
|
data = FORMAT_SERIALIZERS[format].load(s)
|
data/lib/money/currency.rb
CHANGED
@@ -414,7 +414,7 @@ class Money
|
|
414
414
|
|
415
415
|
# Returns the relation between subunit and unit as a base 10 exponent.
|
416
416
|
#
|
417
|
-
# Note that MGA and
|
417
|
+
# Note that MGA and MRU are exceptions and are rounded to 1
|
418
418
|
# @see https://en.wikipedia.org/wiki/ISO_4217#Active_codes
|
419
419
|
#
|
420
420
|
# @return [Integer]
|
@@ -2,9 +2,9 @@
|
|
2
2
|
|
3
3
|
class Money
|
4
4
|
class Allocation
|
5
|
-
# Splits a given amount in parts without
|
6
|
-
# The left-over pennies will be distributed round-robin amongst the
|
7
|
-
#
|
5
|
+
# Splits a given amount in parts without losing pennies.
|
6
|
+
# The left-over pennies will be distributed round-robin amongst the parts. This means that
|
7
|
+
# parts listed first will likely receive more pennies than the ones listed later.
|
8
8
|
#
|
9
9
|
# The results should always add up to the original amount.
|
10
10
|
#
|
@@ -46,7 +46,7 @@ class Money
|
|
46
46
|
# Compares two Money objects. If money objects have a different currency it
|
47
47
|
# will attempt to convert the currency.
|
48
48
|
#
|
49
|
-
# @param [Money]
|
49
|
+
# @param [Money] other Value to compare with.
|
50
50
|
#
|
51
51
|
# @return [Integer]
|
52
52
|
#
|
@@ -103,7 +103,7 @@ class Money
|
|
103
103
|
# values. If +other_money+ has a different currency then its monetary value
|
104
104
|
# is automatically exchanged to this object's currency using +exchange_to+.
|
105
105
|
#
|
106
|
-
# @param [Money]
|
106
|
+
# @param [Money] other Other +Money+ object to add.
|
107
107
|
#
|
108
108
|
# @return [Money]
|
109
109
|
#
|
@@ -116,7 +116,7 @@ class Money
|
|
116
116
|
# its monetary value is automatically exchanged to this object's currency
|
117
117
|
# using +exchange_to+.
|
118
118
|
#
|
119
|
-
# @param [Money]
|
119
|
+
# @param [Money] other Other +Money+ object to subtract.
|
120
120
|
#
|
121
121
|
# @return [Money]
|
122
122
|
#
|
data/lib/money/money.rb
CHANGED
@@ -91,51 +91,63 @@ class Money
|
|
91
91
|
class << self
|
92
92
|
|
93
93
|
# @!attribute [rw] default_bank
|
94
|
-
#
|
95
|
-
#
|
96
|
-
#
|
97
|
-
#
|
98
|
-
#
|
94
|
+
# Used to set a default bank for currency exchange.
|
95
|
+
#
|
96
|
+
# Each Money object is associated with a bank
|
97
|
+
# object, which is responsible for currency exchange. This property
|
98
|
+
# allows you to specify the default bank object. The default value for
|
99
|
+
# this property is an instance of +Bank::VariableExchange.+ It allows
|
100
|
+
# one to specify custom exchange rates.
|
101
|
+
#
|
102
|
+
# @return [Money::Bank::Base]
|
99
103
|
#
|
100
104
|
# @!attribute default_formatting_rules
|
101
|
-
#
|
102
|
-
#
|
103
|
-
#
|
104
|
-
#
|
105
|
+
# Used to define a default hash of rules for every time
|
106
|
+
# +Money#format+ is called. Rules provided on method call will be
|
107
|
+
# merged with the default ones. To overwrite a rule, just provide the
|
108
|
+
# intended value while calling +format+.
|
105
109
|
#
|
106
|
-
# @see
|
110
|
+
# @see Money::Formatter#initialize Money::Formatter for more details
|
107
111
|
#
|
108
112
|
# @example
|
109
113
|
# Money.default_formatting_rules = { display_free: true }
|
110
114
|
# Money.new(0, "USD").format # => "free"
|
111
115
|
# Money.new(0, "USD").format(display_free: false) # => "$0.00"
|
112
116
|
#
|
117
|
+
# @return [Hash]
|
118
|
+
#
|
113
119
|
# @!attribute [rw] use_i18n
|
114
|
-
#
|
115
|
-
#
|
120
|
+
# Used to disable i18n even if it's used by other components of your app.
|
121
|
+
#
|
122
|
+
# @return [Boolean]
|
116
123
|
#
|
117
124
|
# @!attribute [rw] infinite_precision
|
118
|
-
#
|
125
|
+
# Used to enable infinite precision cents
|
126
|
+
#
|
127
|
+
# @return [Boolean]
|
119
128
|
#
|
120
129
|
# @!attribute [rw] conversion_precision
|
121
|
-
#
|
122
|
-
# to BigDecimal
|
123
|
-
attr_accessor :default_bank, :default_formatting_rules,
|
124
|
-
:use_i18n, :infinite_precision, :conversion_precision,
|
125
|
-
:locale_backend
|
126
|
-
|
127
|
-
# @attr_writer rounding_mode Use this to specify the rounding mode
|
130
|
+
# Used to specify precision for converting Rational to BigDecimal
|
128
131
|
#
|
129
|
-
#
|
130
|
-
|
131
|
-
|
132
|
-
# default value is Currency.new("USD"). The value must be a valid
|
133
|
-
# +Money::Currency+ instance.
|
134
|
-
attr_writer :rounding_mode, :default_currency
|
132
|
+
# @return [Integer]
|
133
|
+
attr_accessor :default_bank, :default_formatting_rules,
|
134
|
+
:infinite_precision, :conversion_precision
|
135
135
|
|
136
|
+
attr_reader :use_i18n, :locale_backend
|
136
137
|
end
|
137
138
|
|
139
|
+
# @!attribute default_currency
|
140
|
+
# @return [Money::Currency] The default currency, which is used when
|
141
|
+
# +Money.new+ is called without an explicit currency argument. The
|
142
|
+
# default value is Currency.new("USD"). The value must be a valid
|
143
|
+
# +Money::Currency+ instance.
|
138
144
|
def self.default_currency
|
145
|
+
if @using_deprecated_default_currency
|
146
|
+
warn '[WARNING] The default currency will change from `USD` to `nil` in the next major release. Make ' \
|
147
|
+
'sure to set it explicitly using `Money.default_currency=` to avoid potential issues'
|
148
|
+
@using_deprecated_default_currency = false
|
149
|
+
end
|
150
|
+
|
139
151
|
if @default_currency.respond_to?(:call)
|
140
152
|
Money::Currency.new(@default_currency.call)
|
141
153
|
else
|
@@ -143,10 +155,21 @@ class Money
|
|
143
155
|
end
|
144
156
|
end
|
145
157
|
|
158
|
+
def self.default_currency=(currency)
|
159
|
+
@using_deprecated_default_currency = false
|
160
|
+
@default_currency = currency
|
161
|
+
end
|
162
|
+
|
146
163
|
def self.locale_backend=(value)
|
147
164
|
@locale_backend = value ? LocaleBackend.find(value) : nil
|
148
165
|
end
|
149
166
|
|
167
|
+
# @attr_writer rounding_mode Use this to specify the rounding mode
|
168
|
+
def self.rounding_mode=(new_rounding_mode)
|
169
|
+
@using_deprecated_default_rounding_mode = false
|
170
|
+
@rounding_mode = new_rounding_mode
|
171
|
+
end
|
172
|
+
|
150
173
|
def self.use_i18n=(value)
|
151
174
|
if value
|
152
175
|
warn '[DEPRECATION] `use_i18n` is deprecated - use `Money.locale_backend = :i18n` instead for locale based formatting'
|
@@ -163,6 +186,7 @@ class Money
|
|
163
186
|
|
164
187
|
# Set the default currency for creating new +Money+ object.
|
165
188
|
self.default_currency = Currency.new("USD")
|
189
|
+
@using_deprecated_default_currency = true
|
166
190
|
|
167
191
|
# Default to using i18n
|
168
192
|
@use_i18n = true
|
@@ -175,6 +199,7 @@ class Money
|
|
175
199
|
|
176
200
|
# Default to bankers rounding
|
177
201
|
self.rounding_mode = BigDecimal::ROUND_HALF_EVEN
|
202
|
+
@using_deprecated_default_rounding_mode = true
|
178
203
|
|
179
204
|
# Default the conversion of Rationals precision to 16
|
180
205
|
self.conversion_precision = 16
|
@@ -192,18 +217,30 @@ class Money
|
|
192
217
|
#
|
193
218
|
# @return [BigDecimal::ROUND_MODE] rounding mode
|
194
219
|
def self.rounding_mode(mode = nil)
|
195
|
-
|
220
|
+
if mode
|
221
|
+
warn "[DEPRECATION] calling `rounding_mode` with a block is deprecated. Please use `.with_rounding_mode` instead."
|
222
|
+
return with_rounding_mode(mode) { yield }
|
223
|
+
end
|
196
224
|
|
197
|
-
|
198
|
-
|
225
|
+
return Thread.current[:money_rounding_mode] if Thread.current[:money_rounding_mode]
|
226
|
+
|
227
|
+
if @using_deprecated_default_rounding_mode
|
228
|
+
warn '[WARNING] The default rounding mode will change from `ROUND_HALF_EVEN` to `ROUND_HALF_UP` in the ' \
|
229
|
+
'next major release. Set it explicitly using `Money.rounding_mode=` to avoid potential problems.'
|
230
|
+
@using_deprecated_default_rounding_mode = false
|
231
|
+
end
|
232
|
+
|
233
|
+
@rounding_mode
|
199
234
|
end
|
200
235
|
|
201
|
-
#
|
202
|
-
# results of the block instead.
|
236
|
+
# Temporarily changes the rounding mode in a given block.
|
203
237
|
#
|
204
238
|
# @param [BigDecimal::ROUND_MODE] mode
|
205
239
|
#
|
206
|
-
# @
|
240
|
+
# @yield The block within which rounding mode will be changed. Its return
|
241
|
+
# value will also be the return value of the whole method.
|
242
|
+
#
|
243
|
+
# @return [Object] block results
|
207
244
|
#
|
208
245
|
# @example
|
209
246
|
# fee = Money.with_rounding_mode(BigDecimal::ROUND_HALF_UP) do
|
@@ -509,13 +546,15 @@ class Money
|
|
509
546
|
exchange_to("EUR")
|
510
547
|
end
|
511
548
|
|
512
|
-
# Splits a given amount in parts without
|
513
|
-
# distributed round-robin amongst the parties. This means that
|
514
|
-
# receive more pennies than ones
|
549
|
+
# Splits a given amount in parts without losing pennies. The left-over pennies will be
|
550
|
+
# distributed round-robin amongst the parties. This means that parts listed first will likely
|
551
|
+
# receive more pennies than ones listed later.
|
552
|
+
#
|
553
|
+
# Pass [2, 1, 1] as input to give twice as much to part1 as part2 or
|
554
|
+
# part3 which results in 50% of the cash to party1, 25% to part2, and 25% to part3. Passing a
|
555
|
+
# number instead of an array will split the amount evenly (without losing pennies when rounding).
|
515
556
|
#
|
516
|
-
# @param [Array<Numeric>, Numeric]
|
517
|
-
# party3 which results in 50% of the cash to party1, 25% to party2, and 25% to party3. Passing a
|
518
|
-
# number instead of an array will split the amount evenly (without loosing pennies when rounding).
|
557
|
+
# @param [Array<Numeric>, Numeric] parts how amount should be distributed to parts
|
519
558
|
#
|
520
559
|
# @return [Array<Money>]
|
521
560
|
#
|
@@ -553,7 +592,7 @@ class Money
|
|
553
592
|
|
554
593
|
# Creates a formatted price string according to several rules.
|
555
594
|
#
|
556
|
-
# @param [Hash] See Money::Formatter for the list of formatting options
|
595
|
+
# @param [Hash] rules See {Money::Formatter Money::Formatter} for the list of formatting options
|
557
596
|
#
|
558
597
|
# @return [String]
|
559
598
|
#
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'monitor'
|
2
|
+
|
1
3
|
class Money
|
2
4
|
module RatesStore
|
3
5
|
|
@@ -17,11 +19,11 @@ class Money
|
|
17
19
|
#
|
18
20
|
# @param [Hash] opts Optional store options.
|
19
21
|
# @option opts [Boolean] :without_mutex disables the usage of a mutex
|
20
|
-
# @param [Hash]
|
21
|
-
def initialize(opts = {},
|
22
|
-
@
|
23
|
-
@
|
24
|
-
@
|
22
|
+
# @param [Hash] rates Optional initial exchange rate data.
|
23
|
+
def initialize(opts = {}, rates = {})
|
24
|
+
@rates = rates
|
25
|
+
@options = opts
|
26
|
+
@guard = Monitor.new
|
25
27
|
end
|
26
28
|
|
27
29
|
# Registers a conversion rate and returns it. Uses +Mutex+ to synchronize data access.
|
@@ -37,7 +39,9 @@ class Money
|
|
37
39
|
# store.add_rate("USD", "CAD", 1.24515)
|
38
40
|
# store.add_rate("CAD", "USD", 0.803115)
|
39
41
|
def add_rate(currency_iso_from, currency_iso_to, rate)
|
40
|
-
|
42
|
+
guard.synchronize do
|
43
|
+
rates[rate_key_for(currency_iso_from, currency_iso_to)] = rate
|
44
|
+
end
|
41
45
|
end
|
42
46
|
|
43
47
|
# Retrieve the rate for the given currencies. Uses +Mutex+ to synchronize data access.
|
@@ -54,24 +58,21 @@ class Money
|
|
54
58
|
#
|
55
59
|
# store.get_rate("USD", "CAD") #=> 1.24515
|
56
60
|
def get_rate(currency_iso_from, currency_iso_to)
|
57
|
-
|
61
|
+
guard.synchronize do
|
62
|
+
rates[rate_key_for(currency_iso_from, currency_iso_to)]
|
63
|
+
end
|
58
64
|
end
|
59
65
|
|
60
66
|
def marshal_dump
|
61
|
-
|
67
|
+
guard.synchronize do
|
68
|
+
return [self.class, options, rates.dup]
|
69
|
+
end
|
62
70
|
end
|
63
71
|
|
64
72
|
# Wraps block execution in a thread-safe transaction
|
65
73
|
def transaction(&block)
|
66
|
-
|
67
|
-
|
68
|
-
else
|
69
|
-
@mutex.synchronize do
|
70
|
-
@in_transaction = true
|
71
|
-
result = block.call
|
72
|
-
@in_transaction = false
|
73
|
-
result
|
74
|
-
end
|
74
|
+
guard.synchronize do
|
75
|
+
yield
|
75
76
|
end
|
76
77
|
end
|
77
78
|
|
@@ -88,19 +89,19 @@ class Money
|
|
88
89
|
# puts [iso_from, iso_to, rate].join
|
89
90
|
# end
|
90
91
|
def each_rate(&block)
|
91
|
-
|
92
|
-
|
92
|
+
return to_enum(:each_rate) unless block_given?
|
93
|
+
|
94
|
+
guard.synchronize do
|
95
|
+
rates.each do |key, rate|
|
93
96
|
iso_from, iso_to = key.split(INDEX_KEY_SEPARATOR)
|
94
|
-
|
97
|
+
yield iso_from, iso_to, rate
|
95
98
|
end
|
96
99
|
end
|
97
|
-
|
98
|
-
block_given? ? enum.each(&block) : enum
|
99
100
|
end
|
100
101
|
|
101
102
|
private
|
102
103
|
|
103
|
-
attr_reader :
|
104
|
+
attr_reader :rates, :options, :guard
|
104
105
|
|
105
106
|
# Return the rate hashkey for the given currencies.
|
106
107
|
#
|
data/lib/money/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: money
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.13.
|
4
|
+
version: 6.13.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shane Emmons
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2020-07-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: i18n
|
@@ -159,8 +159,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
159
159
|
- !ruby/object:Gem::Version
|
160
160
|
version: '0'
|
161
161
|
requirements: []
|
162
|
-
|
163
|
-
rubygems_version: 2.6.8
|
162
|
+
rubygems_version: 3.1.2
|
164
163
|
signing_key:
|
165
164
|
specification_version: 4
|
166
165
|
summary: A Ruby Library for dealing with money and currency conversion.
|