minting 1.7.3 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/doc/method_list.html CHANGED
@@ -135,6 +135,22 @@
135
135
  </li>
136
136
 
137
137
 
138
+ <li class="even ">
139
+ <div class="item">
140
+ <span class='object_link'><a href="Mint/Rounding.html#apply-class_method" title="Mint::Rounding.apply (method)">apply</a></span>
141
+ <small>Mint::Rounding</small>
142
+ </div>
143
+ </li>
144
+
145
+
146
+ <li class="odd ">
147
+ <div class="item">
148
+ <span class='object_link'><a href="Mint/Money.html#change-instance_method" title="Mint::Money#change (method)">#change</a></span>
149
+ <small>Mint::Money</small>
150
+ </div>
151
+ </li>
152
+
153
+
138
154
  <li class="even ">
139
155
  <div class="item">
140
156
  <span class='object_link'><a href="Mint/Money.html#clamp-instance_method" title="Mint::Money#clamp (method)">#clamp</a></span>
@@ -201,45 +217,53 @@
201
217
 
202
218
  <li class="even ">
203
219
  <div class="item">
204
- <span class='object_link'><a href="Mint.html#currency_for_code-class_method" title="Mint.currency_for_code (method)">currency_for_code</a></span>
205
- <small>Mint</small>
220
+ <span class='object_link'><a href="Mint/Registry.html#currency_for_symbol-instance_method" title="Mint::Registry#currency_for_symbol (method)">#currency_for_symbol</a></span>
221
+ <small>Mint::Registry</small>
206
222
  </div>
207
223
  </li>
208
224
 
209
225
 
210
226
  <li class="odd ">
211
227
  <div class="item">
212
- <span class='object_link'><a href="Mint/Registry.html#currency_for_symbol-instance_method" title="Mint::Registry#currency_for_symbol (method)">#currency_for_symbol</a></span>
213
- <small>Mint::Registry</small>
228
+ <span class='object_link'><a href="Mint/Rounding.html#current_mode-class_method" title="Mint::Rounding.current_mode (method)">current_mode</a></span>
229
+ <small>Mint::Rounding</small>
214
230
  </div>
215
231
  </li>
216
232
 
217
233
 
218
234
  <li class="even ">
219
235
  <div class="item">
220
- <span class='object_link'><a href="Mint.html#currency_for_symbol-class_method" title="Mint.currency_for_symbol (method)">currency_for_symbol</a></span>
221
- <small>Mint</small>
236
+ <span class='object_link'><a href="Mint/Registry.html#detect_currency-instance_method" title="Mint::Registry#detect_currency (method)">#detect_currency</a></span>
237
+ <small>Mint::Registry</small>
222
238
  </div>
223
239
  </li>
224
240
 
225
241
 
226
242
  <li class="odd ">
227
243
  <div class="item">
228
- <span class='object_link'><a href="Mint/Registry.html#detect_currency-instance_method" title="Mint::Registry#detect_currency (method)">#detect_currency</a></span>
229
- <small>Mint::Registry</small>
244
+ <span class='object_link'><a href="Mint/Money.html#eql%3F-instance_method" title="Mint::Money#eql? (method)">#eql?</a></span>
245
+ <small>Mint::Money</small>
230
246
  </div>
231
247
  </li>
232
248
 
233
249
 
234
250
  <li class="even ">
235
251
  <div class="item">
236
- <span class='object_link'><a href="Mint/Money.html#eql%3F-instance_method" title="Mint::Money#eql? (method)">#eql?</a></span>
237
- <small>Mint::Money</small>
252
+ <span class='object_link'><a href="Mint/Currency.html#for_code-class_method" title="Mint::Currency.for_code (method)">for_code</a></span>
253
+ <small>Mint::Currency</small>
238
254
  </div>
239
255
  </li>
240
256
 
241
257
 
242
258
  <li class="odd ">
259
+ <div class="item">
260
+ <span class='object_link'><a href="Mint/Currency.html#for_symbol-class_method" title="Mint::Currency.for_symbol (method)">for_symbol</a></span>
261
+ <small>Mint::Currency</small>
262
+ </div>
263
+ </li>
264
+
265
+
266
+ <li class="even ">
243
267
  <div class="item">
244
268
  <span class='object_link'><a href="Mint/Money.html#fractional-instance_method" title="Mint::Money#fractional (method)">#fractional</a></span>
