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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f42e86d079045c4e58c7aee230b1faf32eadc6f6ff33c455f2cfb81fce2894c6
4
- data.tar.gz: a06f2900dfe2f743fead4ca7927fdc81b4f9e30e5a51accce428fc78a2315a5e
3
+ metadata.gz: 429ae46c67aa4b6bb032a9e9be85cbf02b2ee0576cce83c0ad4f36aa0c46e08c
4
+ data.tar.gz: a5a1c37ad5f6b8ced5e62323803431cd7385577c7a15963b0a29c92f7f7907b8
5
5
  SHA512:
6
- metadata.gz: 46c5191a5990bf2fec8ca67dcac3cab9fade07d6638b817cf91ce49df40dc63c0e1efbc22eabd776c48d7559912ec7ed82f9ea47d8c7915a5fb76fa9a3e85a9a
7
- data.tar.gz: bd11d6eab450a072a299949157ec18b3d23c9c4283fbd06180121a29c01ed1c953f9ba69aceaf0d4261c1438aa330ff0aa56a044a5e724e4b834c100524586dd
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 [minting-rails](https://github.com/gferraz/minting-rails) companion gem for drop-in ActiveRecord type casting, validators, and form helpers.
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').to_s(format: '%<integral>d dollars and %<fractional>02d cents')
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, Minting keeps everything namespaced under `Mint` to coexist nicely with other gems. If you prefer shorter constants, opt in:
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
- require "minting/dsl" # opt‑in top‑level Money / Currency
229
+
230
+ price = Money.from(10, "USD") # equivalent to Mint::Money.from
231
+ tax = Money.from(2.50, "USD")
235
232
  ```
236
233
 
237
- Or at runtime:
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
- Minting.use_top_level_constants!
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 constants in an initializer:
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/dsl"
247
+ require "minting/mint/aliases"
248
248
  ```
249
249
 
250
- After opting in:
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 `minting-rails` companion for clean Rails integration.
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 `minting-rails`. Make it a full section:
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 `minting-rails` to expose bank config in the Railtie.
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 [ArgumentError] if +object+ cannot be resolved into a registered currency
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 ArgumentError, "Could not resolve (#{object}) into a currency"
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 [ArgumentError] if the currency can't be resolved
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
@@ -1,10 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Optional toplevel aliases for application use.
4
- # Not required automatically.
5
-
6
- # Alias for {Mint::Money} — enables `Money.new(...)` shorthand.
7
- Money = Mint::Money
8
-
9
- # Alias for {Mint::Currency} — enables `Currency.new(...)` shorthand.
10
- Currency = Mint::Currency
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
- # Mint Numeric refinements
4
- module Mint
5
- refine Numeric do
6
- # @return [Money] self interpreted as BRL
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
- # @return [Money] self interpreted as USD
10
- def dollars = Mint::Money.from(self, 'USD')
8
+ # @return [Money] self interpreted as USD
9
+ def dollars = Mint::Money.from(self, 'USD')
11
10
 
12
- # @return [Money] self interpreted as EUR
13
- def euros = Mint::Money.from(self, 'EUR')
11
+ # @return [Money] self interpreted as EUR
12
+ def euros = Mint::Money.from(self, 'EUR')
14
13
 
15
- # @param currency [String, Symbol, Currency] target currency
16
- # @return [Money] self interpreted as the given currency
17
- def to_money(currency) = Mint::Money.from(self, currency)
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
- alias_method :dollar, :dollars
20
- alias_method :euro, :euros
21
- alias_method :mint, :to_money
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
- # Mint String refinement
4
- module Mint
5
- refine String do
6
- # Parses self as a numeric string and creates a Money in the given currency.
7
- #
8
- # @param currency [String, Symbol, Currency] target currency
9
- # @return [Money]
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
@@ -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 minting-rails railtie)
16
+ # @example Rails I18n integration (in attribute-money railtie)
17
17
  # Mint.locale_backend = -> {
18
18
  # fmt = I18n.t('number.currency.format')
19
19
  # {
@@ -2,8 +2,11 @@
2
2
 
3
3
  # Mint currency registration and factory (public API)
4
4
  module Mint
5
- # Unknown currency excpetion
6
- class UnknownCurrency < StandardError
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 currency code is not registered
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 or currency is invalid
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 [ArgumentError] if the currency can't be resolved
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 or +currency+
83
- # is not registered
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]
@@ -3,5 +3,5 @@
3
3
  # Root namespace for the Minting library.
4
4
  module Minting
5
5
  # Current version of the Minting gem.
6
- VERSION = '1.9.3'
6
+ VERSION = '1.9.5'
7
7
  end
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.3
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