minting 1.7.2 → 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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +35 -3
  3. data/doc/Mint/Currency.html +826 -55
  4. data/doc/Mint/Money.html +715 -218
  5. data/doc/Mint/RangeStepPatch.html +1 -1
  6. data/doc/Mint/Registry.html +859 -0
  7. data/doc/Mint/Rounding.html +495 -0
  8. data/doc/Mint/UnknownCurrency.html +1 -1
  9. data/doc/Mint.html +307 -225
  10. data/doc/Minting.html +2 -2
  11. data/doc/_index.html +15 -8
  12. data/doc/agents/api_review-2026-06-15.md +329 -0
  13. data/doc/agents/copilot-instructions.md +0 -5
  14. data/doc/agents/expired/copilot-instructions.md +75 -0
  15. data/doc/class_list.html +1 -1
  16. data/doc/file.README.html +25 -4
  17. data/doc/index.html +25 -4
  18. data/doc/method_list.html +177 -25
  19. data/doc/top-level-namespace.html +1 -1
  20. data/lib/minting/currency/currency.rb +71 -1
  21. data/lib/minting/mint/dsl/range.rb +1 -0
  22. data/lib/minting/mint/locale_backend.rb +29 -0
  23. data/lib/minting/mint/mint.rb +13 -38
  24. data/lib/minting/mint/parser/parser.rb +50 -19
  25. data/lib/minting/mint/parser/separators.rb +10 -8
  26. data/lib/minting/mint/registry/registration.rb +33 -0
  27. data/lib/minting/mint/registry/registry.rb +38 -0
  28. data/lib/minting/mint/registry/symbols.rb +49 -0
  29. data/lib/minting/mint/registry/zeros.rb +20 -0
  30. data/lib/minting/mint/rounding.rb +51 -0
  31. data/lib/minting/mint.rb +12 -23
  32. data/lib/minting/money/allocation/allocation.rb +1 -2
  33. data/lib/minting/money/allocation/split.rb +1 -1
  34. data/lib/minting/money/arithmetics/methods.rb +2 -2
  35. data/lib/minting/money/arithmetics/operators.rb +6 -6
  36. data/lib/minting/money/clamp.rb +1 -1
  37. data/lib/minting/money/coercion.rb +1 -1
  38. data/lib/minting/money/comparable.rb +6 -0
  39. data/lib/minting/money/constructors.rb +63 -20
  40. data/lib/minting/money/format/formatting.rb +16 -0
  41. data/lib/minting/money/format/to_s.rb +13 -4
  42. data/lib/minting/money/money.rb +12 -6
  43. data/lib/minting/version.rb +1 -1
  44. metadata +15 -7
  45. data/lib/minting/currency/currency_registry.rb +0 -67
  46. data/lib/minting/currency/world_currencies.rb +0 -16
  47. /data/doc/agents/{AGENTS.md → expired/AGENTS.md} +0 -0
  48. /data/doc/agents/{gemini_gem_evaluation.md → expired/gemini_gem_evaluation.md} +0 -0
  49. /data/doc/agents/{recommendations.md → expired/recommendations.md} +0 -0
  50. /data/doc/agents/{rubocop-issues.md → expired/rubocop-issues.md} +0 -0
data/doc/index.html CHANGED
@@ -234,12 +234,29 @@
234
234
  <li>Ambiguous symbols like <code>$</code> resolve by currency priority (currently USD).</li>
235
235
  <li>The parser scans all uppercase words for registered codes, so spurious non-currency words before the real code are correctly ignored: <code>Mint.parse(&quot;MAX 10.00 USD&quot;)</code> yields <code>[USD 10.00]</code>.</li>
236
236
  </ul>