245
269
  <small>Mint::Money</small>
@@ -247,7 +271,7 @@
247
271
  </li>
248
272
 
249
273
 
250
- <li class="even ">
274
+ <li class="odd ">
251
275
  <div class="item">
252
276
  <span class='object_link'><a href="Mint/Currency.html#fractional_multiplier-instance_method" title="Mint::Currency#fractional_multiplier (method)">#fractional_multiplier</a></span>
253
277
  <small>Mint::Currency</small>
@@ -255,6 +279,14 @@
255
279
  </li>
256
280
 
257
281
 
282
+ <li class="even ">
283
+ <div class="item">
284
+ <span class='object_link'><a href="Mint/Money.html#from-class_method" title="Mint::Money.from (method)">from</a></span>
285
+ <small>Mint::Money</small>
286
+ </div>
287
+ </li>
288
+
289
+
258
290
  <li class="odd ">
259
291
  <div class="item">
260
292
  <span class='object_link'><a href="Mint/Money.html#from_fractional-class_method" title="Mint::Money.from_fractional (method)">from_fractional</a></span>
@@ -281,16 +313,16 @@
281
313
 
282
314
  <li class="even ">
283
315
  <div class="item">
284
- <span class='object_link'><a href="Mint/Currency.html#inspect-instance_method" title="Mint::Currency#inspect (method)">#inspect</a></span>
285
- <small>Mint::Currency</small>
316
+ <span class='object_link'><a href="Mint/Money.html#inspect-instance_method" title="Mint::Money#inspect (method)">#inspect</a></span>
317
+ <small>Mint::Money</small>
286
318
  </div>
287
319
  </li>
288
320
 
289
321
 
290
322
  <li class="odd ">
291
323
  <div class="item">
292
- <span class='object_link'><a href="Mint/Money.html#inspect-instance_method" title="Mint::Money#inspect (method)">#inspect</a></span>
293
- <small>Mint::Money</small>
324
+ <span class='object_link'><a href="Mint/Currency.html#inspect-instance_method" title="Mint::Currency#inspect (method)">#inspect</a></span>
325
+ <small>Mint::Currency</small>
294
326
  </div>
295
327
  </li>
296
328
 
@@ -369,13 +401,37 @@
369
401
 
370
402
  <li class="odd ">
371
403
  <div class="item">
372
- <span class='object_link'><a href="Mint/Money.html#positive%3F-instance_method" title="Mint::Money#positive? (method)">#positive?</a></span>
404
+ <span class='object_link'><a href="Mint/Money.html#parse-class_method" title="Mint::Money.parse (method)">parse</a></span>
373
405
  <small>Mint::Money</small>
374
406
  </div>
375
407
  </li>
376
408
 
377
409
 
378
410
  <li class="even ">
411
+ <div class="item">
412
+ <span class='object_link'><a href="Mint/Money.html#parse!-class_method" title="Mint::Money.parse! (method)">parse!</a></span>
413
+ <small>Mint::Money</small>
414
+ </div>
415
+ </li>
416
+
417
+
418
+ <li class="odd ">
419
+ <div class="item">
420
+ <span class='object_link'><a href="Mint.html#parse!-instance_method" title="Mint#parse! (method)">#parse!</a></span>
421
+ <small>Mint</small>
422
+ </div>
423
+ </li>
424
+
425
+
426
+ <li class="even ">
427
+ <div class="item">
428
+ <span class='object_link'><a href="Mint/Money.html#positive%3F-instance_method" title="Mint::Money#positive? (method)">#positive?</a></span>
429
+ <small>Mint::Money</small>
430
+ </div>
431
+ </li>
432
+
433
+
434
+ <li class="odd ">
379
435
  <div class="item">
380
436
  <span class='object_link'><a href="Mint/Currency.html#priority-instance_method" title="Mint::Currency#priority (method)">#priority</a></span>
381
437
  <small>Mint::Currency</small>
@@ -383,7 +439,7 @@
383
439
  </li>
384
440
 
385
441
 
386
- <li class="odd ">
442
+ <li class="even ">
387
443
  <div class="item">
388
444
  <span class='object_link'><a href="Mint/Registry.html#register-class_method" title="Mint::Registry.register (method)">register</a></span>
