minting 1.7.2 → 1.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +16 -1
  3. data/doc/Mint/Currency.html +285 -31
  4. data/doc/Mint/Money.html +79 -56
  5. data/doc/Mint/RangeStepPatch.html +1 -1
  6. data/doc/Mint/Registry.html +842 -0
  7. data/doc/Mint/UnknownCurrency.html +1 -1
  8. data/doc/Mint.html +345 -51
  9. data/doc/Minting.html +2 -2
  10. data/doc/_index.html +8 -8
  11. data/doc/agents/api_review-2026-06-15.md +342 -0
  12. data/doc/class_list.html +1 -1
  13. data/doc/file.README.html +13 -2
  14. data/doc/index.html +13 -2
  15. data/doc/method_list.html +100 -36
  16. data/doc/top-level-namespace.html +1 -1
  17. data/lib/minting/currency/currency.rb +31 -0
  18. data/lib/minting/mint/locale_backend.rb +29 -0
  19. data/lib/minting/mint/mint.rb +23 -21
  20. data/lib/minting/mint/parser/parser.rb +3 -7
  21. data/lib/minting/mint/registry/registration.rb +33 -0
  22. data/lib/minting/mint/registry/registry.rb +38 -0
  23. data/lib/minting/mint/registry/symbols.rb +49 -0
  24. data/lib/minting/mint/registry/zeros.rb +18 -0
  25. data/lib/minting/mint.rb +13 -25
  26. data/lib/minting/money/constructors.rb +6 -11
  27. data/lib/minting/money/format/formatting.rb +16 -0
  28. data/lib/minting/money/format/to_s.rb +13 -4
  29. data/lib/minting/money/money.rb +12 -0
  30. data/lib/minting/version.rb +1 -1
  31. metadata +13 -8
  32. data/lib/minting/currency/currency_registry.rb +0 -67
  33. data/lib/minting/currency/world_currencies.rb +0 -16
  34. /data/doc/agents/{AGENTS.md → expired/AGENTS.md} +0 -0
  35. /data/doc/agents/{copilot-instructions.md → expired/copilot-instructions.md} +0 -0
  36. /data/doc/agents/{gemini_gem_evaluation.md → expired/gemini_gem_evaluation.md} +0 -0
  37. /data/doc/agents/{recommendations.md → expired/recommendations.md} +0 -0
  38. /data/doc/agents/{rubocop-issues.md → expired/rubocop-issues.md} +0 -0
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mint
4
+ # :nodoc:
5
+ module Registry
6
+ # Returns the cached zero-Money for a currency, creating it if needed.
7
+ #
8
+ # @param currency [Currency] the currency object
9
+ # @return [Money] a frozen zero-Money
10
+ # @api private
11
+ def self.zero_for(currency)
12
+ MUTEX.synchronize do
13
+ @zeros ||= {}
14
+ @zeros[currency] ||= Mint::Money.send(:new, 0, currency)
15
+ end
16
+ end
17
+ end
18
+ end
data/lib/minting/mint.rb CHANGED
@@ -1,27 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'minting/currency/currency'
4
- require 'minting/currency/currency_registry'
5
- require 'minting/currency/world_currencies'
6
-
7
- require 'minting/mint/dsl/numeric'
8
- require 'minting/mint/dsl/range'
9
- require 'minting/mint/dsl/string'
10
- require 'minting/mint/dsl/top_level'
11
-
12
- require 'minting/mint/mint'
13
- require 'minting/mint/parser/parser'
14
- require 'minting/mint/parser/separators'
15
-
16
- require 'minting/money/allocation/allocation'
17
- require 'minting/money/allocation/split'
18
- require 'minting/money/arithmetics/methods'
19
- require 'minting/money/arithmetics/operators'
20
- require 'minting/money/clamp'
21
- require 'minting/money/coercion'
22
- require 'minting/money/comparable'
23
- require 'minting/money/constructors'
24
- require 'minting/money/conversion'
25
- require 'minting/money/format/formatting'
26
- require 'minting/money/format/to_s'
27
- require 'minting/money/money'
3
+ require_relative 'currency/currency'
4
+
5
+ require_relative 'mint/dsl/numeric'
6
+ require_relative 'mint/dsl/range'
7
+ require_relative 'mint/dsl/string'
8
+ require_relative 'mint/dsl/top_level'
9
+ require_relative 'mint/locale_backend'
10
+ require_relative 'mint/mint'
11
+ require_relative 'mint/parser/parser'
12
+ require_relative 'mint/parser/separators'
13
+ require_relative 'mint/registry/registry'
14
+
15
+ require_relative 'money/money'
@@ -10,12 +10,10 @@ module Mint
10
10
  def self.create(amount, currency)