237
+ <h2 id="Currency_lookup">Currency lookup</h2>
238
+ <pre class="code ruby"><code class="ruby"><span class='comment'># By ISO code (direct hash lookup, string only)
239
+ </span><span class='const'><span class='object_link'><a href="Mint.html" title="Mint (module)">Mint</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="Mint/Currency.html" title="Mint::Currency (class)">Currency</a></span></span><span class='period'>.</span><span class='id identifier rubyid_for_code'><span class='object_link'><a href="Mint/Currency.html#for_code-class_method" title="Mint::Currency.for_code (method)">for_code</a></span></span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>USD</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span> <span class='comment'>#=&gt; #&lt;Currency code=&quot;USD&quot; ...&gt;
240
+ </span>
241
+ <span class='comment'># By display symbol (highest-priority currency for ambiguous symbols)
242
+ </span><span class='const'><span class='object_link'><a href="Mint.html" title="Mint (module)">Mint</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="Mint/Currency.html" title="Mint::Currency (class)">Currency</a></span></span><span class='period'>.</span><span class='id identifier rubyid_for_symbol'><span class='object_link'><a href="Mint/Currency.html#for_symbol-class_method" title="Mint::Currency.for_symbol (method)">for_symbol</a></span></span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>$</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span> <span class='comment'>#=&gt; #&lt;Currency code=&quot;USD&quot; ...&gt;
243
+ </span><span class='const'><span class='object_link'><a href="Mint.html" title="Mint (module)">Mint</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="Mint/Currency.html" title="Mint::Currency (class)">Currency</a></span></span><span class='period'>.</span><span class='id identifier rubyid_for_symbol'><span class='object_link'><a href="Mint/Currency.html#for_symbol-class_method" title="Mint::Currency.for_symbol (method)">for_symbol</a></span></span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>R$</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span> <span class='comment'>#=&gt; #&lt;Currency code=&quot;BRL&quot; ...&gt;
244
+ </span><span class='const'><span class='object_link'><a href="Mint.html" title="Mint (module)">Mint</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="Mint/Currency.html" title="Mint::Currency (class)">Currency</a></span></span><span class='period'>.</span><span class='id identifier rubyid_for_symbol'><span class='object_link'><a href="Mint/Currency.html#for_symbol-class_method" title="Mint::Currency.for_symbol (method)">for_symbol</a></span></span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>€</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span> <span class='comment'>#=&gt; #&lt;Currency code=&quot;EUR&quot; ...&gt;
245
+ </span>
246
+ </code></pre>
237
247
  <h2 id="API_notes">API notes</h2>
238
248
  <p><strong>Exact amounts</strong> — Amounts are stored as <code>Rational</code> and rounded to the currency subunit.</p>