389
445
  <small>Mint::Registry</small>
@@ -391,15 +447,15 @@
391
447
  </li>
392
448
 
393
449
 
394
- <li class="even ">
450
+ <li class="odd ">
395
451
  <div class="item">
396
- <span class='object_link'><a href="Mint.html#register_currency-class_method" title="Mint.register_currency (method)">register_currency</a></span>
397
- <small>Mint</small>
452
+ <span class='object_link'><a href="Mint/Currency.html#register-class_method" title="Mint::Currency.register (method)">register</a></span>
453
+ <small>Mint::Currency</small>
398
454
  </div>
399
455
  </li>
400
456
 
401
457
 
402
- <li class="odd ">
458
+ <li class="even ">
403
459
  <div class="item">
404
460
  <span class='object_link'><a href="Mint/Currency.html#resolve-class_method" title="Mint::Currency.resolve (method)">resolve</a></span>
405
461
  <small>Mint::Currency</small>
@@ -407,7 +463,7 @@
407
463
  </li>
408
464
 
409
465
 
410
- <li class="even ">
466
+ <li class="odd ">
411
467
  <div class="item">
412
468
  <span class='object_link'><a href="Mint/Currency.html#resolve!-class_method" title="Mint::Currency.resolve! (method)">resolve!</a></span>
413
469
  <small>Mint::Currency</small>
@@ -415,7 +471,7 @@
415
471
  </li>
416
472
 
417
473
 
418
- <li class="odd ">
474
+ <li class="even ">
419
475
  <div class="item">
420
476
  <span class='object_link'><a href="Mint/Money.html#same_currency%3F-instance_method" title="Mint::Money#same_currency? (method)">#same_currency?</a></span>
421
477
  <small>Mint::Money</small>
@@ -423,7 +479,7 @@
423
479
  </li>
424
480
 
425
481
 
426
- <li class="even ">
482
+ <li class="odd ">
427
483
  <div class="item">
428
484
  <span class='object_link'><a href="Mint/Money.html#split-instance_method" title="Mint::Money#split (method)">#split</a></span>
429
485
  <small>Mint::Money</small>
@@ -431,7 +487,7 @@
431
487
  </li>
432
488
 
433
489
 
434
- <li class="odd ">
490
+ <li class="even ">
435
491
  <div class="item">
436
492
  <span class='object_link'><a href="Mint/RangeStepPatch.html#step-instance_method" title="Mint::RangeStepPatch#step (method)">#step</a></span>
437
493
  <small>Mint::RangeStepPatch</small>
@@ -439,7 +495,7 @@
439
495
  </li>
440
496
 
441
497
 
442
- <li class="even ">
498
+ <li class="odd ">
443
499
  <div class="item">
444
500
  <span class='object_link'><a href="Mint/Currency.html#subunit-instance_method" title="Mint::Currency#subunit (method)">#subunit</a></span>
445
501
  <small>Mint::Currency</small>
@@ -447,7 +503,7 @@
447
503
  </li>
448
504
 
449
505
 
450
- <li class="odd ">
506
+ <li class="even ">
451
507
  <div class="item">
452
508
  <span class='object_link'><a href="Mint/Money.html#succ-instance_method" title="Mint::Money#succ (method)">#succ</a></span>
453
509
  <small>Mint::Money</small>
@@ -455,7 +511,7 @@
455
511
  </li>
456
512
 
457
513
 
458
- <li class="even ">
514
+ <li class="odd ">
459
515
  <div class="item">
460
516
  <span class='object_link'><a href="Mint/Currency.html#symbol-instance_method" title="Mint::Currency#symbol (method)">#symbol</a></span>
461
517
  <small>Mint::Currency</small>
@@ -463,7 +519,7 @@
463
519
  </li>
464
520
 
465
521
 
466
- <li class="odd ">
522
+ <li class="even ">
467
523
  <div class="item">
468
524
  <span class='object_link'><a href="Mint/Money.html#to_d-instance_method" title="Mint::Money#to_d (method)">#to_d</a></span>
469
525
  <small>Mint::Money</small>
@@ -471,7 +527,7 @@
471
527
  </li>
472
528
 
473
529
 
474
- <li class="even ">
530
+ <li class="odd ">
475
531
  <div class="item">
