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/Minting.html CHANGED
@@ -116,7 +116,7 @@
116
116
 
117
117
  </div>
118
118
  </dt>
119
- <dd><pre class="code"><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>1.7.1</span><span class='tstring_end'>&#39;</span></span></pre></dd>
119
+ <dd><pre class="code"><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>1.7.3</span><span class='tstring_end'>&#39;</span></span></pre></dd>
120
120
 
121
121
  </dl>
122
122
 
@@ -132,7 +132,7 @@
132
132
  </div>
133
133
 
134
134
  <div id="footer">
135
- Generated on Sun Jun 14 21:57:01 2026 by
135
+ Generated on Tue Jun 16 20:22:19 2026 by
136
136
  <a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
137
137
  0.9.44 (ruby-4.0.5).
138
138
  </div>
data/doc/_index.html CHANGED
@@ -89,13 +89,6 @@
89
89
 
90
90
  </li>
91
91
 
92
- <li>
93
- <span class='object_link'><a href="Mint/CurrencyRegistry.html" title="Mint::CurrencyRegistry (module)">CurrencyRegistry</a></span>
94
-
95
- <small>(Mint)</small>
96
-
97
- </li>
98
-
99
92
  </ul>
100
93
  </ul>
101
94
 
@@ -136,6 +129,20 @@
136
129
 
137
130
  </li>
138
131
 
132
+ <li>
133
+ <span class='object_link'><a href="Mint/Registry.html" title="Mint::Registry (module)">Registry</a></span>
134
+
135
+ <small>(Mint)</small>
136
+
137
+ </li>
138
+
139
+ <li>
140
+ <span class='object_link'><a href="Mint/Rounding.html" title="Mint::Rounding (module)">Rounding</a></span>
141
+
142
+ <small>(Mint)</small>
143
+
144
+ </li>
145
+
139
146
  </ul>
140
147
  </ul>
141
148
 
@@ -163,7 +170,7 @@
163
170
  </div>
164
171
 
165
172
  <div id="footer">
166
- Generated on Sun Jun 14 21:57:00 2026 by
173
+ Generated on Tue Jun 16 20:22:19 2026 by
167
174
  <a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
168
175
  0.9.44 (ruby-4.0.5).
169
176
  </div>
