minting 1.7.2 → 1.7.3
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/README.md +16 -1
- data/doc/Mint/Currency.html +285 -31
- data/doc/Mint/Money.html +79 -56
- data/doc/Mint/RangeStepPatch.html +1 -1
- data/doc/Mint/Registry.html +842 -0
- data/doc/Mint/UnknownCurrency.html +1 -1
- data/doc/Mint.html +345 -51
- data/doc/Minting.html +2 -2
- data/doc/_index.html +8 -8
- data/doc/agents/api_review-2026-06-15.md +342 -0
- data/doc/class_list.html +1 -1
- data/doc/file.README.html +13 -2
- data/doc/index.html +13 -2
- data/doc/method_list.html +100 -36
- data/doc/top-level-namespace.html +1 -1
- data/lib/minting/currency/currency.rb +31 -0
- data/lib/minting/mint/locale_backend.rb +29 -0
- data/lib/minting/mint/mint.rb +23 -21
- data/lib/minting/mint/parser/parser.rb +3 -7
- data/lib/minting/mint/registry/registration.rb +33 -0
- data/lib/minting/mint/registry/registry.rb +38 -0
- data/lib/minting/mint/registry/symbols.rb +49 -0
- data/lib/minting/mint/registry/zeros.rb +18 -0
- data/lib/minting/mint.rb +13 -25
- data/lib/minting/money/constructors.rb +6 -11
- data/lib/minting/money/format/formatting.rb +16 -0
- data/lib/minting/money/format/to_s.rb +13 -4
- data/lib/minting/money/money.rb +12 -0
- data/lib/minting/version.rb +1 -1
- metadata +13 -8
- data/lib/minting/currency/currency_registry.rb +0 -67
- data/lib/minting/currency/world_currencies.rb +0 -16
- /data/doc/agents/{AGENTS.md → expired/AGENTS.md} +0 -0
- /data/doc/agents/{copilot-instructions.md → expired/copilot-instructions.md} +0 -0
- /data/doc/agents/{gemini_gem_evaluation.md → expired/gemini_gem_evaluation.md} +0 -0
- /data/doc/agents/{recommendations.md → expired/recommendations.md} +0 -0
- /data/doc/agents/{rubocop-issues.md → expired/rubocop-issues.md} +0 -0
data/doc/method_list.html
CHANGED
|
@@ -177,23 +177,23 @@
|
|
|
177
177
|
|
|
178
178
|
<li class="odd ">
|
|
179
179
|
<div class="item">
|
|
180
|
-
<span class='object_link'><a href="Mint/
|
|
181
|
-
<small>Mint::
|
|
180
|
+
<span class='object_link'><a href="Mint/Registry.html#currencies-class_method" title="Mint::Registry.currencies (method)">currencies</a></span>
|
|
181
|
+
<small>Mint::Registry</small>
|
|
182
182
|
</div>
|
|
183
183
|
</li>
|
|
184
184
|
|
|
185
185
|
|
|
186
186
|
<li class="even ">
|
|
187
187
|
<div class="item">
|
|
188
|
-
<span class='object_link'><a href="Mint.html#currency-
|
|
189
|
-
<small>Mint</small>
|
|
188
|
+
<span class='object_link'><a href="Mint/Money.html#currency-instance_method" title="Mint::Money#currency (method)">#currency</a></span>
|
|
189
|
+
<small>Mint::Money</small>
|
|
190
190
|
</div>
|
|
191
191
|
</li>
|
|
192
192
|
|
|
193
193
|
|
|
194
194
|
<li class="odd ">
|
|
195
195
|
<div class="item">
|
|
196
|
-
<span class='object_link'><a href="Mint/Money.html#
|
|
196
|
+
<span class='object_link'><a href="Mint/Money.html#currency_code-instance_method" title="Mint::Money#currency_code (method)">#currency_code</a></span>
|
|
197
197
|
<small>Mint::Money</small>
|
|
198
198
|
</div>
|
|
199
199
|
</li>
|
|
@@ -201,16 +201,32 @@
|
|
|
201
201
|
|
|
202
202
|
<li class="even ">
|
|
203
203
|
<div class="item">
|
|
204
|
-
<span class='object_link'><a href="Mint
|
|
205
|
-
<small>Mint
|
|
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>
|
|
206
|
+
</div>
|
|
207
|
+
</li>
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
<li class="odd ">
|
|
211
|
+
<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>
|
|
214
|
+
</div>
|
|
215
|
+
</li>
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
<li class="even ">
|
|
219
|
+
<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>
|
|
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/
|
|
213
|
-
<small>Mint::
|
|
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>
|
|
214
230
|
</div>
|
|
215
231
|
</li>
|
|
216
232
|
|
|
@@ -280,6 +296,14 @@
|
|
|
280
296
|
|
|
281
297
|
|
|
282
298
|
<li class="even ">
|
|
299
|
+
<div class="item">
|
|
300
|
+
<span class='object_link'><a href="Mint.html#locale_backend-class_method" title="Mint.locale_backend (method)">locale_backend</a></span>
|
|
301
|
+
<small>Mint</small>
|
|
302
|
+
</div>
|
|
303
|
+
</li>
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
<li class="odd ">
|
|
283
307
|
<div class="item">
|
|
284
308
|
<span class='object_link'><a href="Mint/Currency.html#minimum_amount-instance_method" title="Mint::Currency#minimum_amount (method)">#minimum_amount</a></span>
|
|
285
309
|
<small>Mint::Currency</small>
|
|
@@ -287,7 +311,7 @@
|
|
|
287
311
|
</li>
|
|
288
312
|
|
|
289
313
|
|
|
290
|
-
<li class="
|
|
314
|
+
<li class="even ">
|
|
291
315
|
<div class="item">
|
|
292
316
|
<span class='object_link'><a href="Mint/Money.html#mint-instance_method" title="Mint::Money#mint (method)">#mint</a></span>
|
|
293
317
|
<small>Mint::Money</small>
|
|
@@ -295,7 +319,7 @@
|
|
|
295
319
|
</li>
|
|
296
320
|
|
|
297
321
|
|
|
298
|
-
<li class="
|
|
322
|
+
<li class="odd ">
|
|
299
323
|
<div class="item">
|
|
300
324
|
<span class='object_link'><a href="Mint.html#money-class_method" title="Mint.money (method)">money</a></span>
|
|
301
325
|
<small>Mint</small>
|
|
@@ -303,7 +327,7 @@
|
|
|
303
327
|
</li>
|
|
304
328
|
|
|
305
329
|
|
|
306
|
-
<li class="
|
|
330
|
+
<li class="even ">
|
|
307
331
|
<div class="item">
|
|
308
332
|
<span class='object_link'><a href="Mint/Currency.html#name-instance_method" title="Mint::Currency#name (method)">#name</a></span>
|
|
309
333
|
<small>Mint::Currency</small>
|
|
@@ -311,7 +335,7 @@
|
|
|
311
335
|
</li>
|
|
312
336
|
|
|
313
337
|
|
|
314
|
-
<li class="
|
|
338
|
+
<li class="odd ">
|
|
315
339
|
<div class="item">
|
|
316
340
|
<span class='object_link'><a href="Mint/Money.html#negative%3F-instance_method" title="Mint::Money#negative? (method)">#negative?</a></span>
|
|
317
341
|
<small>Mint::Money</small>
|
|
@@ -319,7 +343,7 @@
|
|
|
319
343
|
</li>
|
|
320
344
|
|
|
321
345
|
|
|
322
|
-
<li class="
|
|
346
|
+
<li class="even ">
|
|
323
347
|
<div class="item">
|
|
324
348
|
<span class='object_link'><a href="Mint/Money.html#nonzero%3F-instance_method" title="Mint::Money#nonzero? (method)">#nonzero?</a></span>
|
|
325
349
|
<small>Mint::Money</small>
|
|
@@ -327,7 +351,7 @@
|
|
|
327
351
|
</li>
|
|
328
352
|
|
|
329
353
|
|
|
330
|
-
<li class="
|
|
354
|
+
<li class="odd ">
|
|
331
355
|
<div class="item">
|
|
332
356
|
<span class='object_link'><a href="Mint/Currency.html#normalize_amount-instance_method" title="Mint::Currency#normalize_amount (method)">#normalize_amount</a></span>
|
|
333
357
|
<small>Mint::Currency</small>
|
|
@@ -335,7 +359,7 @@
|
|
|
335
359
|
</li>
|
|
336
360
|
|
|
337
361
|
|
|
338
|
-
<li class="
|
|
362
|
+
<li class="even ">
|
|
339
363
|
<div class="item">
|
|
340
364
|
<span class='object_link'><a href="Mint.html#parse-instance_method" title="Mint#parse (method)">#parse</a></span>
|
|
341
365
|
<small>Mint</small>
|
|
@@ -343,7 +367,7 @@
|
|
|
343
367
|
</li>
|
|
344
368
|
|
|
345
369
|
|
|
346
|
-
<li class="
|
|
370
|
+
<li class="odd ">
|
|
347
371
|
<div class="item">
|
|
348
372
|
<span class='object_link'><a href="Mint/Money.html#positive%3F-instance_method" title="Mint::Money#positive? (method)">#positive?</a></span>
|
|
349
373
|
<small>Mint::Money</small>
|
|
@@ -351,7 +375,7 @@
|
|
|
351
375
|
</li>
|
|
352
376
|
|
|
353
377
|
|
|
354
|
-
<li class="
|
|
378
|
+
<li class="even ">
|
|
355
379
|
<div class="item">
|
|
356
380
|
<span class='object_link'><a href="Mint/Currency.html#priority-instance_method" title="Mint::Currency#priority (method)">#priority</a></span>
|
|
357
381
|
<small>Mint::Currency</small>
|
|
@@ -359,15 +383,15 @@
|
|
|
359
383
|
</li>
|
|
360
384
|
|
|
361
385
|
|
|
362
|
-
<li class="
|
|
386
|
+
<li class="odd ">
|
|
363
387
|
<div class="item">
|
|
364
|
-
<span class='object_link'><a href="Mint/
|
|
365
|
-
<small>Mint::
|
|
388
|
+
<span class='object_link'><a href="Mint/Registry.html#register-class_method" title="Mint::Registry.register (method)">register</a></span>
|
|
389
|
+
<small>Mint::Registry</small>
|
|
366
390
|
</div>
|
|
367
391
|
</li>
|
|
368
392
|
|
|
369
393
|
|
|
370
|
-
<li class="
|
|
394
|
+
<li class="even ">
|
|
371
395
|
<div class="item">
|
|
372
396
|
<span class='object_link'><a href="Mint.html#register_currency-class_method" title="Mint.register_currency (method)">register_currency</a></span>
|
|
373
397
|
<small>Mint</small>
|
|
@@ -375,7 +399,23 @@
|
|
|
375
399
|
</li>
|
|
376
400
|
|
|
377
401
|
|
|
402
|
+
<li class="odd ">
|
|
403
|
+
<div class="item">
|
|
404
|
+
<span class='object_link'><a href="Mint/Currency.html#resolve-class_method" title="Mint::Currency.resolve (method)">resolve</a></span>
|
|
405
|
+
<small>Mint::Currency</small>
|
|
406
|
+
</div>
|
|
407
|
+
</li>
|
|
408
|
+
|
|
409
|
+
|
|
378
410
|
<li class="even ">
|
|
411
|
+
<div class="item">
|
|
412
|
+
<span class='object_link'><a href="Mint/Currency.html#resolve!-class_method" title="Mint::Currency.resolve! (method)">resolve!</a></span>
|
|
413
|
+
<small>Mint::Currency</small>
|
|
414
|
+
</div>
|
|
415
|
+
</li>
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
<li class="odd ">
|
|
379
419
|
<div class="item">
|
|
380
420
|
<span class='object_link'><a href="Mint/Money.html#same_currency%3F-instance_method" title="Mint::Money#same_currency? (method)">#same_currency?</a></span>
|
|
381
421
|
<small>Mint::Money</small>
|
|
@@ -383,7 +423,7 @@
|
|
|
383
423
|
</li>
|
|
384
424
|
|
|
385
425
|
|
|
386
|
-
<li class="
|
|
426
|
+
<li class="even ">
|
|
387
427
|
<div class="item">
|
|
388
428
|
<span class='object_link'><a href="Mint/Money.html#split-instance_method" title="Mint::Money#split (method)">#split</a></span>
|
|
389
429
|
<small>Mint::Money</small>
|
|
@@ -391,7 +431,7 @@
|
|
|
391
431
|
</li>
|
|
392
432
|
|
|
393
433
|
|
|
394
|
-
<li class="
|
|
434
|
+
<li class="odd ">
|
|
395
435
|
<div class="item">
|
|
396
436
|
<span class='object_link'><a href="Mint/RangeStepPatch.html#step-instance_method" title="Mint::RangeStepPatch#step (method)">#step</a></span>
|
|
397
437
|
<small>Mint::RangeStepPatch</small>
|
|
@@ -399,7 +439,7 @@
|
|
|
399
439
|
</li>
|
|
400
440
|
|
|
401
441
|
|
|
402
|
-
<li class="
|
|
442
|
+
<li class="even ">
|
|
403
443
|
<div class="item">
|
|
404
444
|
<span class='object_link'><a href="Mint/Currency.html#subunit-instance_method" title="Mint::Currency#subunit (method)">#subunit</a></span>
|
|
405
445
|
<small>Mint::Currency</small>
|
|
@@ -407,7 +447,7 @@
|
|
|
407
447
|
</li>
|
|
408
448
|
|
|
409
449
|
|
|
410
|
-
<li class="
|
|
450
|
+
<li class="odd ">
|
|
411
451
|
<div class="item">
|
|
412
452
|
<span class='object_link'><a href="Mint/Money.html#succ-instance_method" title="Mint::Money#succ (method)">#succ</a></span>
|
|
413
453
|
<small>Mint::Money</small>
|
|
@@ -415,7 +455,7 @@
|
|
|
415
455
|
</li>
|
|
416
456
|
|
|
417
457
|
|
|
418
|
-
<li class="
|
|
458
|
+
<li class="even ">
|
|
419
459
|
<div class="item">
|
|
420
460
|
<span class='object_link'><a href="Mint/Currency.html#symbol-instance_method" title="Mint::Currency#symbol (method)">#symbol</a></span>
|
|
421
461
|
<small>Mint::Currency</small>
|
|
@@ -423,7 +463,7 @@
|
|
|
423
463
|
</li>
|
|
424
464
|
|
|
425
465
|
|
|
426
|
-
<li class="
|
|
466
|
+
<li class="odd ">
|
|
427
467
|
<div class="item">
|
|
428
468
|
<span class='object_link'><a href="Mint/Money.html#to_d-instance_method" title="Mint::Money#to_d (method)">#to_d</a></span>
|
|
429
469
|
<small>Mint::Money</small>
|
|
@@ -431,7 +471,7 @@
|
|
|
431
471
|
</li>
|
|
432
472
|
|
|
433
473
|
|
|
434
|
-
<li class="
|
|
474
|
+
<li class="even ">
|
|
435
475
|
<div class="item">
|
|
436
476
|
<span class='object_link'><a href="Mint/Money.html#to_f-instance_method" title="Mint::Money#to_f (method)">#to_f</a></span>
|
|
437
477
|
<small>Mint::Money</small>
|
|
@@ -439,7 +479,7 @@
|
|
|
439
479
|
</li>
|
|
440
480
|
|
|
441
481
|
|
|
442
|
-
<li class="
|
|
482
|
+
<li class="odd ">
|
|
443
483
|
<div class="item">
|
|
444
484
|
<span class='object_link'><a href="Mint/Money.html#to_hash-instance_method" title="Mint::Money#to_hash (method)">#to_hash</a></span>
|
|
445
485
|
<small>Mint::Money</small>
|
|
@@ -447,7 +487,7 @@
|
|
|
447
487
|
</li>
|
|
448
488
|
|
|
449
489
|
|
|
450
|
-
<li class="
|
|
490
|
+
<li class="even ">
|
|
451
491
|
<div class="item">
|
|
452
492
|
<span class='object_link'><a href="Mint/Money.html#to_html-instance_method" title="Mint::Money#to_html (method)">#to_html</a></span>
|
|
453
493
|
<small>Mint::Money</small>
|
|
@@ -455,7 +495,7 @@
|
|
|
455
495
|
</li>
|
|
456
496
|
|
|
457
497
|
|
|
458
|
-
<li class="
|
|
498
|
+
<li class="odd ">
|
|
459
499
|
<div class="item">
|
|
460
500
|
<span class='object_link'><a href="Mint/Money.html#to_i-instance_method" title="Mint::Money#to_i (method)">#to_i</a></span>
|
|
461
501
|
<small>Mint::Money</small>
|
|
@@ -463,7 +503,7 @@
|
|
|
463
503
|
</li>
|
|
464
504
|
|
|
465
505
|
|
|
466
|
-
<li class="
|
|
506
|
+
<li class="even ">
|
|
467
507
|
<div class="item">
|
|
468
508
|
<span class='object_link'><a href="Mint/Money.html#to_json-instance_method" title="Mint::Money#to_json (method)">#to_json</a></span>
|
|
469
509
|
<small>Mint::Money</small>
|
|
@@ -471,7 +511,7 @@
|
|
|
471
511
|
</li>
|
|
472
512
|
|
|
473
513
|
|
|
474
|
-
<li class="
|
|
514
|
+
<li class="odd ">
|
|
475
515
|
<div class="item">
|
|
476
516
|
<span class='object_link'><a href="Mint/Money.html#to_r-instance_method" title="Mint::Money#to_r (method)">#to_r</a></span>
|
|
477
517
|
<small>Mint::Money</small>
|
|
@@ -479,7 +519,7 @@
|
|
|
479
519
|
</li>
|
|
480
520
|
|
|
481
521
|
|
|
482
|
-
<li class="
|
|
522
|
+
<li class="even ">
|
|
483
523
|
<div class="item">
|
|
484
524
|
<span class='object_link'><a href="Mint/Money.html#to_s-instance_method" title="Mint::Money#to_s (method)">#to_s</a></span>
|
|
485
525
|
<small>Mint::Money</small>
|
|
@@ -487,7 +527,7 @@
|
|
|
487
527
|
</li>
|
|
488
528
|
|
|
489
529
|
|
|
490
|
-
<li class="
|
|
530
|
+
<li class="odd ">
|
|
491
531
|
<div class="item">
|
|
492
532
|
<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>
|
|
493
533
|
<small>Mint</small>
|
|
@@ -495,6 +535,14 @@
|
|
|
495
535
|
</li>
|
|
496
536
|
|
|
497
537
|
|
|
538
|
+
<li class="even ">
|
|
539
|
+
<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>
|
|
542
|
+
</div>
|
|
543
|
+
</li>
|
|
544
|
+
|
|
545
|
+
|
|
498
546
|
<li class="odd ">
|
|
499
547
|
<div class="item">
|
|
500
548
|
<span class='object_link'><a href="Mint.html#world_currencies-class_method" title="Mint.world_currencies (method)">world_currencies</a></span>
|
|
@@ -504,6 +552,14 @@
|
|
|
504
552
|
|
|
505
553
|
|
|
506
554
|
<li class="even ">
|
|
555
|
+
<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>
|
|
558
|
+
</div>
|
|
559
|
+
</li>
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
<li class="odd ">
|
|
507
563
|
<div class="item">
|
|
508
564
|
<span class='object_link'><a href="Mint/Money.html#zero%3F-instance_method" title="Mint::Money#zero? (method)">#zero?</a></span>
|
|
509
565
|
<small>Mint::Money</small>
|
|
@@ -511,6 +567,14 @@
|
|
|
511
567
|
</li>
|
|
512
568
|
|
|
513
569
|
|
|
570
|
+
<li class="even ">
|
|
571
|
+
<div class="item">
|
|
572
|
+
<span class='object_link'><a href="Mint/Registry.html#zero_for-class_method" title="Mint::Registry.zero_for (method)">zero_for</a></span>
|
|
573
|
+
<small>Mint::Registry</small>
|
|
574
|
+
</div>
|
|
575
|
+
</li>
|
|
576
|
+
|
|
577
|
+
|
|
514
578
|
|
|
515
579
|
</ul>
|
|
516
580
|
</div>
|
|
@@ -141,7 +141,7 @@
|
|
|
141
141
|
</div>
|
|
142
142
|
|
|
143
143
|
<div id="footer">
|
|
144
|
-
Generated on
|
|
144
|
+
Generated on Mon Jun 15 19:57:57 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>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
# :nodoc:
|
|
3
4
|
module Mint
|
|
4
5
|
# Represents a specific currency unit, identified by ISO 4217 alphabetic code.
|
|
5
6
|
# Currency objects are immutable and define the properties of a monetary unit
|
|
@@ -41,4 +42,34 @@ module Mint
|
|
|
41
42
|
# 2. Rounds to respect currency subunit
|
|
42
43
|
def normalize_amount(amount) = amount.to_r.round(subunit)
|
|
43
44
|
end
|
|
45
|
+
|
|
46
|
+
# Resolves an object into a {Currency}, returning +nil+ when it can't.
|
|
47
|
+
#
|
|
48
|
+
# Accepts +nil+, +String+, {Currency}, or {Money}.
|
|
49
|
+
# Passing a {Money} extracts its currency
|
|
50
|
+
#
|
|
51
|
+
# @param object [String, Currency, Money, nil] a currency code, object, or +nil+
|
|
52
|
+
# @return [Currency, nil] the resolved Currency, or +nil+ if +object+ is +nil+
|
|
53
|
+
# or the code is not registered
|
|
54
|
+
# @raise [ArgumentError] if +object+ is an unsupported type (e.g. +Integer+)
|
|
55
|
+
def Currency.resolve(object)
|
|
56
|
+
case object
|
|
57
|
+
when NilClass then nil
|
|
58
|
+
when Currency then object
|
|
59
|
+
when Money then object.currency
|
|
60
|
+
when String then Mint.currency_for_code object
|
|
61
|
+
else raise ArgumentError, "currency must be [Currency], [Money], [String] or nil (#{object})"
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Resolves an object into a {Currency}, raising on failure.
|
|
66
|
+
#
|
|
67
|
+
# Like {.resolve} but raises when the result would be +nil+.
|
|
68
|
+
#
|
|
69
|
+
# @param object [String, Currency, Money, nil] a currency code, object, or +nil+
|
|
70
|
+
# @return [Currency] the resolved Currency
|
|
71
|
+
# @raise [ArgumentError] if +object+ cannot be resolved into a registered currency
|
|
72
|
+
def Currency.resolve!(object)
|
|
73
|
+
resolve(object) or raise ArgumentError, "Could not resolve (#{object}) into a currency"
|
|
74
|
+
end
|
|
44
75
|
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# :nodoc:
|
|
4
|
+
module Mint
|
|
5
|
+
class << self
|
|
6
|
+
# Optional callable that returns a Hash with locale-aware formatting defaults.
|
|
7
|
+
#
|
|
8
|
+
# The callable receives no arguments and returns a Hash with these keys:
|
|
9
|
+
# [+:decimal+] Decimal separator (e.g. +","+)
|
|
10
|
+
# [+:thousand+] Thousands delimiter (e.g. +"."+)
|
|
11
|
+
# [+:format+] Format template string (e.g. +"%<amount>f %<symbol>s"+)
|
|
12
|
+
#
|
|
13
|
+
# When set, +#to_s+ and +#format+ use these values as fallbacks when the
|
|
14
|
+
# corresponding parameter is not explicitly provided.
|
|
15
|
+
#
|
|
16
|
+
# @example Rails I18n integration (in minting-rails railtie)
|
|
17
|
+
# Mint.locale_backend = -> {
|
|
18
|
+
# fmt = I18n.t('number.currency.format')
|
|
19
|
+
# {
|
|
20
|
+
# decimal: fmt[:separator],
|
|
21
|
+
# thousand: fmt[:delimiter],
|
|
22
|
+
# format: fmt[:format] == '%n %u' ? '%<amount>f %<symbol>s' : '%<symbol>s%<amount>f'
|
|
23
|
+
# }
|
|
24
|
+
# }
|
|
25
|
+
#
|
|
26
|
+
# @return [Proc, #call, nil]
|
|
27
|
+
attr_accessor :locale_backend
|
|
28
|
+
end
|
|
29
|
+
end
|
data/lib/minting/mint/mint.rb
CHANGED
|
@@ -14,18 +14,26 @@ module Mint
|
|
|
14
14
|
# @raise [ArgumentError] if the currency code is not registered
|
|
15
15
|
def self.money(amount, currency_code) = Money.create(amount, currency_code)
|
|
16
16
|
|
|
17
|
-
#
|
|
18
|
-
#
|
|
17
|
+
# @return [Hash{String => Currency}] the frozen world-currencies hash
|
|
18
|
+
# @api private
|
|
19
|
+
def self.world_currencies = Registry.world_currencies
|
|
20
|
+
|
|
21
|
+
# Looks up a registered currency by its alpha code.
|
|
22
|
+
#
|
|
23
|
+
# Unlike {.currency}, this performs a direct hash lookup and only accepts strings.
|
|
19
24
|
#
|
|
20
|
-
# @param
|
|
21
|
-
# @return [Currency, nil] the registered Currency
|
|
22
|
-
def self.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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)
|
|
29
37
|
end
|
|
30
38
|
|
|
31
39
|
# Returns a zero {Money} in the given currency, useful as a default value
|
|
@@ -33,16 +41,10 @@ module Mint
|
|
|
33
41
|
#
|
|
34
42
|
# @param currency [String, Currency] a currency code or object
|
|
35
43
|
# @return [Money] a frozen zero-Money
|
|
36
|
-
# @raise [ArgumentError] if the currency
|
|
37
|
-
def self.zero(currency)
|
|
38
|
-
checked = Mint.currency(currency)
|
|
39
|
-
raise ArgumentError, "Invalid Currency: [#{currency}]" unless checked
|
|
40
|
-
|
|
41
|
-
@zeros ||= CurrencyRegistry.currencies.values.to_h { |currency| [currency, Mint::Money.send(:new, 0, currency)] }
|
|
42
|
-
@zeros[currency] ||= Money.send(:new, 0, currency)
|
|
43
|
-
@zeros[currency]
|
|
44
|
-
end
|
|
44
|
+
# @raise [ArgumentError] if the currency can't be resolved
|
|
45
|
+
def self.zero(currency) = Registry.zero_for(Currency.resolve!(currency))
|
|
45
46
|
|
|
47
|
+
# Registers a new currency, raising a KeyError if already registered.
|
|
46
48
|
#
|
|
47
49
|
# @param code [String] the unique currency code
|
|
48
50
|
# @param subunit [Integer] the decimal subunit precision, defaults to 0
|
|
@@ -52,6 +54,6 @@ module Mint
|
|
|
52
54
|
# @raise [ArgumentError] if the code contains invalid characters
|
|
53
55
|
# @raise [KeyError] if the currency code is already registered
|
|
54
56
|
def self.register_currency(code:, subunit: 0, symbol: '', priority: 0)
|
|
55
|
-
|
|
57
|
+
Registry.register(code:, subunit:, symbol:, priority:)
|
|
56
58
|
end
|
|
57
59
|
end
|
|
@@ -25,7 +25,7 @@ module Mint
|
|
|
25
25
|
input = input.strip
|
|
26
26
|
raise ArgumentError, 'input cannot be empty' if input.empty?
|
|
27
27
|
|
|
28
|
-
currency =
|
|
28
|
+
currency = Currency.resolve(currency) || parse_currency(input)
|
|
29
29
|
raise ArgumentError, "Currency [#{currency}] not registered" unless currency
|
|
30
30
|
|
|
31
31
|
amount = currency.normalize_amount(parse_amount(input))
|
|
@@ -53,14 +53,10 @@ module Mint
|
|
|
53
53
|
# @private
|
|
54
54
|
def parse_currency(input)
|
|
55
55
|
input.scan(/\b([A-Z_]+)\b/) do |(code)|
|
|
56
|
-
currency = Mint.
|
|
56
|
+
currency = Mint.currency_for_code(code)
|
|
57
57
|
return currency if currency
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
return currency if input.include?(symbol)
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
raise ArgumentError, 'Currency could not be detected'
|
|
60
|
+
Registry.detect_currency(input) or raise ArgumentError, 'Currency could not be detected'
|
|
65
61
|
end
|
|
66
62
|
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Mint
|
|
4
|
+
# :nodoc:
|
|
5
|
+
module Registry
|
|
6
|
+
# Registers a new currency, raising a KeyError if already registered.
|
|
7
|
+
#
|
|
8
|
+
# @param code [String] the unique currency code
|
|
9
|
+
# @param subunit [Integer] the decimal subunit precision, defaults to 0
|
|
10
|
+
# @param symbol [String] the display symbol
|
|
11
|
+
# @param priority [Integer] parser precedence priority
|
|
12
|
+
# @return [Currency] the newly registered Currency instance
|
|
13
|
+
# @raise [ArgumentError] if the code contains invalid characters
|
|
14
|
+
# @raise [KeyError] if the currency code is already registered
|
|
15
|
+
def self.register(code:, subunit: 0, symbol: '', priority: 0)
|
|
16
|
+
raise ArgumentError, 'Currency code must be String' unless code.is_a? String
|
|
17
|
+
unless code.match?(/^[A-Z_]+$/)
|
|
18
|
+
raise ArgumentError,
|
|
19
|
+
"Currency code must have only letters or '_' ('USD',, 'MY_COIN')"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
MUTEX.synchronize do
|
|
23
|
+
raise KeyError, "Currency: #{code} already registered" if currencies[code]
|
|
24
|
+
|
|
25
|
+
currency = Currency.new(code:, subunit:, symbol:, priority:)
|
|
26
|
+
@currencies = @currencies.merge(code => currency).freeze
|
|
27
|
+
@currency_symbols = nil
|
|
28
|
+
@currency_symbol_map = nil
|
|
29
|
+
currency
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'yaml'
|
|
4
|
+
require_relative 'symbols'
|
|
5
|
+
require_relative 'registration'
|
|
6
|
+
require_relative 'zeros'
|
|
7
|
+
|
|
8
|
+
# Mint registry: manages all cached state
|
|
9
|
+
module Mint
|
|
10
|
+
# Internal registry for currencies, symbols, and zero-money cache.
|
|
11
|
+
# All mutable shared state lives here.
|
|
12
|
+
module Registry
|
|
13
|
+
MUTEX = Monitor.new
|
|
14
|
+
|
|
15
|
+
private_constant :MUTEX
|
|
16
|
+
|
|
17
|
+
# Loads ISO world currencies from YAML file.
|
|
18
|
+
#
|
|
19
|
+
# @return [Hash{String => Currency}] ISO-4217 world currencies mapped by code
|
|
20
|
+
# @api private
|
|
21
|
+
def self.world_currencies
|
|
22
|
+
@world_currencies || MUTEX.synchronize do
|
|
23
|
+
@world_currencies = begin
|
|
24
|
+
path = File.join(File.expand_path('../../data', __dir__), 'world-currencies.yaml')
|
|
25
|
+
YAML.load_file(path).to_h { |entry| [entry['code'], Currency.new(**entry.transform_keys(&:to_sym))] }
|
|
26
|
+
end.freeze
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Returns the frozen hash of all registered currencies (world + custom).
|
|
31
|
+
#
|
|
32
|
+
# @return [Hash{String => Currency}] registered currencies mapped by code
|
|
33
|
+
# @api private
|
|
34
|
+
def self.currencies
|
|
35
|
+
@currencies || MUTEX.synchronize { @currencies = world_currencies.dup.freeze }
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Mint
|
|
4
|
+
# :nodoc:
|
|
5
|
+
module Registry
|
|
6
|
+
extend self
|
|
7
|
+
|
|
8
|
+
# Looks up a currency by its display symbol.
|
|
9
|
+
#
|
|
10
|
+
# @param symbol [String] the display symbol (e.g. "$", "R$")
|
|
11
|
+
# @return [Currency, nil] the highest-priority currency for the symbol
|
|
12
|
+
# @api private
|
|
13
|
+
def currency_for_symbol(symbol)
|
|
14
|
+
@currency_symbol_map || MUTEX.synchronize { @currency_symbol_map = currency_symbols.to_h.freeze }
|
|
15
|
+
@currency_symbol_map[symbol]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Scans +input+ for registered currency symbols and returns the first match.
|
|
19
|
+
#
|
|
20
|
+
# @param input [String] the string to scan
|
|
21
|
+
# @return [Currency, nil]
|
|
22
|
+
# @api private
|
|
23
|
+
def detect_currency(input)
|
|
24
|
+
currency_symbols.each do |symbol, currency|
|
|
25
|
+
return currency if input.include?(symbol)
|
|
26
|
+
end
|
|
27
|
+
nil
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
# Registered symbols sorted for detection: longest match wins, then parser priority.
|
|
33
|
+
# Duplicate symbols are deduplicated — the highest-priority currency wins.
|
|
34
|
+
#
|
|
35
|
+
# @return [Array<Array<String, Currency>>] sorted symbol-to-currency mappings
|
|
36
|
+
# @api private
|
|
37
|
+
def currency_symbols
|
|
38
|
+
@currency_symbols || MUTEX.synchronize do
|
|
39
|
+
@currency_symbols =
|
|
40
|
+
currencies.values
|
|
41
|
+
.reject { |currency| currency.symbol.empty? }
|
|
42
|
+
.map { |currency| [currency.symbol, currency] }
|
|
43
|
+
.sort_by { |symbol, currency| [-symbol.length, -currency.priority] }
|
|
44
|
+
.uniq { |symbol, _| symbol }
|
|
45
|
+
.freeze
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|