476
532
  <span class='object_link'><a href="Mint/Money.html#to_f-instance_method" title="Mint::Money#to_f (method)">#to_f</a></span>
477
533
  <small>Mint::Money</small>
@@ -479,7 +535,7 @@
479
535
  </li>
480
536
 
481
537
 
482
- <li class="odd ">
538
+ <li class="even ">
483
539
  <div class="item">
484
540
  <span class='object_link'><a href="Mint/Money.html#to_hash-instance_method" title="Mint::Money#to_hash (method)">#to_hash</a></span>
485
541
  <small>Mint::Money</small>
@@ -487,7 +543,7 @@
487
543
  </li>
488
544
 
489
545
 
490
- <li class="even ">
546
+ <li class="odd ">
491
547
  <div class="item">
492
548
  <span class='object_link'><a href="Mint/Money.html#to_html-instance_method" title="Mint::Money#to_html (method)">#to_html</a></span>
493
549
  <small>Mint::Money</small>
@@ -495,7 +551,7 @@
495
551
  </li>
496
552
 
497
553
 
498
- <li class="odd ">
554
+ <li class="even ">
499
555
  <div class="item">
500
556
  <span class='object_link'><a href="Mint/Money.html#to_i-instance_method" title="Mint::Money#to_i (method)">#to_i</a></span>
501
557
  <small>Mint::Money</small>
@@ -503,7 +559,7 @@
503
559
  </li>
504
560
 
505
561
 
506
- <li class="even ">
562
+ <li class="odd ">
507
563
  <div class="item">
508
564
  <span class='object_link'><a href="Mint/Money.html#to_json-instance_method" title="Mint::Money#to_json (method)">#to_json</a></span>
509
565
  <small>Mint::Money</small>
@@ -511,7 +567,7 @@
511
567
  </li>
512
568
 
513
569
 
514
- <li class="odd ">
570
+ <li class="even ">
515
571
  <div class="item">
516
572
  <span class='object_link'><a href="Mint/Money.html#to_r-instance_method" title="Mint::Money#to_r (method)">#to_r</a></span>
517
573
  <small>Mint::Money</small>
@@ -519,7 +575,7 @@
519
575
  </li>
520
576
 
521
577
 
522
- <li class="even ">
578
+ <li class="odd ">
523
579
  <div class="item">
524
580
  <span class='object_link'><a href="Mint/Money.html#to_s-instance_method" title="Mint::Money#to_s (method)">#to_s</a></span>
525
581
  <small>Mint::Money</small>
@@ -527,7 +583,7 @@
527
583
  </li>
528
584
 
529
585
 
530
- <li class="odd ">
586
+ <li class="even ">
531
587
  <div class="item">
532
588
  <span class='object_link'><a href="Mint.html#use_top_level_constants!-class_method" title="Mint.use_top_level_constants! (method)">use_top_level_constants!</a></span>
533
589
  <small>Mint</small>
@@ -535,10 +591,18 @@
535
591
  </li>
536
592
 
537
593
 
594
+ <li class="odd ">
595
+ <div class="item">
596
+ <span class='object_link'><a href="Mint/Rounding.html#with_mode-class_method" title="Mint::Rounding.with_mode (method)">with_mode</a></span>
597
+ <small>Mint::Rounding</small>
598
+ </div>
599
+ </li>
600
+
601
+
538
602
  <li class="even ">
539
603
  <div class="item">
540
- <span class='object_link'><a href="Mint/Registry.html#world_currencies-class_method" title="Mint::Registry.world_currencies (method)">world_currencies</a></span>
541
- <small>Mint::Registry</small>
604
+ <span class='object_link'><a href="Mint.html#with_rounding-class_method" title="Mint.with_rounding (method)">with_rounding</a></span>
605
+ <small>Mint</small>
542
606
  </div>
543
607
  </li>
544
608
 
@@ -553,21 +617,45 @@
553
617
 
554
618
  <li class="even ">
555
619
  <div class="item">
556
- <span class='object_link'><a href="Mint.html#zero-class_method" title="Mint.zero (method)">zero</a></span>
557
- <small>Mint</small>
620
+ <span class='object_link'><a href="Mint/Registry.html#world_currencies-class_method" title="Mint::Registry.world_currencies (method)">world_currencies</a></span>
621
+ <small>Mint::Registry</small>
558
622
  </div>