249
+ <p><strong>Rounding modes</strong> — Wrap operations in <code>Mint.with_rounding(mode)</code> to change how amounts are rounded to the subunit:</p>
250
+ <pre class="code ruby"><code class="ruby"><span class='const'><span class='object_link'><a href="Mint.html" title="Mint (module)">Mint</a></span></span><span class='period'>.</span><span class='id identifier rubyid_with_rounding'><span class='object_link'><a href="Mint.html#with_rounding-class_method" title="Mint.with_rounding (method)">with_rounding</a></span></span><span class='lparen'>(</span><span class='symbol'>:half_down</span><span class='rparen'>)</span> <span class='lbrace'>{</span> <span class='const'><span class='object_link'><a href="Mint.html" title="Mint (module)">Mint</a></span></span><span class='period'>.</span><span class='id identifier rubyid_money'><span class='object_link'><a href="Mint.html#money-class_method" title="Mint.money (method)">money</a></span></span><span class='lparen'>(</span><span class='float'>1.005</span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>USD</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span> <span class='rbrace'>}</span> <span class='comment'>#=&gt; [USD 1.00]
251
+ </span><span class='const'><span class='object_link'><a href="Mint.html" title="Mint (module)">Mint</a></span></span><span class='period'>.</span><span class='id identifier rubyid_with_rounding'><span class='object_link'><a href="Mint.html#with_rounding-class_method" title="Mint.with_rounding (method)">with_rounding</a></span></span><span class='lparen'>(</span><span class='symbol'>:ceil</span><span class='rparen'>)</span> <span class='lbrace'>{</span> <span class='const'><span class='object_link'><a href="Mint.html" title="Mint (module)">Mint</a></span></span><span class='period'>.</span><span class='id identifier rubyid_money'><span class='object_link'><a href="Mint.html#money-class_method" title="Mint.money (method)">money</a></span></span><span class='lparen'>(</span><span class='float'>1.001</span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>USD</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span> <span class='rbrace'>}</span> <span class='comment'>#=&gt; [USD 1.01]
252
+ </span><span class='const'><span class='object_link'><a href="Mint.html" title="Mint (module)">Mint</a></span></span><span class='period'>.</span><span class='id identifier rubyid_with_rounding'><span class='object_link'><a href="Mint.html#with_rounding-class_method" title="Mint.with_rounding (method)">with_rounding</a></span></span><span class='lparen'>(</span><span class='symbol'>:floor</span><span class='rparen'>)</span> <span class='lbrace'>{</span> <span class='const'><span class='object_link'><a href="Mint.html" title="Mint (module)">Mint</a></span></span><span class='period'>.</span><span class='id identifier rubyid_parse'><span class='object_link'><a href="Mint.html#parse-instance_method" title="Mint#parse (method)">parse</a></span></span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>1.009</span><span class='tstring_end'>&#39;</span></span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>USD</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span> <span class='rbrace'>}</span> <span class='comment'>#=&gt; [USD 1.00]
253
+ </span></code></pre>
254
+ <p>Modes: <code>:half_up</code> (default), <code>:half_down</code>, <code>:floor</code>, <code>:ceil</code>, <code>:truncate</code>, <code>:down</code>. Applies to construction, parsing, <code>change</code>, <code>split</code>, and <code>allocate</code>. Restores the previous mode when the block exits, even on exception.</p>
239
255
  <p><strong>Refinements</strong> — <code>10.dollars</code> and similar helpers require <code>using Mint</code> in the current scope (see Usage above).</p>
240
256
  <p><strong>Division</strong> — <code>money / 5</code> returns new <code>Money</code>; <code>money / other_money</code> returns a numeric ratio, not money.</p>
241
257
  <p><strong>Zero equality</strong> — Any zero amount is considered equal across currencies and to numeric zero (<code>Mint.money(0, 'USD') == Mint.money(0, 'EUR')</code> is intentionally <code>true</code>). Non-zero amounts must match currency and value.</p>
242
- <p><strong>Registered currencies</strong> — <code>Mint.register_currency</code>. Only registered currency codes and symbols are recognized by the parser.</p>
258
+ <p><strong>Zero helper</strong> — <code>Currency.zero('USD')</code> returns a frozen zero-Money, useful as a default value for discounts, totals, or counters.</p>
259
+ <p><strong>Registered currencies</strong> — <code>Currency.register(code:, subunit:, symbol:, priority:)</code> adds custom currencies. Only registered codes and symbols are recognized by the parser.</p>
243
260
  <p><strong>Built-in currencies</strong> — 150+ ISO-4217 world currencies ship in <code>lib/minting/data/currencies.yaml</code> and load when the registry is first accessed.</p>
244
261
  <h2 id="Optional_top_level__Money__and__Currency_">Optional top-level <code>Money</code> and <code>Currency</code></h2>
245
262
  <p>By default, Minting keeps everything namespaced under <code>Mint</code> to coexist nicely with other gems. If you prefer shorter constants, opt in:</p>
@@ -249,9 +266,13 @@
249
266
  <p>Or at runtime:</p>
250
267
  <pre class="code ruby"><code class="ruby"><span class='const'><span class='object_link'><a href="Minting.html" title="Minting (module)">Minting</a></span></span><span class='period'>.</span><span class='id identifier rubyid_use_top_level_constants!'>use_top_level_constants!</span>
251
268
  </code></pre>
269
+ <p>For Rails applications, you can enable the top-level constants in an initializer:</p>
270
+ <pre class="code ruby"><code class="ruby"><span class='comment'># config/initializers/minting.rb
271
+ </span><span class='id identifier rubyid_require'>require</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>minting/dsl</span><span class='tstring_end'>&quot;</span></span>
272
+ </code></pre>
252
273
  <p>After opting in:</p>
253
- <pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_price'>price</span> <span class='op'>=</span> <span class='const'><span class='object_link'><a href="top-level-namespace.html#Money-constant" title="Money (constant)">Money</a></span></span><span class='period'>.</span><span class='id identifier rubyid_create'>create</span><span class='lparen'>(</span><span class='int'>10</span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>USD</span><span class='tstring_end'>&quot;</span></span><span class='rparen'>)</span> <span class='comment'># equivalent to Mint::Money.create
254
- </span><span class='id identifier rubyid_tax'>tax</span> <span class='op'>=</span> <span class='const'><span class='object_link'><a href="top-level-namespace.html#Money-constant" title="Money (constant)">Money</a></span></span><span class='period'>.</span><span class='id identifier rubyid_money'>money</span><span class='lparen'>(</span><span class='float'>2.50</span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>USD</span><span class='tstring_end'>&quot;</span></span><span class='rparen'>)</span>
274
+ <pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_price'>price</span> <span class='op'>=</span> <span class='const'><span class='object_link'><a href="top-level-namespace.html#Money-constant" title="Money (constant)">Money</a></span></span><span class='period'>.</span><span class='id identifier rubyid_from'>from</span><span class='lparen'>(</span><span class='int'>10</span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>USD</span><span class='tstring_end'>&quot;</span></span><span class='rparen'>)</span> <span class='comment'># equivalent to Mint::Money.from
275
+ </span><span class='id identifier rubyid_tax'>tax</span> <span class='op'>=</span> <span class='const'><span class='object_link'><a href="top-level-namespace.html#Money-constant" title="Money (constant)">Money</a></span></span><span class='period'>.</span><span class='id identifier rubyid_from'>from</span><span class='lparen'>(</span><span class='float'>2.50</span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>USD</span><span class='tstring_end'>&quot;</span></span><span class='rparen'>)</span>
255
276
  <span class='id identifier rubyid_cur'>cur</span> <span class='op'>=</span> <span class='const'><span class='object_link'><a href="top-level-namespace.html#Currency-constant" title="Currency (constant)">Currency</a></span></span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span><span class='lparen'>(</span><span class='label'>code:</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>EUR</span><span class='tstring_end'>&quot;</span></span><span class='comma'>,</span> <span class='label'>symbol:</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>€</span><span class='tstring_end'>&quot;</span></span><span class='comma'>,</span> <span class='label'>subunit:</span> <span class='int'>2</span><span class='comma'>,</span> <span class='label'>priority:</span> <span class='int'>0</span><span class='rparen'>)</span>
256
277
  </code></pre>
257
278
  <p><strong>Good fit:</strong> Application code, especially Rails apps.
@@ -265,7 +286,7 @@
265
286
  <p>MIT</p></div></div>
266
287
 
267
288
  <div id="footer">
268
- Generated on Sun Jun 14 21:57:00 2026 by
289
+ Generated on Tue Jun 16 20:22:19 2026 by
269
290
  <a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
270
291
  0.9.44 (ruby-4.0.5).
271
292
  </div>
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>
@@ -177,23 +193,23 @@
177
193
 
178
194
  <li class="odd ">
179
195
  <div class="item">
180
- <span class='object_link'><a href="Mint/CurrencyRegistry.html#currencies-instance_method" title="Mint::CurrencyRegistry#currencies (method)">#currencies</a></span>
181
- <small>Mint::CurrencyRegistry</small>
196
+ <span class='object_link'><a href="Mint/Registry.html#currencies-class_method" title="Mint::Registry.currencies (method)">currencies</a></span>
197
+ <small>Mint::Registry</small>
182
198
  </div>
183
199
  </li>
184
200
 
185
201
 
186
202
  <li class="even ">
187
203
  <div class="item">
188
- <span class='object_link'><a href="Mint.html#currency-class_method" title="Mint.currency (method)">currency</a></span>
189
- <small>Mint</small>
204
+ <span class='object_link'><a href="Mint/Money.html#currency-instance_method" title="Mint::Money#currency (method)">#currency</a></span>
205
+ <small>Mint::Money</small>
190
206
  </div>
191
207
  </li>
192
208
 
193
209
 
194
210
  <li class="odd ">
195
211
  <div class="item">
196
- <span class='object_link'><a href="Mint/Money.html#currency-instance_method" title="Mint::Money#currency (method)">#currency</a></span>
212
+ <span class='object_link'><a href="Mint/Money.html#currency_code-instance_method" title="Mint::Money#currency_code (method)">#currency_code</a></span>
197
213
  <small>Mint::Money</small>
198
214
  </div>
199
215
  </li>
@@ -201,21 +217,29 @@
201
217
 
202
218
  <li class="even ">
203
219
  <div class="item">
204
- <span class='object_link'><a href="Mint/Money.html#currency_code-instance_method" title="Mint::Money#currency_code (method)">#currency_code</a></span>
205
- <small>Mint::Money</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/CurrencyRegistry.html#currency_symbols-instance_method" title="Mint::CurrencyRegistry#currency_symbols (method)">#currency_symbols</a></span>
213
- <small>Mint::CurrencyRegistry</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 ">
235
+ <div class="item">
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>
238
+ </div>
239
+ </li>
240
+
241
+
242
+ <li class="odd ">
219
243
  <div class="item">
220
244
  <span class='object_link'><a href="Mint/Money.html#eql%3F-instance_method" title="Mint::Money#eql? (method)">#eql?</a></span>
221
245
  <small>Mint::Money</small>
@@ -223,7 +247,23 @@
223
247
  </li>
224
248
 
225
249
 
250
+ <li class="even ">
251
+ <div class="item">
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>
254
+ </div>
255
+ </li>
256
+
257
+
226
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 ">
227
267
  <div class="item">
228
268
  <span class='object_link'><a href="Mint/Money.html#fractional-instance_method" title="Mint::Money#fractional (method)">#fractional</a></span>
229
269
  <small>Mint::Money</small>
@@ -231,7 +271,7 @@
231
271
  </li>
232
272
 
233
273
 
234
- <li class="even ">
274
+ <li class="odd ">
235
275
  <div class="item">
236
276
  <span class='object_link'><a href="Mint/Currency.html#fractional_multiplier-instance_method" title="Mint::Currency#fractional_multiplier (method)">#fractional_multiplier</a></span>
237
277
  <small>Mint::Currency</small>
@@ -239,6 +279,14 @@
239
279
  </li>
240
280
 
241
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
+
242
290
  <li class="odd ">
243
291
  <div class="item">
244
292
  <span class='object_link'><a href="Mint/Money.html#from_fractional-class_method" title="Mint::Money.from_fractional (method)">from_fractional</a></span>
@@ -265,21 +313,29 @@
265
313
 
266
314
  <li class="even ">
267
315
  <div class="item">
268
- <span class='object_link'><a href="Mint/Currency.html#inspect-instance_method" title="Mint::Currency#inspect (method)">#inspect</a></span>
269
- <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>
270
318
  </div>
271
319
  </li>
272
320
 
273
321
 
274
322
  <li class="odd ">
275
323
  <div class="item">
276
- <span class='object_link'><a href="Mint/Money.html#inspect-instance_method" title="Mint::Money#inspect (method)">#inspect</a></span>
277
- <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>
278
326
  </div>
279
327
  </li>
280
328
 
281
329
 
282
330
  <li class="even ">
331
+ <div class="item">
332
+ <span class='object_link'><a href="Mint.html#locale_backend-class_method" title="Mint.locale_backend (method)">locale_backend</a></span>
333
+ <small>Mint</small>
334
+ </div>
335
+ </li>
336
+
337
+
338
+ <li class="odd ">
283
339
  <div class="item">
284
340
  <span class='object_link'><a href="Mint/Currency.html#minimum_amount-instance_method" title="Mint::Currency#minimum_amount (method)">#minimum_amount</a></span>
285
341
  <small>Mint::Currency</small>
@@ -287,7 +343,7 @@
287
343
  </li>
288
344
 
289
345
 
290
- <li class="odd ">
346
+ <li class="even ">
291
347
  <div class="item">
292
348
  <span class='object_link'><a href="Mint/Money.html#mint-instance_method" title="Mint::Money#mint (method)">#mint</a></span>
293
349
  <small>Mint::Money</small>
@@ -295,7 +351,7 @@
295
351
  </li>
296
352
 
297
353
 
298
- <li class="even ">
354
+ <li class="odd ">
299
355
  <div class="item">
300
356
  <span class='object_link'><a href="Mint.html#money-class_method" title="Mint.money (method)">money</a></span>
301
357
  <small>Mint</small>
@@ -303,7 +359,7 @@
303
359
  </li>
304
360
 
305
361
 
306
- <li class="odd ">
362
+ <li class="even ">
307
363
  <div class="item">
308
364
  <span class='object_link'><a href="Mint/Currency.html#name-instance_method" title="Mint::Currency#name (method)">#name</a></span>
309
365
  <small>Mint::Currency</small>
@@ -311,7 +367,7 @@
311
367
  </li>
312
368
 
313
369
 
314
- <li class="even ">
370
+ <li class="odd ">
315
371
  <div class="item">
316
372
  <span class='object_link'><a href="Mint/Money.html#negative%3F-instance_method" title="Mint::Money#negative? (method)">#negative?</a></span>
317
373
  <small>Mint::Money</small>
@@ -319,7 +375,7 @@
319
375
  </li>
320
376
 
321
377
 
322
- <li class="odd ">
378
+ <li class="even ">
323
379
  <div class="item">
324
380
  <span class='object_link'><a href="Mint/Money.html#nonzero%3F-instance_method" title="Mint::Money#nonzero? (method)">#nonzero?</a></span>
325
381
  <small>Mint::Money</small>
@@ -327,7 +383,7 @@
327
383
  </li>
328
384
 
329
385
 
330
- <li class="even ">
386
+ <li class="odd ">
331
387
  <div class="item">
332
388
  <span class='object_link'><a href="Mint/Currency.html#normalize_amount-instance_method" title="Mint::Currency#normalize_amount (method)">#normalize_amount</a></span>
333
389
  <small>Mint::Currency</small>
@@ -335,7 +391,7 @@
335
391
  </li>
336
392
 
337
393
 
338
- <li class="odd ">
394
+ <li class="even ">
339
395
  <div class="item">
340
396
  <span class='object_link'><a href="Mint.html#parse-instance_method" title="Mint#parse (method)">#parse</a></span>
341
397
  <small>Mint</small>
@@ -343,6 +399,30 @@
343
399
  </li>
344
400
 
345
401
 
402
+ <li class="odd ">
403
+ <div class="item">
404
+ <span class='object_link'><a href="Mint/Money.html#parse-class_method" title="Mint::Money.parse (method)">parse</a></span>
405
+ <small>Mint::Money</small>
406
+ </div>
407
+ </li>
408
+
409
+
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
+
346
426
  <li class="even ">
347
427
  <div class="item">
348
428
  <span class='object_link'><a href="Mint/Money.html#positive%3F-instance_method" title="Mint::Money#positive? (method)">#positive?</a></span>
@@ -361,16 +441,32 @@
361
441
 
362
442
  <li class="even ">
363
443
  <div class="item">
364
- <span class='object_link'><a href="Mint/CurrencyRegistry.html#register-instance_method" title="Mint::CurrencyRegistry#register (method)">#register</a></span>
365
- <small>Mint::CurrencyRegistry</small>
444
+ <span class='object_link'><a href="Mint/Registry.html#register-class_method" title="Mint::Registry.register (method)">register</a></span>
445
+ <small>Mint::Registry</small>
366
446
  </div>
367
447
  </li>
368
448
 
369
449
 
370
450
  <li class="odd ">
371
451
  <div class="item">
372
- <span class='object_link'><a href="Mint.html#register_currency-class_method" title="Mint.register_currency (method)">register_currency</a></span>
373
- <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>
454
+ </div>
455
+ </li>
456
+
457
+
458
+ <li class="even ">
459
+ <div class="item">
460
+ <span class='object_link'><a href="Mint/Currency.html#resolve-class_method" title="Mint::Currency.resolve (method)">resolve</a></span>
461
+ <small>Mint::Currency</small>
462
+ </div>
463
+ </li>
464
+
465
+
466
+ <li class="odd ">
467
+ <div class="item">
468
+ <span class='object_link'><a href="Mint/Currency.html#resolve!-class_method" title="Mint::Currency.resolve! (method)">resolve!</a></span>
469
+ <small>Mint::Currency</small>
374
470
  </div>
375
471
  </li>
376
472
 
@@ -495,6 +591,22 @@
495
591
  </li>
496
592
 
497
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
+
602
+ <li class="even ">
603
+ <div class="item">
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>
606
+ </div>
607
+ </li>
608
+
609
+
498
610
  <li class="odd ">
499
611
  <div class="item">
500
612
  <span class='object_link'><a href="Mint.html#world_currencies-class_method" title="Mint.world_currencies (method)">world_currencies</a></span>
@@ -503,6 +615,38 @@
503
615
  </li>
504
616
 
505
617
 
618
+ <li class="even ">
619
+ <div class="item">
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>
622
+ </div>
623
+ </li>
624
+
625
+
626
+ <li class="odd ">
627
+ <div class="item">
628
+ <span class='object_link'><a href="Mint/Money.html#zero-class_method" title="Mint::Money.zero (method)">zero</a></span>
629
+ <small>Mint::Money</small>
630
+ </div>
631
+ </li>
632
+
633
+
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
+
506
650
  <li class="even ">
507
651
  <div class="item">
508
652
  <span class='object_link'><a href="Mint/Money.html#zero%3F-instance_method" title="Mint::Money#zero? (method)">#zero?</a></span>
@@ -511,6 +655,14 @@
511
655
  </li>
512
656
 
513
657
 
658
+ <li class="odd ">
659
+ <div class="item">
660
+ <span class='object_link'><a href="Mint/Registry.html#zero_for-class_method" title="Mint::Registry.zero_for (method)">zero_for</a></span>
661
+ <small>Mint::Registry</small>
662
+ </div>
663
+ </li>
664
+
665
+
514
666
 
515
667
  </ul>
516
668
  </div>
@@ -141,7 +141,7 @@
141
141
  </div>
142
142
 
143
143
  <div id="footer">
144
- Generated on Sun Jun 14 21:57:00 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>
@@ -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
@@ -39,6 +40,75 @@ module Mint
39
40
  # Normalizes numeric amounts for this currency
40
41
  # 1. Converts to Rational
41
42
  # 2. Rounds to respect currency subunit
42
- 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:)
43
59
  end
60
+
61
+ # Resolves an object into a {Currency}, returning +nil+ when it can't.
62
+ #
63
+ # Accepts +nil+, +String+, {Currency}, or {Money}.
64
+ # Passing a {Money} extracts its currency
65
+ #
66
+ # @param object [String, Currency, Money, nil] a currency code, object, or +nil+
67
+ # @return [Currency, nil] the resolved Currency, or +nil+ if +object+ is +nil+
68
+ # or the code is not registered
69
+ # @raise [ArgumentError] if +object+ is an unsupported type (e.g. +Integer+)
70
+ def Currency.resolve(object)
71
+ case object
72
+ when NilClass then nil
73
+ when Currency then object
74
+ when Money then object.currency
75
+ when String then Currency.for_code object
76
+ else raise ArgumentError, "currency must be [Currency], [Money], [String] or nil (#{object})"
77
+ end
78
+ end
79
+
80
+ # Resolves an object into a {Currency}, raising on failure.
81
+ #
82
+ # Like {.resolve} but raises when the result would be +nil+.
83
+ #
84
+ # @param object [String, Currency, Money, nil] a currency code, object, or +nil+
85
+ # @return [Currency] the resolved Currency
86
+ # @raise [ArgumentError] if +object+ cannot be resolved into a registered currency
87
+ def Currency.resolve!(object)
88
+ resolve(object) or raise ArgumentError, "Could not resolve (#{object}) into a currency"
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))
44
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
@@ -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