11
11
  raise ArgumentError, 'amount must be Numeric' unless amount.is_a?(Numeric)
12
12
 
13
- checked_currency = Mint.currency(currency)
14
- raise ArgumentError, "Currency not found (#{currency})" unless checked_currency
13
+ currency = Currency.resolve!(currency)
14
+ amount = currency.normalize_amount(amount)
15
15
 
16
- amount = checked_currency.normalize_amount(amount)
17
-
18
- amount.zero? ? Mint.zero(checked_currency) : new(amount, checked_currency)
16
+ amount.zero? ? Mint.zero(currency) : new(amount, currency)
19
17
  end
20
18
 
21
19
  # Builds a Money from a fractional (smallest-unit) Integer amount.
@@ -39,12 +37,9 @@ module Mint
39
37
  def self.from_fractional(fractional, currency)
40
38
  raise ArgumentError, 'fractional must be an Integer' unless fractional.is_a?(Integer)
41
39
 
42
- checked_currency = Mint.currency(currency)
43
- raise ArgumentError, "Currency not found (#{currency})" unless checked_currency
44
-
45
- amount = Rational(fractional, checked_currency.fractional_multiplier)
46
-
47
- amount.zero? ? Mint.zero(checked_currency) : new(amount, checked_currency)
40
+ currency = Currency.resolve!(currency)
41
+ amount = Rational(fractional, currency.fractional_multiplier)
42
+ amount.zero? ? Mint.zero(currency) : new(amount, currency)
48
43
  end
49
44
 
50
45
  # Returns a new Money object with the specified amount, or self if unchanged.
@@ -5,6 +5,22 @@ module Mint
5
5
  class Money
6
6
  private
7
7
 
8
+ # Resolves format/decimal/thousand from locale_backend when not explicitly given.
9
+ # @private
10
+ def resolve_locale_for(format, decimal, thousand)
11
+ locale = locale_backend
12
+ [format || locale[:format] || '%<symbol>s%<amount>f',
13
+ decimal || locale[:decimal] || '.',
14
+ thousand || locale[:thousand] || ',']
15
+ end
16
+
17
+ def locale_backend
18
+ bk = Mint.locale_backend
19
+ return {} unless bk.respond_to?(:call)
20
+
21
+ bk.call
22
+ end
23
+
8
24
  # Selects the appropriate format template and value based on the amount's sign.
9
25
  # @private
10
26
  def select_format(format)
@@ -5,7 +5,7 @@ module Mint
5
5
  class Money
6
6
  # Formats money as a string with customizable format, thousand delimiter, and decimal
7
7
  #
8
- # @param format [String, Hash] Either a Format string with placeholders
8
+ # @param format [String, Hash, nil] Either a Format string with placeholders
9
9
  # (%<symbol>s, %<amount>f, %<currency>s), or a Hash with per-sign keys
10
10
  # (:positive, :negative, :zero) each holding a format string. A Hash
11
11
  # is convenient for sign-aware formats such as accounting parentheses:
@@ -15,8 +15,12 @@ module Mint
15
15
  # Missing keys fall back to the module default, so a Hash with only
16
16
  # :negative will still format positives sensibly. The valid keys are
17
17
  # :positive, :negative, :zero; anything else raises ArgumentError.