559
623
  </li>
560
624
 
561
625
 
562
626
  <li class="odd ">
563
627
  <div class="item">
564
- <span class='object_link'><a href="Mint/Money.html#zero%3F-instance_method" title="Mint::Money#zero? (method)">#zero?</a></span>
628
+ <span class='object_link'><a href="Mint/Money.html#zero-class_method" title="Mint::Money.zero (method)">zero</a></span>
565
629
  <small>Mint::Money</small>
566
630
  </div>
567
631
  </li>
568
632
 
569
633
 
570
634
  <li class="even ">
635
+ <div class="item">
636
+ <span class='object_link'><a href="Mint/Currency.html#zero-class_method" title="Mint::Currency.zero (method)">zero</a></span>
637
+ <small>Mint::Currency</small>
638
+ </div>
639
+ </li>
640
+
641
+
642
+ <li class="odd ">
643
+ <div class="item">
644
+ <span class='object_link'><a href="Mint/Currency.html#zero-instance_method" title="Mint::Currency#zero (method)">#zero</a></span>
645
+ <small>Mint::Currency</small>
646
+ </div>
647
+ </li>
648
+
649
+
650
+ <li class="even ">
651
+ <div class="item">
652
+ <span class='object_link'><a href="Mint/Money.html#zero%3F-instance_method" title="Mint::Money#zero? (method)">#zero?</a></span>
653
+ <small>Mint::Money</small>
654
+ </div>
655
+ </li>
656
+
657
+
658
+ <li class="odd ">
571
659
  <div class="item">
572
660
  <span class='object_link'><a href="Mint/Registry.html#zero_for-class_method" title="Mint::Registry.zero_for (method)">zero_for</a></span>
573
661
  <small>Mint::Registry</small>
@@ -141,7 +141,7 @@
141
141
  </div>
142
142
 
143
143
  <div id="footer">
144
- Generated on Mon Jun 15 19:57:57 2026 by
144
+ Generated on Tue Jun 16 20:22:19 2026 by
145
145
  <a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
146
146
  0.9.44 (ruby-4.0.5).
147
147
  </div>
@@ -40,7 +40,22 @@ module Mint
40
40
  # Normalizes numeric amounts for this currency
41
41
  # 1. Converts to Rational
42
42
  # 2. Rounds to respect currency subunit
43
- def normalize_amount(amount) = amount.to_r.round(subunit)
43
+ def normalize_amount(amount) = Mint::Rounding.apply(amount, subunit)
44
+
45
+ def zero = Registry.zero_for(self)
46
+ end
47
+
48
+ # Registers a new currency, raising a KeyError if already registered.
49
+ #
50
+ # @param code [String] the unique currency code
51
+ # @param subunit [Integer] the decimal subunit precision, defaults to 0
52
+ # @param symbol [String] the display symbol
53
+ # @param priority [Integer] parser precedence priority
54
+ # @return [Currency] the newly registered Currency instance
55
+ # @raise [ArgumentError] if the code contains invalid characters
56
+ # @raise [KeyError] if the currency code is already registered
57
+ def Currency.register(code:, subunit: 0, symbol: '', priority: 0)
58
+ Registry.register(code:, subunit:, symbol:, priority:)
44
59
  end
45
60
 
46
61
  # Resolves an object into a {Currency}, returning +nil+ when it can't.
@@ -57,7 +72,7 @@ module Mint
57
72
  when NilClass then nil
58
73
  when Currency then object
59
74
  when Money then object.currency
60
- when String then Mint.currency_for_code object
75
+ when String then Currency.for_code object
61
76
  else raise ArgumentError, "currency must be [Currency], [Money], [String] or nil (#{object})"
62
77
  end
63
78
  end
@@ -72,4 +87,28 @@ module Mint
72
87
  def Currency.resolve!(object)
73
88
  resolve(object) or raise ArgumentError, "Could not resolve (#{object}) into a currency"
74
89
  end