@@ -0,0 +1,329 @@
1
+ # Minting gem API review
2
+
3
+ **Data:** 2026-06-15
4
+ **Author:** Wave AI (via Wave Terminal assistant)
5
+
6
+ ## 1. Top-level API surface (Mint / Money / Currency)
7
+
8
+ ### What’s good
9
+
10
+ - `Mint.money(10, 'USD')` is clear and discoverable.
11
+ - Refinements (`10.dollars`, `4.to_money('USD')`) are modern and opt-in.
12
+ - Optional `minting/dsl` with `Money` / `Currency` constants is a good compromise for ergonomics vs. gem conflicts.
13
+
14
+ ### Suggestions
15
+
16
+ 1. **Tighten constructor story (too many verbs)**
17
+ Right now you have:
18
+ - `Mint.money(amount, code)`
19
+ - `Mint.zero(currency)`
20
+ - `Mint::Money.create(amount, currency)`
21
+ - `Mint::Money.from_fractional(fractional, currency)`
22
+ - `Money.create` / `Money.from_fractional` / `price.mint(new_amount)` (instance)
23
+
24
+ Consider a simpler, more opinionated set:
25
+
26
+ - **Class side:**
27
+ - `Money.from(amount, currency)` (instead of `create`)
28
+ - `Money.from_fractional(fractional, currency)`
29
+ - **Module side:**
30
+ - `Mint.money(amount, currency)` (delegates to `Money.from`)
31
+ - `Mint.from_fractional(fractional, currency)` (delegates to `Money.from_fractional`)
32
+ - `Mint.zero(currency)`
33
+
34
+ And **remove / de-emphasize** `Money.create` from public docs (keep as private alias if needed).
35
+
36
+ 2. **Rename `mint(new_amount)` → clearer “copy with” semantics**
37
+
38
+ `price.mint(15.00)` is cute but not self-describing. Consider:
39
+
40
+ - `price.with_amount(15.00)`
41
+ - or `price.change(amount: 15.00)`
42
+ - or `price.rebuild(15.00)` (less good, but at least indicates a copy)
43
+
44
+ And surface this in README (“Immutability helpers”).
45
+
46
+ 3. **Top-level constants: make the opt-in path prominent, but one-liner**
47
+
48
+ You already have:
49
+
50
+ ```ruby
51
+ require "minting"
52
+ require "minting/dsl" # opt-in top‑level Money / Currency
53
+ ```
54
+
55
+ For Rails developers, you might recommend in README:
56
+
57
+ ```ruby
58
+ # config/initializers/minting.rb
59
+ require "minting/dsl"
60
+ ```
61
+
62
+ And add a short “Rails setup” snippet, since that’s what competing gems usually highlight first.
63
+
64
+ ---
65
+
66
+ ## 2. Money semantics & naming
67
+
68
+ ### Zero equality semantics
69
+
70
+ You do something non-standard and powerful:
71
+
72
+ ```ruby
73
+ Mint.money(0, 'USD') == Mint.money(0, 'EUR') # => true
74
+ Mint.money(0, 'USD') == 0 # => true
75
+ ```
76
+
77
+ This is very nice for totals, but surprising vs. `money` gem.
78
+
79
+ **Changes:**
80
+
81
+ 1. **Make this a named feature, with an escape hatch**
82
+
83
+ - Give it a name in docs: e.g. “currency-agnostic zero”.
84
+ - Provide an **explicit predicate or helper**:
85
+
86
+ ```ruby
87
+ price.zero? # usual predicate
88
+ price.strictly_zero_in?('USD') # same_currency? + zero?
89
+ ```
90
+
91
+ - Consider a **config flag** or alternate comparator:
92
+
93
+ ```ruby
94
+ Mint.strict_zero_comparison = true
95
+ # or
96
+ price.eql_in_currency?(other_price)
97
+ ```
98
+
99
+ 2. **Docs: add a clear “Gotchas” section**
100
+ Call out at the bottom of README “Behavior that differs from `money` gem”, starting with zero. This directly addresses “gap to competitors” and reduces surprises.
101
+
102
+ ### `same_currency?`
103
+
104
+ Current doc:
105
+
106
+ ```ruby
107
+ # @param other [Currency] the target currency to compare
108
+ def same_currency?(other) = other.currency == currency
109
+ ```
110
+
111
+ This is odd: the param type is a `Currency` in the docs, but you call `other.currency` which implies it’s actually `Money`.
112
+
113
+ **Change:**
114
+
115
+ - Decide on the intent; then:
116
+ - If it compares two `Money` objects, define:
117
+
118
+ ```ruby
119
+ # @param other [Money]
120
+ def same_currency?(other) = other.currency == currency
121
+ ```
122
+
123
+ - Or if you want both forms, accept either and update docs:
124
+
125
+ ```ruby
126
+ def same_currency?(other)
127
+ other_currency =
128
+ case other
129
+ when Mint::Money then other.currency
130
+ when Mint::Currency then other
131
+ else
132
+ Currency.resolve!(other)
133
+ end
134
+
135
+ other_currency == currency
136
+ end
137
+ ```
138
+
139
+ - Consider renaming to `same_currency_as?(other)` to better match Ruby predicate idioms and feel less “type-ish”.
140
+
141
+ ---
142
+
143
+ ## 3. Parsing API
144
+
145
+ ### Suggestions
146
+
147
+ 1. **Return type & error modes**
148
+
149
+ - Document explicitly that `Mint.parse` returns `Mint::Money`.
150
+ - Add **two modes**:
151
+ - `Mint.parse!(...)` – raises on failure.
152
+ - `Mint.parse(...)` – returns `nil` on failure or perhaps `Result` object in future, but nil is sufficient initially.
153
+
154
+ 3. **Quality-of-life alias**
155
+
156
+ - `Mint.money_from(str, currency_code = nil)`
157
+ - Or a class method: `Mint::Money.parse(str, currency: nil)`
158
+
159
+ That keeps “all money stuff under Money” for folks who avoid module functions.
160
+
161
+ ---
162
+
163
+ ## 4. Formatting API
164
+
165
+ Current:
166
+
167
+ - `to_s(format: '%<symbol>s%<amount>f')`
168
+ - Hash format for per-sign: `{ negative: '(%<symbol>s%<amount>f)' }`
169
+
170
+ This is powerful but low-level. Competing gems typically offer higher-level presets and localization.
171
+
172
+ ### Suggestions
173
+
174
+ 1. **Named formats / shortcuts**
175
+
176
+ Something like:
177
+
178
+ ```ruby
179
+ price.format # same as to_s
180
+ price.format(:iso) # "USD 9.99"
181
+ price.format(:symbol) # "$9.99"
182
+ price.format(:code) # "9.99 USD"
183
+ ```
184
+
185
+ Internally, use a format registry:
186
+
187
+ ```ruby
188
+ Mint.formats.register(:iso, '%<currency>s %<amount>f')
189
+ ```
190
+
191
+ 2. **Accounting format shortcut**
192
+
193
+ You already support per-sign hash formats; expose a named helper:
194
+
195
+ ```ruby
196
+ price.to_accounting # ($1,234.56) for negatives, 0.00 for zero
197
+ ```
198
+
199
+ 3. **JSON / Rails integration**
200
+
201
+ You have:
202
+
203
+ ```ruby
204
+ price.to_json # => {"currency":"USD","amount":"9.99"}
205
+ price.to_hash # => { currency: "USD", amount: "9.99" }
206
+ ```
207
+
208
+ For better Rails DX & parity:
209
+
210
+ - Add `as_json` delegating to `to_hash`.
211
+ - Mention in README: “Works with Rails serialization (`as_json` implemented).”
212
+
213
+ ---
214
+
215
+ ## 5. Currency API
216
+
217
+ Current:
218
+
219
+ - `Mint.currency_for_code('USD')`
220
+ - `Mint.currency_for_symbol('$')`
221
+ - `Mint.register_currency(...)`
222
+ - `Mint.world_currencies` (+ internal `Registry`)
223
+
224
+ ### Suggestions
225
+
226
+ 1. **Consistent names & variants**
227
+
228
+ Consider:
229
+
230
+ - `Mint.currency('USD')` → primary lookup (by code; maybe symbol in future).
231
+ - Keep `currency_for_code` / `currency_for_symbol` as explicit variants, but guide people to the simple `currency`.
232
+
233
+ 2. **Clarify custom currency lifecycle**
234
+
235
+ Competitors often have quirks here; you can win on clarity:
236
+
237
+ - Are custom currencies persisted per process?
238
+ - Are they thread-safe?
239
+ - Are they ordered by `priority` in deterministic way?
240
+
241
+ Add a small “Custom currencies” section with examples and guarantees.
242
+
243
+ 3. **Expose the registry read-only**
244
+
245
+ Instead of `world_currencies` returning “the frozen world-currencies hash” (but you also have `Registry.currencies`), maybe have:
246
+
247
+ ```ruby
248
+ Mint.currencies # => { "USD" => <Currency>, ... } (frozen hash)
249
+ ```
250
+
251
+ And keep `Registry` private in docs.
252
+
253
+ ---
254
+
255
+ ## 6. Error types & clarity
256
+
257
+ ### UnknownCurrency
258
+
259
+ ```ruby
260
+ # Unknown currency excpetion
261
+ class UnknownCurrency < StandardError; end
262
+ ```
263
+
264
+ - Typo in comment (“excpetion”).
265
+ - Recommend renaming to `UnknownCurrencyError` for conventional Ruby style.
266
+ - Ensure it’s actually raised from `Currency.resolve!` (and document that).
267
+
268
+ ### Validation errors
269
+
270
+ You currently raise `ArgumentError` for several things (`amount must be Numeric`, `fractional must be an Integer`).
271
+
272
+ Consider:
273
+
274
+ - Keeping `ArgumentError` but **documenting all the failure cases** in YARD and README.
275
+ - Or, for one level up in clarity, introduce:
276
+
277
+ ```ruby
278
+ class InvalidMoneyArgument < ArgumentError; end
279
+ ```
280
+
281
+ and use that everywhere. This is a small DX win in large apps.
282
+
283
+ ---
284
+
285
+ ## 7. Documentation structure (DX & competitiveness)
286
+
287
+ Your README is already strong. To push it over the top vs. `money` gem and friends:
288
+
289
+ 1. **Add a “Comparison” section**
290
+
291
+ Not necessarily with names, but structurally:
292
+
293
+ - “What Minting does differently”
294
+ - Always-exact `Rational` amounts.
295
+ - Currency-agnostic zero.
296
+ - Faster formatting (link benchmarks).
297
+ - Separate `minting-rails` companion for clean Rails integration.
298
+
299
+ 2. **Add “Common tasks” cheatsheet**
300
+
301
+ Short, scannable table:
302
+
303
+ | Task | Code |
304
+ |------------------------------|-----------------------------------|
305
+ | New amount | `Mint.money(10, 'USD')` |
306
+ | From cents | `Mint::Money.from_fractional(999, 'USD')` |
307
+ | Change amount immutably | `price.with_amount(15)` (or `mint`) |
308
+ | Parse user input | `Mint.parse('$19.99')` |
309
+ | Serialize to JSON | `price.to_hash` / `price.as_json` |
310
+ | Clamp to range | `price.clamp(0, 100)` |
311
+ | Split / allocate | `ten.split(3)` / `ten.allocate([...])` |
312
+
313
+ This directly optimizes developer experience.
314
+
315
+ 3. **Prominent “Rails” heading**
316
+
317
+ Right now you just mention `minting-rails`. Make it a full section:
318
+
319
+ - How to add gem.
320
+ - Example migration / attribute definition (even if in the other repo, mirror one snippet here).
321
+
322
+ ---
323
+
324
+ ## 8. Minor polish
325
+
326
+ - In `README` “Json serialization” → “JSON serialization”.
327
+ - Make sure `Mint::Money`’s `inspect` and `to_s` are clearly differentiated in docs:
328
+ - `inspect` → developer/debugging (`[USD 10.00]`).
329
+ - `to_s` → user-facing, configurable formatting.
@@ -21,10 +21,6 @@ Build, test and lint commands
21
21
  - Run a single test method by name (Minitest -n regexp):