18
- # @param thousand [String, false] Thousands delimiter (e.g., ',' for 1,000)
19
- # @param decimal [String] Decimal separator (e.g., '.' or ',')
18
+ # When +nil+, falls back to +Mint.locale_backend+ if set, otherwise
19
+ # +"%<symbol>s%<amount>f"+.
20
+ # @param thousand [String, false, nil] Thousands delimiter (e.g., ',' for 1,000).
21
+ # When +nil+, falls back to +Mint.locale_backend+ if set, otherwise +","+.
22
+ # @param decimal [String, nil] Decimal separator (e.g., '.' or ',').
23
+ # When +nil+, falls back to +Mint.locale_backend+ if set, otherwise +"."+.
20
24
  # @return [String] Formatted money string
21
25
  #
22
26
  # @raise [ArgumentError] if +format+ is not a String or Hash, the Hash
@@ -43,7 +47,12 @@ module Mint
43
47
  # money.to_s(format: '%<amount>10.2f') #=> " 1234.56"
44
48
  # money.to_s(format: '%<symbol>s%<amount>010.2f') #=> "$0001234.56"
45
49
  #
46
- def to_s(format: '%<symbol>s%<amount>f', decimal: '.', thousand: ',', width: nil)
50
+ # @example Locale-aware formatting (with Mint.locale_backend set)
51
+ # money.to_s # decimal and thousand come from locale_backend
52
+ #
53
+ def to_s(format: nil, decimal: nil, thousand: nil, width: nil)
54
+ format, decimal, thousand = resolve_locale_for(format, decimal, thousand)
55
+
47
56
  case format
48
57
  when {}, '' then raise ArgumentError, 'format must not be empty'
49
58
  when Hash then validate_format_hash(format)
@@ -1,5 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'allocation/allocation'
4
+ require_relative 'allocation/split'
5
+ require_relative 'arithmetics/methods'
6
+ require_relative 'arithmetics/operators'
7
+ require_relative 'clamp'
8
+ require_relative 'coercion'
9
+ require_relative 'comparable'
10
+ require_relative 'constructors'
11
+ require_relative 'conversion'
12
+ require_relative 'format/formatting'
13
+ require_relative 'format/to_s'
14
+
3
15
  module Mint
4
16
  # Money constructors
5
17
  class Money
@@ -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.7.2'
6
+ VERSION = '1.7.3'
7
7
  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.7.2
4
+ version: 1.7.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gilson Ferraz
@@ -41,14 +41,16 @@ files:
41
41
  - doc/Mint/CurrencyRegistry.html
42
42
  - doc/Mint/Money.html
43
43
  - doc/Mint/RangeStepPatch.html
44
+ - doc/Mint/Registry.html
44
45
  - doc/Mint/UnknownCurrency.html
45
46
  - doc/Minting.html
46
47
  - doc/_index.html
47
- - doc/agents/AGENTS.md
48
- - doc/agents/copilot-instructions.md
49
- - doc/agents/gemini_gem_evaluation.md
50
- - doc/agents/recommendations.md
51
- - doc/agents/rubocop-issues.md
48
+ - doc/agents/api_review-2026-06-15.md
49
+ - doc/agents/expired/AGENTS.md
50
+ - doc/agents/expired/copilot-instructions.md
51
+ - doc/agents/expired/gemini_gem_evaluation.md
52
+ - doc/agents/expired/recommendations.md
53
+ - doc/agents/expired/rubocop-issues.md
52
54
  - doc/class_list.html
53
55
  - doc/css/common.css
54
56
  - doc/css/full_list.css
@@ -64,8 +66,6 @@ files:
64
66
  - doc/top-level-namespace.html
65
67
  - lib/minting.rb
66
68
  - lib/minting/currency/currency.rb
67
- - lib/minting/currency/currency_registry.rb
68
- - lib/minting/currency/world_currencies.rb
69
69
  - lib/minting/data/world-currencies.yaml
70
70
  - lib/minting/mint.rb