90
+
91
+ # Looks up a registered currency by its alpha code.
92
+ #
93
+ # @param code [String] the currency code
94
+ # @return [Currency, nil] the registered Currency, or +nil+ if not found
95
+ def Currency.for_code(code)
96
+ Registry.currencies[code]
97
+ end
98
+
99
+ # Looks up a currency by its display symbol.
100
+ #
101
+ # @param symbol [String] the display symbol (e.g. "$", "R$")
102
+ # @return [Currency, nil] the highest-priority currency for the symbol
103
+ def Currency.for_symbol(symbol)
104
+ Registry.currency_for_symbol(symbol)
105
+ end
106
+
107
+ # Returns a zero {Money} in the given currency, useful as a default value
108
+ # for discounts, totals, or placeholders.
109
+ #
110
+ # @param currency [String, Currency] a currency code or object
111
+ # @return [Money] a frozen zero-Money
112
+ # @raise [ArgumentError] if the currency can't be resolved
113
+ def Currency.zero(currency) = Registry.zero_for(Currency.resolve!(currency))
75
114
  end
@@ -62,6 +62,7 @@ module Mint
62
62
  end
63
63
  end
64
64
  end
65
+
65
66
  Range.prepend(Mint::RangeStepPatch)
66
67
  end
67
68
  end
@@ -12,48 +12,21 @@ module Mint
12
12
  # @param currency_code [Currency, String] Currency code
13
13
  # @return [Money] the instantiated Money object
14
14
  # @raise [ArgumentError] if the currency code is not registered
15
- def self.money(amount, currency_code) = Money.create(amount, currency_code)
15
+ def self.money(amount, currency_code) = Money.from(amount, currency_code)
16
16
 
17
17
  # @return [Hash{String => Currency}] the frozen world-currencies hash
18
18
  # @api private
19
19
  def self.world_currencies = Registry.world_currencies
20
20
 
21
- # Looks up a registered currency by its alpha code.
21
+ # Executes a block with a specific rounding mode applied to all money
22
+ # construction, parsing, change, allocation, and split operations.
22
23
  #
23
- # Unlike {.currency}, this performs a direct hash lookup and only accepts strings.
24
+ # Restores the previous mode (or default) when the block exits, even on
25
+ # exception.
24
26
  #
25
- # @param code [String] the currency code
26
- # @return [Currency, nil] the registered Currency, or +nil+ if not found
27
- def self.currency_for_code(code)
28
- Registry.currencies[code]
29
- end
30
-
31
- # Looks up a currency by its display symbol.
32
- #
33
- # @param symbol [String] the display symbol (e.g. "$", "R$")
34
- # @return [Currency, nil] the highest-priority currency for the symbol
35
- def self.currency_for_symbol(symbol)
36
- Registry.currency_for_symbol(symbol)
37
- end
38
-
39
- # Returns a zero {Money} in the given currency, useful as a default value
40
- # for discounts, totals, or placeholders.
41
- #
42
- # @param currency [String, Currency] a currency code or object
43
- # @return [Money] a frozen zero-Money
44
- # @raise [ArgumentError] if the currency can't be resolved
45
- def self.zero(currency) = Registry.zero_for(Currency.resolve!(currency))
46
-
47
- # Registers a new currency, raising a KeyError if already registered.
48
- #
49
- # @param code [String] the unique currency code
50
- # @param subunit [Integer] the decimal subunit precision, defaults to 0
51
- # @param symbol [String] the display symbol
52
- # @param priority [Integer] parser precedence priority
53
- # @return [Currency] the newly registered Currency instance
54
- # @raise [ArgumentError] if the code contains invalid characters
55
- # @raise [KeyError] if the currency code is already registered
56
- def self.register_currency(code:, subunit: 0, symbol: '', priority: 0)
57
- Registry.register(code:, subunit:, symbol:, priority:)
58
- end
27
+ # @param mode [Symbol] one of: +:half_up+, +:half_down+, +:floor+,
28
+ # +:ceil+, +:truncate+, +:down+
29
+ # @yield block to execute with the rounding mode active
30
+ # @raise [ArgumentError] if +mode+ is not a recognised rounding mode
31
+ def self.with_rounding(mode, &) = Rounding.with_mode(mode, &)
59
32
  end
@@ -6,29 +6,58 @@ module Mint
6
6
 
7
7
  # Parses a human-readable money string into a {Money} object.
8
8
  #
9
+ # Returns +nil+ when the input is invalid or currency cannot be determined.
10
+ #
9
11
  # @param input [String] Amount input, optionally including a currency symbol or code
10
12
  # @param currency [String, Symbol, Currency, nil] ISO code when not present in +input+
