minting 1.9.3 → 1.9.5
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 +14 -20
- data/doc/agents/api_review-2026-06-15.md +2 -2
- data/doc/agents/expired/recommendations.md +1 -1
- data/lib/minting/currency/currency.rb +5 -3
- data/lib/minting/mint/aliases.rb +14 -8
- data/lib/minting/mint/dsl/numeric.rb +14 -16
- data/lib/minting/mint/dsl/string.rb +7 -9
- data/lib/minting/mint/i18n.rb +1 -1
- data/lib/minting/mint/mint.rb +8 -3
- data/lib/minting/mint.rb +0 -1
- data/lib/minting/money/constructors.rb +5 -11
- data/lib/minting/version.rb +1 -1
- data/lib/minting.rb +10 -0
- metadata +1 -2
- data/lib/minting/mint/dsl/top_level.rb +0 -17
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 429ae46c67aa4b6bb032a9e9be85cbf02b2ee0576cce83c0ad4f36aa0c46e08c
|
|
4
|
+
data.tar.gz: a5a1c37ad5f6b8ced5e62323803431cd7385577c7a15963b0a29c92f7f7907b8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ad956434a0dd03f554a638466d44ce049cd7b16e1592f07507954d331d32b5ede3a3f9cb635b6fe9ad6204fe44f840240cbd6d8d49d5c18afcf7b4401328ecab
|
|
7
|
+
data.tar.gz: 5c81f05414ea2c8f4e6b68daaf5a48a76ab7109c68581246333d99e488d9eec3faf5f5e6dc7e8293f2dfb2d6fb51f01b43ddc49770fde62cb49c05288496a7be
|
data/README.md
CHANGED
|
@@ -30,7 +30,7 @@ Minting is faster than the Money gem for everyday operations and **over 10× fas
|
|
|
30
30
|
Intuitive interface, descriptive error messages, and sensible defaults. Works the way you expect.
|
|
31
31
|
|
|
32
32
|
### Rails-ready
|
|
33
|
-
Use with the [
|
|
33
|
+
Use with the [attribute-money](https://github.com/gferraz/attribute-money) companion gem for drop-in ActiveRecord type casting, validators, and form helpers.
|
|
34
34
|
|
|
35
35
|
### Quality code
|
|
36
36
|
- **100% test coverage** — every line exercised
|
|
@@ -57,9 +57,6 @@ require 'minting'
|
|
|
57
57
|
# Create money
|
|
58
58
|
ten = Mint.money(10, 'USD') #=> [USD 10.00]
|
|
59
59
|
|
|
60
|
-
# Create money using Numeric refinements
|
|
61
|
-
using Mint
|
|
62
|
-
|
|
63
60
|
1.dollar == Mint.money(1, 'USD') #=> true
|
|
64
61
|
ten = 10.dollars #=> [USD 10.00]
|
|
65
62
|
4.to_money('USD') #=> [USD 4.00]
|
|
@@ -110,7 +107,7 @@ price_in_euros.to_formatted_s(format: '%<symbol>2s%<amount>+10f') #=> " €
|
|
|
110
107
|
|
|
111
108
|
# Integral & fractional parts
|
|
112
109
|
price.to_formatted_s(format: '%<integral>d %<fractional>d/100') #=> "9 99/100"
|
|
113
|
-
Mint.money(0.99, 'USD').
|
|
110
|
+
Mint.money(0.99, 'USD').to_fs(format: '%<integral>d dollars and %<fractional>02d cents')
|
|
114
111
|
#=> "0 dollars and 99 cents"
|
|
115
112
|
|
|
116
113
|
# Per-sign Hash format (e.g. accounting parentheses for losses)
|
|
@@ -213,8 +210,6 @@ Modes: `:half_up` (default), `:half_down`, `:floor`, `:ceil`, `:truncate`, `:dow
|
|
|
213
210
|
|
|
214
211
|
> **Performance note:** Rounding-mode support is not loaded by default — `require 'minting'` uses the fastest possible rounding (equivalent to `:half_up`) with zero dispatch overhead. The first call to `Mint.with_rounding` loads the rounding module and patches `Currency#normalize_amount`, adding ~10–35 ns per money creation or mutation. If your application never uses custom rounding modes (the common case), there is **no performance cost**.
|
|
215
212
|
|
|
216
|
-
**Refinements** — `10.dollars` and similar helpers require `using Mint` in the current scope (see Usage above).
|
|
217
|
-
|
|
218
213
|
**Division** — `money / 5` returns new `Money`; `money / other_money` returns a numeric ratio, not money.
|
|
219
214
|
|
|
220
215
|
**Zero equality** — Any zero amount is considered equal across currencies and to numeric zero (`Mint.money(0, 'USD') == Mint.money(0, 'EUR')` is intentionally `true`). Non-zero amounts must match currency and value.
|
|
@@ -227,33 +222,32 @@ Modes: `:half_up` (default), `:half_down`, `:floor`, `:ceil`, `:truncate`, `:dow
|
|
|
227
222
|
|
|
228
223
|
## Optional top-level `Money` and `Currency`
|
|
229
224
|
|
|
230
|
-
By default,
|
|
225
|
+
By default, `require "minting"` exposes `Mint::Money` as the top-level `Money` constant, so you can write `Money.from(10, "USD")` directly:
|
|
231
226
|
|
|
232
227
|
```ruby
|
|
233
228
|
require "minting"
|
|
234
|
-
|
|
229
|
+
|
|
230
|
+
price = Money.from(10, "USD") # equivalent to Mint::Money.from
|
|
231
|
+
tax = Money.from(2.50, "USD")
|
|
235
232
|
```
|
|
236
233
|
|
|
237
|
-
|
|
234
|
+
`Currency` is **not** auto-bound, because application domain models are commonly named `Currency` (e.g. a Rails model). To opt in to the top-level `Currency` constant:
|
|
238
235
|
|
|
239
236
|
```ruby
|
|
240
|
-
|
|
237
|
+
require "minting"
|
|
238
|
+
require "minting/mint/aliases" # opt-in top-level Currency
|
|
239
|
+
|
|
240
|
+
cur = Currency.new(code: "EUR", symbol: "€", subunit: 2, priority: 0)
|
|
241
241
|
```
|
|
242
242
|
|
|
243
|
-
For Rails applications, you can enable the top-level
|
|
243
|
+
For Rails applications, you can enable the top-level `Currency` constant in an initializer:
|
|
244
244
|
|
|
245
245
|
```ruby
|
|
246
246
|
# config/initializers/minting.rb
|
|
247
|
-
require "minting/
|
|
247
|
+
require "minting/mint/aliases"
|
|
248
248
|
```
|
|
249
249
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
```ruby
|
|
253
|
-
price = Money.from(10, "USD") # equivalent to Mint::Money.from
|
|
254
|
-
tax = Money.from(2.50, "USD")
|
|
255
|
-
cur = Currency.new(code: "EUR", symbol: "€", subunit: 2, priority: 0)
|
|
256
|
-
```
|
|
250
|
+
If another `Money` is already defined when `require "minting"` runs (e.g. the `money` gem was loaded first), Minting warns and skips the auto-bind — use `Mint::Money` in that case. The same applies to `Currency` via `minting/mint/aliases`.
|
|
257
251
|
|
|
258
252
|
**Good fit:** Application code, especially Rails apps.
|
|
259
253
|
**Not recommended:** Reusable gems/libraries — stick to `Mint::Money` to avoid conflicts.
|
|
@@ -294,7 +294,7 @@ Your README is already strong. To push it over the top vs. `money` gem and frien
|
|
|
294
294
|
- Always-exact `Rational` amounts.
|
|
295
295
|
- Currency-agnostic zero.
|
|
296
296
|
- Faster formatting (link benchmarks).
|
|
297
|
-
- Separate `
|
|
297
|
+
- Separate `attribute-money` companion for clean Rails integration.
|
|
298
298
|
|
|
299
299
|
2. **Add “Common tasks” cheatsheet**
|
|
300
300
|
|
|
@@ -314,7 +314,7 @@ Your README is already strong. To push it over the top vs. `money` gem and frien
|
|
|
314
314
|
|
|
315
315
|
3. **Prominent “Rails” heading**
|
|
316
316
|
|
|
317
|
-
Right now you just mention `
|
|
317
|
+
Right now you just mention `attribute-money`. Make it a full section:
|
|
318
318
|
|
|
319
319
|
- How to add gem.
|
|
320
320
|
- Example migration / attribute definition (even if in the other repo, mirror one snippet here).
|
|
@@ -253,7 +253,7 @@ Multi-PR epic:
|
|
|
253
253
|
1. `Mint::Bank` interface with `#exchange(money, target)`.
|
|
254
254
|
2. `Mint::Bank::MemoryStore` (in-memory, good for tests).
|
|
255
255
|
3. `Mint::Bank::ECB` or `Mint::Bank::OpenExchangeRates` (network).
|
|
256
|
-
4. Update `
|
|
256
|
+
4. Update `attribute-money` to expose bank config in the Railtie.
|
|
257
257
|
|
|
258
258
|
### P2-3 Reek / RuboCop tightening
|
|
259
259
|
|
|
@@ -88,9 +88,11 @@ module Mint
|
|
|
88
88
|
#
|
|
89
89
|
# @param object [String, Currency, Money, nil] a currency code, object, or +nil+
|
|
90
90
|
# @return [Currency] the resolved Currency
|
|
91
|
-
# @raise [
|
|
91
|
+
# @raise [Mint::UnknownCurrency] if +object+ cannot be resolved into a
|
|
92
|
+
# registered currency. +Mint::UnknownCurrency+ inherits from +ArgumentError+,
|
|
93
|
+
# so existing +rescue ArgumentError+ handlers continue to work.
|
|
92
94
|
def Currency.resolve!(object)
|
|
93
|
-
resolve(object) or raise
|
|
95
|
+
resolve(object) or raise Mint::UnknownCurrency, "Could not resolve (#{object}) into a currency"
|
|
94
96
|
end
|
|
95
97
|
|
|
96
98
|
# Looks up a registered currency by its alpha code.
|
|
@@ -114,6 +116,6 @@ module Mint
|
|
|
114
116
|
#
|
|
115
117
|
# @param currency [String, Currency] a currency code or object
|
|
116
118
|
# @return [Money] a frozen zero-Money
|
|
117
|
-
# @raise [
|
|
119
|
+
# @raise [Mint::UnknownCurrency] if the currency can't be resolved
|
|
118
120
|
def Currency.zero(currency) = Registry.zero_for(Currency.resolve!(currency))
|
|
119
121
|
end
|
data/lib/minting/mint/aliases.rb
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# Optional top
|
|
4
|
-
#
|
|
5
|
-
|
|
6
|
-
#
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
#
|
|
10
|
-
|
|
3
|
+
# Optional top-level alias for Mint::Currency.
|
|
4
|
+
#
|
|
5
|
+
# Mint::Money is auto-bound as the top-level Money constant by
|
|
6
|
+
# `require 'minting'` (see lib/minting.rb). Currency is not auto-bound
|
|
7
|
+
# because application domain models are commonly named Currency (e.g. a
|
|
8
|
+
# Rails model). Require this file to opt in:
|
|
9
|
+
#
|
|
10
|
+
# require 'minting/mint/aliases'
|
|
11
|
+
#
|
|
12
|
+
if defined?(Currency) && Currency != Mint::Currency
|
|
13
|
+
warn "minting: top-level Currency is already defined (#{Currency}); skipping alias."
|
|
14
|
+
else
|
|
15
|
+
Currency = Mint::Currency unless defined?(Currency)
|
|
16
|
+
end
|
|
@@ -1,23 +1,21 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
#
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def reais = Mint::Money.from(self, 'BRL')
|
|
3
|
+
# Core extension: adds money-conversion helpers to Numeric.
|
|
4
|
+
class Numeric
|
|
5
|
+
# @return [Money] self interpreted as BRL
|
|
6
|
+
def reais = Mint::Money.from(self, 'BRL')
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
# @return [Money] self interpreted as USD
|
|
9
|
+
def dollars = Mint::Money.from(self, 'USD')
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
# @return [Money] self interpreted as EUR
|
|
12
|
+
def euros = Mint::Money.from(self, 'EUR')
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
# @param currency [String, Symbol, Currency] target currency
|
|
15
|
+
# @return [Money] self interpreted as the given currency
|
|
16
|
+
def to_money(currency) = Mint::Money.from(self, currency)
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
end
|
|
18
|
+
alias dollar dollars
|
|
19
|
+
alias euro euros
|
|
20
|
+
alias mint to_money
|
|
23
21
|
end
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
#
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def to_money(currency) = Mint::Money.from(to_r, currency)
|
|
11
|
-
end
|
|
3
|
+
# Core extension: adds money-parsing helper to String.
|
|
4
|
+
class String
|
|
5
|
+
# Parses self as a numeric string and creates a Money in the given currency.
|
|
6
|
+
#
|
|
7
|
+
# @param currency [String, Symbol, Currency] target currency
|
|
8
|
+
# @return [Money]
|
|
9
|
+
def to_money(currency = nil) = Mint::Money.parse(self, currency)
|
|
12
10
|
end
|
data/lib/minting/mint/i18n.rb
CHANGED
|
@@ -13,7 +13,7 @@ module Mint
|
|
|
13
13
|
# When set, +#to_formatted_s+ and +#format+ use these values as fallbacks when the
|
|
14
14
|
# corresponding parameter is not explicitly provided.
|
|
15
15
|
#
|
|
16
|
-
# @example Rails I18n integration (in
|
|
16
|
+
# @example Rails I18n integration (in attribute-money railtie)
|
|
17
17
|
# Mint.locale_backend = -> {
|
|
18
18
|
# fmt = I18n.t('number.currency.format')
|
|
19
19
|
# {
|
data/lib/minting/mint/mint.rb
CHANGED
|
@@ -2,8 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
# Mint currency registration and factory (public API)
|
|
4
4
|
module Mint
|
|
5
|
-
#
|
|
6
|
-
|
|
5
|
+
# Raised when a currency cannot be resolved from a code or object.
|
|
6
|
+
#
|
|
7
|
+
# Inherits from +ArgumentError+ so existing +rescue ArgumentError+ handlers
|
|
8
|
+
# continue to work; rescue +Mint::UnknownCurrency+ for the specific case.
|
|
9
|
+
class UnknownCurrency < ArgumentError
|
|
7
10
|
end
|
|
8
11
|
|
|
9
12
|
# Creates a new {Money} instance with the given amount and currency code.
|
|
@@ -11,7 +14,9 @@ module Mint
|
|
|
11
14
|
# @param amount [Numeric] the financial value
|
|
12
15
|
# @param currency_code [Currency, String] Currency code
|
|
13
16
|
# @return [Money] the instantiated Money object
|
|
14
|
-
# @raise [ArgumentError] if the
|
|
17
|
+
# @raise [ArgumentError] if the amount is not a Numeric
|
|
18
|
+
# @raise [Mint::UnknownCurrency] if the currency code is not registered.
|
|
19
|
+
# +Mint::UnknownCurrency+ inherits from +ArgumentError+.
|
|
15
20
|
def self.money(amount, currency_code) = Money.from(amount, currency_code)
|
|
16
21
|
|
|
17
22
|
# @return [Hash{String => Currency}] the frozen world-currencies hash
|
data/lib/minting/mint.rb
CHANGED
|
@@ -5,7 +5,6 @@ require_relative 'currency/currency'
|
|
|
5
5
|
require_relative 'mint/dsl/numeric'
|
|
6
6
|
require_relative 'mint/dsl/range'
|
|
7
7
|
require_relative 'mint/dsl/string'
|
|
8
|
-
require_relative 'mint/dsl/top_level'
|
|
9
8
|
require_relative 'mint/i18n'
|
|
10
9
|
require_relative 'mint/mint'
|
|
11
10
|
require_relative 'mint/parser/parser'
|
|
@@ -7,7 +7,8 @@ module Mint
|
|
|
7
7
|
# @param amount [Numeric] The monetary amount
|
|
8
8
|
# @param currency [Currency, String] The currency code or currency object
|
|
9
9
|
# @return [Money] the new Money instance
|
|
10
|
-
# @raise [ArgumentError] If amount is not numeric
|
|
10
|
+
# @raise [ArgumentError] If amount is not numeric
|
|
11
|
+
# @raise [Mint::UnknownCurrency] If currency cannot be resolved
|
|
11
12
|
# @example
|
|
12
13
|
# Money.from(10, 'USD') #=> [USD 10.00]
|
|
13
14
|
def self.from(amount, currency)
|
|
@@ -61,16 +62,9 @@ module Mint
|
|
|
61
62
|
#
|
|
62
63
|
# @param currency [String, Currency] a currency code or object
|
|
63
64
|
# @return [Money] a frozen zero-Money
|
|
64
|
-
# @raise [
|
|
65
|
+
# @raise [Mint::UnknownCurrency] if the currency can't be resolved
|
|
65
66
|
def self.zero(currency) = Currency.resolve!(currency).zero
|
|
66
67
|
|
|
67
|
-
# Backwards-compatible alias for previous API
|
|
68
|
-
# TODO: deprecate in a future major release
|
|
69
|
-
def self.create(amount, currency)
|
|
70
|
-
warn 'Money.create is now deprecated. Use Money.from'
|
|
71
|
-
from(amount, currency)
|
|
72
|
-
end
|
|
73
|
-
|
|
74
68
|
# Builds a Money from a subunit (smallest-unit) Integer amount.
|
|
75
69
|
# This is the inverse of {#subunits}: for USD, the subunit is
|
|
76
70
|
# 1 cent; for JPY it is 1 yen; for IQD it is 1 dinar (subunit 3).
|
|
@@ -79,8 +73,8 @@ module Mint
|
|
|
79
73
|
# smallest unit (e.g. cents). Must be an Integer to preserve exactness.
|
|
80
74
|
# @param currency [String, Symbol, Currency] the currency identifier
|
|
81
75
|
# @return [Money] the resulting Money instance
|
|
82
|
-
# @raise [ArgumentError] if +subunits+ is not an Integer
|
|
83
|
-
#
|
|
76
|
+
# @raise [ArgumentError] if +subunits+ is not an Integer
|
|
77
|
+
# @raise [Mint::UnknownCurrency] if +currency+ is not registered
|
|
84
78
|
#
|
|
85
79
|
# @example USD cents
|
|
86
80
|
# Money.from_subunits(123_456, 'USD') #=> [USD 1234.56]
|
data/lib/minting/version.rb
CHANGED
data/lib/minting.rb
CHANGED
|
@@ -2,3 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
require 'minting/mint'
|
|
4
4
|
require 'minting/version'
|
|
5
|
+
|
|
6
|
+
# By default, expose Mint::Money as the top-level Money constant for
|
|
7
|
+
# convenience. If Money is already defined (e.g. by the `money` gem), warn
|
|
8
|
+
# and skip so both libraries can coexist in the same process without
|
|
9
|
+
# corrupting either class.
|
|
10
|
+
if defined?(Money) && Money != Mint::Money
|
|
11
|
+
warn "minting: top-level Money is already defined (#{Money}); skipping auto-bind. Use Mint::Money."
|
|
12
|
+
else
|
|
13
|
+
Money = Mint::Money unless defined?(Money)
|
|
14
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: minting
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.9.
|
|
4
|
+
version: 1.9.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Gilson Ferraz
|
|
@@ -74,7 +74,6 @@ files:
|
|
|
74
74
|
- lib/minting/mint/dsl/numeric.rb
|
|
75
75
|
- lib/minting/mint/dsl/range.rb
|
|
76
76
|
- lib/minting/mint/dsl/string.rb
|
|
77
|
-
- lib/minting/mint/dsl/top_level.rb
|
|
78
77
|
- lib/minting/mint/i18n.rb
|
|
79
78
|
- lib/minting/mint/mint.rb
|
|
80
79
|
- lib/minting/mint/parser/parser.rb
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# Mint refinements
|
|
4
|
-
module Mint
|
|
5
|
-
# Registers top-level ::Money and ::Currency constants as aliases for Mint's classes.
|
|
6
|
-
#
|
|
7
|
-
# @raise [NameError] if ::Money or ::Currency are already defined and differ
|
|
8
|
-
def self.use_top_level_constants!
|
|
9
|
-
if !defined?(::Money) && !defined?(::Currency)
|
|
10
|
-
require 'minting/mint/aliases'
|
|
11
|
-
elsif ::Money == Mint::Money && ::Currency == Mint::Currency
|
|
12
|
-
warn 'Warning: Money and Currency already defined as Mint aliases, skipping'
|
|
13
|
-
else
|
|
14
|
-
raise NameError, 'Cannot define top-level Money or Currency constants: already defined'
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
end
|