71
71
  - lib/minting/mint/aliases.rb
@@ -73,9 +73,14 @@ files:
73
73
  - lib/minting/mint/dsl/range.rb
74
74
  - lib/minting/mint/dsl/string.rb
75
75
  - lib/minting/mint/dsl/top_level.rb
76
+ - lib/minting/mint/locale_backend.rb
76
77
  - lib/minting/mint/mint.rb
77
78
  - lib/minting/mint/parser/parser.rb
78
79
  - lib/minting/mint/parser/separators.rb
80
+ - lib/minting/mint/registry/registration.rb
81
+ - lib/minting/mint/registry/registry.rb
82
+ - lib/minting/mint/registry/symbols.rb
83
+ - lib/minting/mint/registry/zeros.rb
79
84
  - lib/minting/money/allocation/allocation.rb
80
85
  - lib/minting/money/allocation/split.rb
81
86
  - lib/minting/money/arithmetics/methods.rb
@@ -1,67 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'yaml'
4
-
5
- # Mint currency store (internal)
6
- module Mint
7
- # Internal currency registry
8
- # Manages the registry cache and currency symbol lookups.
9
- module CurrencyRegistry
10
- extend self
11
-
12
- # Returns the hash of all registered currencies.
13
- #
14
- # @return [Hash{String => Currency}] registered currencies mapped by code
15
- # @api private
16
- def currencies
17
- @currencies ||= Mint.world_currencies.dup
18
- end
19
-
20
- # Registered symbols sorted for detection: longest match wins, then parser priority.
21
- #
22
- # @return [Array<Array<String, Currency>>] sorted symbol-to-currency mappings
23
- # @api private
24
- def currency_symbols
25
- @currency_symbols ||= begin
26
- currencies.values
27
- .reject { |c| c.symbol.empty? }
28
- .map { |currency| [currency.symbol, currency] }
29
- .sort_by { |symbol, currency| [-symbol.length, -currency.priority] }
30
- end.freeze
31
- end
32
-
33
- # Registers a new currency, raising a KeyError if already registered.
34
- #
35
- # @param code [String] the unique currency code
36
- # @param subunit [Integer] the decimal subunit precision, defaults to 0
37
- # @param symbol [String] the display symbol
38
- # @param priority [Integer] parser precedence priority
39
- # @return [Currency] the newly registered Currency instance
40
- # @raise [ArgumentError] if the code contains invalid characters
41
- # @raise [KeyError] if the currency code is already registered
42
- def register(code:, subunit: 0, symbol: '', priority: 0)
43
- raise ArgumentError, 'Currency code must be String' unless code.is_a? String
44
- unless code.match?(/^[A-Z_]+$/)
45
- raise ArgumentError,
46
- "Currency code must have only letters or '_' ('USD',, 'MY_COIN')"
47
- end
48
-
49
- currencies = CurrencyRegistry.currencies
50
- raise KeyError, "Currency: #{code} already registered" if currencies[code]
51
-
52
- currency = currencies[code] = Currency.new(code:, subunit:, symbol:, priority:)
53
- invalidate_symbols_cache
54
- currency
55
- end
56
-
57
- private
58
-
59
- # Clears and refreshes the currency symbol cache.
60
- # Called when currencies are registered.
61
- #
62
- # @api private
63
- def invalidate_symbols_cache
64
- @currency_symbols = nil
65
- end
66
- end
67
- end
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Mint list of world currencies
4
- module Mint
5
- # Loads ISO world currencies from YAML file into the registry.
6
- #
7
- # @return [Hash{String => Currency}] ISO-4217 world currencies mapped by code
8
- # @api private
9
- def self.world_currencies
10
- @world_currencies ||= begin
11
- path = File.join(File.expand_path('../data', __dir__), 'world-currencies.yaml')
12
-
13
- YAML.load_file(path).to_h { |entry| [entry['code'], Currency.new(**entry.transform_keys(&:to_sym))] }
14
- end.freeze
15
- end
16
- end
File without changes