11
- # @return [Money]
12
- # @raise [ArgumentError] when +input+ is invalid or currency cannot be determined
13
+ # @return [Money, nil]
13
14
  #
14
15
  # @example With explicit currency
15
- # Money.parse('19.99', 'USD') #=> [USD 19.99]
16
- # Money.parse('1.234,56', 'EUR') #=> [EUR 1234.56]
16
+ # Mint.parse('19.99', 'USD') #=> [USD 19.99]
17
+ # Mint.parse('garbage', 'USD') #=> nil
17
18
  #
18
19
  # @example With symbol or code in the string
19
- # Money.parse('$19.99') #=> [USD 19.99]
20
- # Money.parse('19,99 €') #=> [EUR 19.99]
21
- # Money.parse('USD 1,234.56') #=> [USD 1234.56]
20
+ # Mint.parse('$19.99') #=> [USD 19.99]
21
+ # Mint.parse('USD 1,234.56') #=> [USD 1234.56]
22
22
  def parse(input, currency = nil)
23
+ return nil unless input.is_a?(String)
24
+
25
+ input = input.strip
26
+ return nil if input.empty?
27
+
28
+ currency = parse_currency(input, currency)
29
+ return nil unless currency
30
+
31
+ amount = parse_amount(input)
32
+ return nil unless amount
33
+
34
+ amount = currency.normalize_amount(amount)
35
+ Mint::Money.new(amount, currency)
36
+ end
37
+
38
+ # Like {.parse} but raises on failure.
39
+ #
40
+ # @param input [String] Amount input, optionally including a currency symbol or code
41
+ # @param currency [String, Symbol, Currency, nil] ISO code when not present in +input+
42
+ # @return [Money]
43
+ # @raise [ArgumentError] when +input+ is invalid or currency cannot be determined
44
+ #
45
+ # @example
46
+ # Mint.parse!('19.99', 'USD') #=> [USD 19.99]
47
+ # Mint.parse!('garbage', 'USD') #=> ArgumentError
48
+ def parse!(input, currency = nil)
23
49
  raise ArgumentError, 'input must be a String' unless input.is_a?(String)
24
50
 
25
51
  input = input.strip
26
52
  raise ArgumentError, 'input cannot be empty' if input.empty?
27
53
 
28
- currency = Currency.resolve(currency) || parse_currency(input)
29
- raise ArgumentError, "Currency [#{currency}] not registered" unless currency
54
+ currency = parse_currency(input, currency)
55
+ raise ArgumentError, "Currency [#{currency}] not found" unless currency
56
+
57
+ amount = parse_amount(input)
58
+ raise ArgumentError, "Could not parse [#{input}]" unless amount
30
59
 
31
- amount = currency.normalize_amount(parse_amount(input))
60
+ amount = currency.normalize_amount(amount)
32
61
  Mint::Money.new(amount, currency)
33
62
  end
34
63
 
@@ -40,8 +69,11 @@ module Mint
40
69
  accounting_negative = input.start_with?('(') && input.end_with?(')')
41
70
 
42
71
  # Remove any charater that is not a digit, comma or period
43
- numeric = input.scan(/[\d.,-]/).join
44
- amount = Rational(normalize_separators(numeric))
72
+ numeric_input = input.scan(/[\d.,-]/).join
73
+ numeric = parse_separators(numeric_input)
74
+ return nil unless numeric
75
+
76
+ amount = Rational(numeric)
45
77
  accounting_negative ? -amount : amount
46
78
  end
47
79
 
@@ -51,12 +83,15 @@ module Mint
51
83
  # back to symbol matching. This correctly handles inputs like
52
84
  # "MAX 10.00 USD" where the first uppercase word isn't a currency code.
53
85
  # @private
54
- def parse_currency(input)
86
+ def parse_currency(input, currency = nil)
87
+ currency = Currency.resolve(currency)
88
+ return currency if currency
89
+
55
90
  input.scan(/\b([A-Z_]+)\b/) do |(code)|
56
- currency = Mint.currency_for_code(code)
91
+ currency = Currency.for_code(code)
57
92
  return currency if currency
58
93
  end
59
94
 
60
- Registry.detect_currency(input) or raise ArgumentError, 'Currency could not be detected'
95
+ Registry.detect_currency(input)
61
96
  end
62
97
  end