money 6.13.3 → 6.13.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: f37a415a5295b884c2d1c5c55a94d1bb68856a01
4
- data.tar.gz: efea099f7b00a66f8ccda8099426ba16edd8b1f0
2
+ SHA256:
3
+ metadata.gz: 1773172616f278d2f107e19153498c029c5f1b63f4ae68a7468ef66fbbef8991
4
+ data.tar.gz: 035cd8170e536decc4748cd8a6c2ef1b7a7d5e985e6a2ecba0c989f8cf89096c
5
5
  SHA512:
6
- metadata.gz: 60c02cb6a321987bacea58784b5707337ff09dcf793189a9ffee28f6eee73fd57b5bedd49948a08215c7d6a7e9e124d713a33cf04fc55cc77b57b749545250c8
7
- data.tar.gz: 17120c61dd889fd9de0f5c498497cedb4aa4b7b4f27c477e6069b6cdc1017b3fb77453d761c34a7fd07baef08295d5ce979a094344a888c3219f0d698733869c
6
+ metadata.gz: 5636c6323a8538ccc669a2ecfd07a3108adde4f6315e43d0d2b0bb818fc31d1c230ff0ca9715a2c1ca67edcdfa7cb71c9c4d8405410f0764cc82aaad5d3af4e1
7
+ data.tar.gz: 4b2532f674ca8b665b43c745f5b8cc2beb3d7d5fda0584273bc53d8a42e8a551037758374b6864cfe4b227d61d043282394ed51b62e27f82b8f374ddb27dbe5b
@@ -1,9 +1,34 @@
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
+
24
+ ## 6.13.4
25
+ - Update currency config for Zambian Kwacha (ZMW)
26
+ - Do not modify options passed to FormattingRules
27
+
3
28
  ## 6.13.3
4
29
  - Remove specs from the packaged gem
5
30
  - Use Currency::Loader directly without extending
6
- - Add Money.with_rounding_mode as a replacement for calling Money.roudning_mode with a block
31
+ - Add Money.with_rounding_mode as a replacement for calling Money.rounding_mode with a block
7
32
  - Fix currency search for two digit ISO numbers
8
33
  - Add description to TypeError raised by +/- operations
9
34
 
@@ -42,7 +67,7 @@
42
67
  - Wrap all amount parts when `:html_wrap` option is used
43
68
  - Deprecate `#currency_as_string` and `#currency_as_string=` (in favour of `#with_currency`)
44
69
  - Add `#with_currency` for swapping the currency
45
- - Rewrite allocate/split (fixing some penny loosing issues)
70
+ - Rewrite allocate/split (fixing some penny losing issues)
46
71
 
47
72
  ## 6.11.3
48
73
  - Fix regression: if enabled use i18n locales in Money#to_s
@@ -61,7 +86,7 @@
61
86
  - Added new symbol for bitcoin denomination
62
87
  - Specify custom rounding precision when using `infinite_precision`
63
88
  - Allow splits with sums greater than 1
64
- - Prevent arithmetic methods from loosing reference to the bank
89
+ - Prevent arithmetic methods from losing reference to the bank
65
90
  - Fix coerced zero numeric subtraction
66
91
  - Fix south asian formatting to support whole numbers
67
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 an certain
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.
@@ -253,7 +253,7 @@ The default bank is initialized with an in-memory store for exchange rates.
253
253
  Money.default_bank = Money::Bank::VariableExchange.new(Money::RatesStore::Memory.new)
254
254
  ```
255
255
 
256
- You can pass you own store implementation, ie. for storing and retrieving rates off a database, file, cache, etc.
256
+ You can pass your own store implementation, i.e. for storing and retrieving rates off a database, file, cache, etc.
257
257
 
258
258
  ```ruby
259
259
  Money.default_bank = Money::Bank::VariableExchange.new(MyCustomStore.new)
@@ -270,7 +270,7 @@ Stores must implement the following interface:
270
270
  # @return [Numeric] rate.
271
271
  def add_rate(iso_from, iso_to, rate); end
272
272
 
273
- # Get rate. Must be idempotent. ie. adding the same rate must not produce duplicates.
273
+ # Get rate. Must be idempotent. i.e. adding the same rate must not produce duplicates.
274
274
  # @param [String] iso_from Currency ISO code. ex. 'USD'
275
275
  # @param [String] iso_to Currency ISO code. ex. 'CAD'
276
276
  #