22
22
  - ruby -Ilib:test -r ./test/test_helper.rb test/money/money_test.rb -n /test_creation/
23
23
 
24
- - Performance suites:
25
- - rake bench:performance
26
- - rake bench:competitive
27
- - rake bench:regression
28
24
 
29
25
  - Linting:
30
26
  - bundle exec rake cop
@@ -56,7 +52,6 @@ Key conventions and repo-specific rules
56
52
  - Currency registration: use Mint.register_currency for idempotent registration; Mint.register_currency! raises on duplicates. Codes must match /^[A-Z_]+$/.
57
53
  - Symbol parsing: parser resolves symbols by longest match then currency priority (see Mint.currency_symbols sorting).
58
54
  - Tests: test_helper.rb configures coverage (SimpleCov) and loads minitest; when running tests outside rake, require test_helper (-r ./test/test_helper.rb).
59
- - Benchmarks: set to enable benchmark-heavy tasks; benchmarks use Minitest::Benchmark patterns.
60
55
  - Formatting: Money.to_s uses Kernel.format patterns; take care with %<amount>f vs %<amount>d depending on desired rounding/formatting.
61
56
 
62
57
  Files and places to check first during edits
@@ -0,0 +1,75 @@
1
+ Repository overview
2
+
3
+ - Language: Ruby gem (minting)
4
+ - Location of main code: lib/minting and its subfolders (mint/, money/)
5
+ - Public API surface: Mint (factory/helpers), Mint::Money, Mint::Currency
6
+ - Data: built-in currencies in lib/minting/data/currencies.yaml
7
+ - Tests: Minitest (unit) + performance benchmarks under test/performance
8
+
9
+ Build, test and lint commands
10
+
11
+ - Install dependencies:
12
+ - bundle install
13
+
14
+ - Run full test suite (default task):
15
+ - bundle exec rake
16
+ - or simply: rake
17
+
18
+ - Run a single test file (recommended when iterating):
19
+ - ruby -Ilib:test -r ./test/test_helper.rb test/money/money_test.rb
20
+
21
+ - Run a single test method by name (Minitest -n regexp):
22
+ - ruby -Ilib:test -r ./test/test_helper.rb test/money/money_test.rb -n /test_creation/
23
+
24
+ - Performance suites:
25
+ - rake bench:performance
26
+ - rake bench:competitive
27
+ - rake bench:regression
28
+
29
+ - Linting:
30
+ - bundle exec rake cop
31
+ - or: bundle exec rubocop
32
+
33
+ - Build gem package:
34
+ - gem build minting.gemspec
35
+
36
+ - Documentation:
37
+ - bundle exec rake yard
38
+
39
+ - README verification:
40
+ - README examples are exercised by `test/minting_test.rb#test_readme_usage`.
41
+ - Prefer the README as the authoritative usage guide for feature behavior and examples.
42
+
43
+ High-level architecture (big picture)
44
+
45
+ - Top-level: lib/minting.rb requires the Mint module and Money implementation.
46
+ - Mint module: currency registry and factory helpers live in lib/minting/mint/*. Registry loads lib/minting/data/currencies.yaml on first access.
47
+ - Currency: lightweight value object (code, subunit, symbol, priority, minimum_amount).
48
+ - Money: immutable value object stored as Rational and rounded to currency.subunit. Core concerns split across lib/minting/money/* (arithmetics, formatting, conversion, coercion, allocation, parsing, comparable).
49
+ - Refinements: Numeric/String/Refinements in lib/minting/mint/refinements.rb expose helpers like 10.dollars, 4.to_money('USD'), and require `using Mint` in scope.
50
+ - Performance tests: separate bench tasks under Rake; test/performance holds benchmark suites.
51
+
52
+ Key conventions and repo-specific rules
53
+
54
+ - Exactness: amounts are stored as Rational and rounded to the currency subunit. Prefer rationals or decimal strings (e.g., '19.99'.to_r or 1999/100r) when precision is needed.
55
+ - Zero equality: zeros are equal across currencies (Mint.money(0,'USD') == Mint.money(0,'EUR') == 0). Non-zero comparisons require identical currency and amount.
56
+ - Currency registration: use Mint.register_currency for idempotent registration; Mint.register_currency! raises on duplicates. Codes must match /^[A-Z_]+$/.
57
+ - Symbol parsing: parser resolves symbols by longest match then currency priority (see Mint.currency_symbols sorting).
58
+ - Tests: test_helper.rb configures coverage (SimpleCov) and loads minitest; when running tests outside rake, require test_helper (-r ./test/test_helper.rb).
59
+ - Benchmarks: set to enable benchmark-heavy tasks; benchmarks use Minitest::Benchmark patterns.
60
+ - Formatting: Money.to_s uses Kernel.format patterns; take care with %<amount>f vs %<amount>d depending on desired rounding/formatting.
61
+
62
+ Files and places to check first during edits
63
+
64
+ - lib/minting/money - core behavior and arithmetic
65
+ - lib/minting/mint - currency registry, refinements, and factory API
66
+ - lib/minting/data/currencies.yaml - canonical currency definitions
67
+ - test/ - unit tests; test/performance - benchmark suites
68
+
69
+ Notes for Copilot sessions
70
+
71
+ - Prefer making atomic changes and run the unit test(s) covering the changed area. Use the single-file test invocation above when iterating rapidly.
72
+ - When changing numeric/rounding behavior, run both unit tests and relevant performance benchmarks.
73
+ - Respect zero-equality semantics and currency code validation when modifying equality/hash logic.
74
+
75
+ If you want, update this file with project-specific conventions to capture workflow choices (e.g., backport policy, DI patterns).
data/doc/class_list.html CHANGED
@@ -46,7 +46,7 @@
46
46
 
47
47
  <ul id="full_list" class="class">
48
48
  <li id="object_" class="odd"><div class="item" style="padding-left:30px"><span class='object_link'><a href="top-level-namespace.html" title="Top Level Namespace (root)">Top Level Namespace</a></span></div></li>
49
- <li id='object_Mint' class='even'><div class='item' style='padding-left:30px'><a tabindex='0' class='toggle' role='button' aria-label='Mint child nodes' aria-expanded='false' aria-controls='object_Mint'></a> <span class='object_link'><a href="Mint.html" title="Mint (module)">Mint</a></span><small class='search_info'>Top Level Namespace</small></div><div aria-labelledby='object_Mint'><ul><li id='object_Mint::Currency' class='collapsed odd'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Mint/Currency.html" title="Mint::Currency (class)">Currency</a></span> &lt; Data<small class='search_info'>Mint</small></div></li><li id='object_Mint::CurrencyRegistry' class='collapsed even'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Mint/CurrencyRegistry.html" title="Mint::CurrencyRegistry (module)">CurrencyRegistry</a></span><small class='search_info'>Mint</small></div></li><li id='object_Mint::Money' class='collapsed odd'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Mint/Money.html" title="Mint::Money (class)">Money</a></span> &lt; Object<small class='search_info'>Mint</small></div></li><li id='object_Mint::RangeStepPatch' class='collapsed even'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Mint/RangeStepPatch.html" title="Mint::RangeStepPatch (module)">RangeStepPatch</a></span><small class='search_info'>Mint</small></div></li><li id='object_Mint::UnknownCurrency' class='collapsed odd'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Mint/UnknownCurrency.html" title="Mint::UnknownCurrency (class)">UnknownCurrency</a></span> &lt; StandardError<small class='search_info'>Mint</small></div></li></ul></div></li><li id='object_Minting' class='even'><div class='item' style='padding-left:30px'><span class='object_link'><a href="Minting.html" title="Minting (module)">Minting</a></span><small class='search_info'>Top Level Namespace</small></div></li>
49
+ <li id='object_Mint' class='even'><div class='item' style='padding-left:30px'><a tabindex='0' class='toggle' role='button' aria-label='Mint child nodes' aria-expanded='false' aria-controls='object_Mint'></a> <span class='object_link'><a href="Mint.html" title="Mint (module)">Mint</a></span><small class='search_info'>Top Level Namespace</small></div><div aria-labelledby='object_Mint'><ul><li id='object_Mint::Currency' class='collapsed odd'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Mint/Currency.html" title="Mint::Currency (class)">Currency</a></span> &lt; Data<small class='search_info'>Mint</small></div></li><li id='object_Mint::Money' class='collapsed even'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Mint/Money.html" title="Mint::Money (class)">Money</a></span> &lt; Object<small class='search_info'>Mint</small></div></li><li id='object_Mint::RangeStepPatch' class='collapsed odd'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Mint/RangeStepPatch.html" title="Mint::RangeStepPatch (module)">RangeStepPatch</a></span><small class='search_info'>Mint</small></div></li><li id='object_Mint::Registry' class='collapsed even'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Mint/Registry.html" title="Mint::Registry (module)">Registry</a></span><small class='search_info'>Mint</small></div></li><li id='object_Mint::Rounding' class='collapsed odd'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Mint/Rounding.html" title="Mint::Rounding (module)">Rounding</a></span><small class='search_info'>Mint</small></div></li><li id='object_Mint::UnknownCurrency' class='collapsed even'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Mint/UnknownCurrency.html" title="Mint::UnknownCurrency (class)">UnknownCurrency</a></span> &lt; StandardError<small class='search_info'>Mint</small></div></li></ul></div></li><li id='object_Minting' class='odd'><div class='item' style='padding-left:30px'><span class='object_link'><a href="Minting.html" title="Minting (module)">Minting</a></span><small class='search_info'>Top Level Namespace</small></div></li>
50
50
 
51
51
  </ul>
52
52
  </div>
data/doc/file.README.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>