@@ -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",
@@ -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": true,
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
- "mro": {
1415
+ "mru": {
1416
1416
  "priority": 100,
1417
- "iso_code": "MRO",
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": "478",
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": "Fr",
2339
+ "symbol": "CFA",
2340
2340
  "disambiguate_symbol": "FCFA",
2341
2341
  "alternate_symbols": ["FCFA"],
2342
2342
  "subunit": "Centime",
@@ -2594,12 +2594,12 @@
2594
2594
  "priority": 100,
2595
2595
  "iso_code": "ZMW",
2596
2596
  "name": "Zambian Kwacha",
2597
- "symbol": "ZK",
2597
+ "symbol": "K",
2598
2598
  "disambiguate_symbol": "ZMW",
2599
2599
  "alternate_symbols": [],
2600
2600
  "subunit": "Ngwee",
2601
2601
  "subunit_to_unit": 100,
2602
- "symbol_first": false,
2602
+ "symbol_first": true,
2603
2603
  "html_entity": "",
2604
2604
  "decimal_mark": ".",
2605
2605
  "thousands_separator": ",",
@@ -42,7 +42,7 @@ class Money
42
42
  # bank.get_rate 'USD', 'CAD'
43
43
  class VariableExchange < Base
44
44
 
45
- attr_reader :mutex, :store
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
- RATE_FORMATS.include? format
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)
@@ -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 MRO are exceptions and are rounded to 1
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]
@@ -91,51 +91,63 @@ class Money
91
91
  class << self
92
92
 
93
93
  # @!attribute [rw] default_bank
94
- # @return [Money::Bank::Base] Each Money object is associated to a bank
95
- # object, which is responsible for currency exchange. This property
96
- # allows you to specify the default bank object. The default value for
97
- # this property is an instance of +Bank::VariableExchange.+ It allows
98
- # one to specify custom exchange rates.
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
- # @return [Hash] Use this to define a default hash of rules for every time
102
- # +Money#format+ is called. Rules provided on method call will be
103
- # merged with the default ones. To overwrite a rule, just provide the
104
- # intended value while calling +format+.
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 +Money::Formatting#format+ for more details.
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
- # @return [Boolean] Use this to disable i18n even if it's used by other
115
- # objects in your app.
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
- # @return [Boolean] Use this to enable infinite precision cents
125
+ # Used to enable infinite precision cents
126
+ #
127
+ # @return [Boolean]
119
128
  #
120
129
  # @!attribute [rw] conversion_precision
121
- # @return [Integer] Use this to specify precision for converting Rational
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
- # @!attribute default_currency
130
- # @return [Money::Currency] The default currency, which is used when
131
- # +Money.new+ is called without an explicit currency argument. The
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
- return Thread.current[:money_rounding_mode] || @rounding_mode unless mode
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
- warn "[DEPRECATION] calling `rounding_mode` with a block is deprecated. Please use `.with_rounding_mode` instead."
198
- with_rounding_mode(mode) { yield }
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
- # This method temporarily changes the rounding mode. It will then return the
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
- # @return [BigDecimal::ROUND_MODE,Yield] block results
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 loosing pennies. The left-over pennies will be
513
- # distributed round-robin amongst the parties. This means that parties listed first will likely
514
- # receive more pennies than ones that are listed later.
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] pass [2, 1, 1] to give twice as much to party1 as party2 or
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
  #
@@ -2,9 +2,9 @@
2
2
 
3
3
  class Money
4
4
  class Allocation
5
- # Splits a given amount in parts without loosing pennies.
6
- # The left-over pennies will be distributed round-robin amongst the parties. This means that
7
- # parties listed first will likely receive more pennies than ones that are listed later.
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] other_money Value to compare with.
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] other_money Other +Money+ object to add.
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] other_money Other +Money+ object to subtract.
119
+ # @param [Money] other Other +Money+ object to subtract.
120
120
  #
121
121
  # @return [Money]
122
122
  #
@@ -38,6 +38,7 @@ class Money
38
38
  rules = {}
39
39
  elsif rules.size == 1
40
40
  rules = rules.pop
41
+ rules = rules.dup if rules.is_a?(Hash)
41
42
 
42
43
  if rules.is_a?(Symbol)
43
44
  warn '[DEPRECATION] Use Hash when passing rules to Money#format.'
@@ -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] rt Optional initial exchange rate data.
21
- def initialize(opts = {}, rt = {})
22
- @options, @index = opts, rt
23
- @mutex = Mutex.new
24
- @in_transaction = false
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
- transaction { index[rate_key_for(currency_iso_from, currency_iso_to)] = rate }
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
- transaction { index[rate_key_for(currency_iso_from, currency_iso_to)] }
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
- [self.class, options, index]
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
- if @in_transaction || options[:without_mutex]
67
- block.call self
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
- enum = Enumerator.new do |yielder|
92
- index.each do |key, rate|
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
- yielder.yield iso_from, iso_to, rate
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 :index, :options
104
+ attr_reader :rates, :options, :guard
104
105
 
105
106
  # Return the rate hashkey for the given currencies.
106
107
  #
@@ -1,3 +1,3 @@
1
1
  class Money
2
- VERSION = '6.13.3'
2
+ VERSION = '6.13.8'
3
3
  end
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.3
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: 2019-04-14 00:00:00.000000000 Z
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
- rubyforge_project:
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.