Class: Mint::Currency
- Inherits:
-
Object
- Object
- Mint::Currency
- Defined in:
- lib/minting/currency/currency.rb,
lib/minting/currency/rounding.rb
Overview
:nodoc:
Constant Summary collapse
- VALID_ROUNDING_MODES =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
%i[up down even].freeze
- ROUNDING_THREAD_KEY =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
:minting_rounding_mode
Instance Attribute Summary collapse
-
#code ⇒ String
readonly
ISO 4217 currency code (e.g., "USD", "EUR").
-
#country ⇒ String?
readonly
Associated country code.
-
#disambiguate_symbol ⇒ String?
readonly
A longer, code-prefixed variant to distinguish currencies that share the same primary symbol (e.g. "US$" for USD, "C$" for CAD).
-
#fractional_multiplier ⇒ Integer
readonly
10^subunit, used for fractional conversions.
-
#minimum_amount ⇒ Rational
readonly
Smallest representable amount (1/fractional_multiplier).
-
#name ⇒ String?
readonly
Currency name.
-
#priority ⇒ Integer
readonly
Parser precedence for symbol detection.
-
#subunit ⇒ Integer
readonly
Number of decimal places (0 for JPY, 2 for USD, 3 for IQD).
-
#symbol ⇒ String?
readonly
Display symbol (e.g., "$", "€", "R$").
Class Method Summary collapse
-
.activate_custom_rounding! ⇒ Object
private
Activates the custom rounding dispatch path in #normalize_amount.
-
.crypto_currencies ⇒ Array<Currency>
Returns the list of built-in crypto currency definitions.
-
.current_rounding_mode ⇒ Symbol
private
Returns the currently active rounding mode, falling back to
:up. -
.custom_rounding_active? ⇒ Boolean
private
Whether a custom rounding mode has been activated.
-
.for_code(code) ⇒ Currency?
Looks up a registered currency by its alpha code.
-
.for_symbol(symbol) ⇒ Currency?
Looks up a currency by its display symbol.
-
.register(code:, subunit: 0, symbol: '', priority: 0) ⇒ Currency
Registers a new currency, raising a KeyError if already registered.
-
.register_all_crypto ⇒ Array<Currency>
Registers all built-in crypto currencies at once.
-
.register_crypto ⇒ Array<Currency>
Registers one or more crypto currencies into the shared currency registry.
-
.registered_currencies ⇒ Hash{String => Currency}
Returns all registered currencies as a frozen hash keyed by ISO code.
-
.resolve(object) ⇒ Currency?
Resolves an object into a Currency, returning
nilwhen it can't. -
.resolve!(object) ⇒ Currency
Resolves an object into a Currency, raising on failure.
-
.rounding_mode(mode) { ... } ⇒ Object
private
Sets a rounding mode for the duration of a block, restoring the previous mode on exit (even on exception).
-
.world_currencies ⇒ Hash{String => Currency}
private
Returns the frozen hash of all built-in ISO 4217 world currencies.
-
.zero(currency) ⇒ Money
Returns a zero Money in the given currency, useful as a default value for discounts, totals, or placeholders.
Instance Method Summary collapse
-
#==(other) ⇒ Object
Two Currency objects are equal if they share the same ISO code.
-
#dsymbol ⇒ String?
Disambiguate_symbol or code/symbol fallback.
-
#eql?(other) ⇒ Boolean
Currency identity is by code — two objects with the same code are
eql?regardless of other attributes. -
#hash ⇒ Integer
Stable hash based on currency code.
-
#initialize(code:, symbol:, subunit: 0, priority: 0, country: nil, name: nil, disambiguate_symbol: nil) ⇒ Currency
constructor
A new instance of Currency.
-
#inspect ⇒ String
Debug representation.
-
#normalize_amount(amount) ⇒ Rational
Normalizes a numeric amount for this currency.
-
#zero ⇒ Money
Returns the cached frozen zero-Money for this currency.
Constructor Details
#initialize(code:, symbol:, subunit: 0, priority: 0, country: nil, name: nil, disambiguate_symbol: nil) ⇒ Currency
Returns a new instance of Currency.
49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/minting/currency/currency.rb', line 49 def initialize(code:, symbol:, subunit: 0, priority: 0, country: nil, name: nil, disambiguate_symbol: nil) @code = code @country = country @name = name @priority = priority.to_i @subunit = subunit.to_i @symbol = symbol.nil? || symbol.empty? ? nil : symbol @fractional_multiplier = 10**@subunit @minimum_amount = Rational(1, @fractional_multiplier) @disambiguate_symbol = [code, @symbol].include?(disambiguate_symbol) ? nil : disambiguate_symbol freeze end |
Instance Attribute Details
#code ⇒ String (readonly)
Returns ISO 4217 currency code (e.g., "USD", "EUR").
16 17 18 |
# File 'lib/minting/currency/currency.rb', line 16 def code @code end |
#country ⇒ String? (readonly)
Returns Associated country code.
19 20 21 |
# File 'lib/minting/currency/currency.rb', line 19 def country @country end |
#disambiguate_symbol ⇒ String? (readonly)
Returns A longer, code-prefixed variant to distinguish currencies that share the same primary symbol (e.g. "US$" for USD, "C$" for CAD).
23 24 25 |
# File 'lib/minting/currency/currency.rb', line 23 def disambiguate_symbol @disambiguate_symbol end |
#fractional_multiplier ⇒ Integer (readonly)
Returns 10^subunit, used for fractional conversions.
26 27 28 |
# File 'lib/minting/currency/currency.rb', line 26 def fractional_multiplier @fractional_multiplier end |
#minimum_amount ⇒ Rational (readonly)
Returns Smallest representable amount (1/fractional_multiplier).
29 30 31 |
# File 'lib/minting/currency/currency.rb', line 29 def minimum_amount @minimum_amount end |
#name ⇒ String? (readonly)
Returns Currency name.
32 33 34 |
# File 'lib/minting/currency/currency.rb', line 32 def name @name end |
#priority ⇒ Integer (readonly)
Returns Parser precedence for symbol detection.
35 36 37 |
# File 'lib/minting/currency/currency.rb', line 35 def priority @priority end |
#subunit ⇒ Integer (readonly)
Returns Number of decimal places (0 for JPY, 2 for USD, 3 for IQD).
38 39 40 |
# File 'lib/minting/currency/currency.rb', line 38 def subunit @subunit end |
#symbol ⇒ String? (readonly)
Returns Display symbol (e.g., "$", "€", "R$").
41 42 43 |
# File 'lib/minting/currency/currency.rb', line 41 def symbol @symbol end |
Class Method Details
.activate_custom_rounding! ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Activates the custom rounding dispatch path in #normalize_amount. Once called, this cannot be reversed for the lifetime of the process.
20 |
# File 'lib/minting/currency/rounding.rb', line 20 def self.activate_custom_rounding! = @custom_rounding_active = true |
.crypto_currencies ⇒ Array<Currency>
Returns the list of built-in crypto currency definitions.
These are not registered by default — call register_crypto to opt in.
15 |
# File 'lib/minting/currency/registry.rb', line 15 def Currency.crypto_currencies = Registry.crypto_currencies |
.current_rounding_mode ⇒ Symbol
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns the currently active rounding mode, falling back to :up.
25 26 27 |
# File 'lib/minting/currency/rounding.rb', line 25 def self.current_rounding_mode Thread.current[ROUNDING_THREAD_KEY] || :up end |
.custom_rounding_active? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns whether a custom rounding mode has been activated.
15 |
# File 'lib/minting/currency/rounding.rb', line 15 def self.custom_rounding_active? = @custom_rounding_active |
.for_code(code) ⇒ Currency?
Looks up a registered currency by its alpha code.
21 |
# File 'lib/minting/currency/registry.rb', line 21 def Currency.for_code(code) = Registry.currencies[code] |
.for_symbol(symbol) ⇒ Currency?
Looks up a currency by its display symbol.
27 |
# File 'lib/minting/currency/registry.rb', line 27 def Currency.for_symbol(symbol) = Registry.currency_for_symbol(symbol) |
.register(code:, subunit: 0, symbol: '', priority: 0) ⇒ Currency
Registers a new currency, raising a KeyError if already registered.
38 39 40 |
# File 'lib/minting/currency/registry.rb', line 38 def Currency.register(code:, subunit: 0, symbol: '', priority: 0) Registry.register(code:, subunit:, symbol:, priority:) end |
.register_all_crypto ⇒ Array<Currency>
Registers all built-in crypto currencies at once.
Raises on the first duplicate — call rescue if idempotency is needed.
48 |
# File 'lib/minting/currency/registry.rb', line 48 def Currency.register_all_crypto = Registry.register_all_crypto |
.register_crypto ⇒ Array<Currency>
Registers one or more crypto currencies into the shared currency registry.
Raises on duplicate registration or unknown code — use rescue if
idempotent bulk registration is needed.
59 |
# File 'lib/minting/currency/registry.rb', line 59 def Currency.register_crypto(...) = Registry.register_crypto(...) |
.registered_currencies ⇒ Hash{String => Currency}
Returns all registered currencies as a frozen hash keyed by ISO code.
68 |
# File 'lib/minting/currency/registry.rb', line 68 def Currency.registered_currencies = Registry.currencies |
.resolve(object) ⇒ Currency?
Resolves an object into a Mint::Currency, returning nil when it can't.
Accepts nil, String, Mint::Currency, Money, or any object implementing
#to_currency (must return Mint::Currency) or #currency_code (must return String).
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/minting/currency/registry.rb', line 81 def Currency.resolve(object) case object when NilClass then nil when Currency then object when Money then object.currency when String then Currency.for_code object else if object.respond_to?(:to_currency) result = object.to_currency unless result.is_a?(Currency) raise ArgumentError, "#to_currency must return a [Money::Currency], got #{result.class}" end result elsif object.respond_to?(:currency_code) result = object.currency_code raise ArgumentError, "#currency_code must return a [String], got #{result.class}" unless result.is_a?(String) Currency.for_code result else raise ArgumentError, "currency must be [Money::Currency], [Money], [String] or nil (#{object})" end end end |
.resolve!(object) ⇒ Currency
Resolves an object into a Mint::Currency, raising on failure.
Like resolve but raises when the result would be nil.
115 116 117 |
# File 'lib/minting/currency/registry.rb', line 115 def Currency.resolve!(object) resolve(object) or raise Mint::UnknownCurrency, "Could not resolve (#{object}) into a currency" end |
.rounding_mode(mode) { ... } ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Sets a rounding mode for the duration of a block, restoring the previous mode on exit (even on exception).
35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/minting/currency/rounding.rb', line 35 def self.rounding_mode(mode) unless VALID_ROUNDING_MODES.include?(mode) raise ArgumentError, "Unknown rounding mode: #{mode} (expected :up, :down, or :even)" end prev = Thread.current[ROUNDING_THREAD_KEY] Thread.current[ROUNDING_THREAD_KEY] = mode yield ensure Thread.current[ROUNDING_THREAD_KEY] = prev end |
.world_currencies ⇒ Hash{String => Currency}
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns the frozen hash of all built-in ISO 4217 world currencies.
133 |
# File 'lib/minting/currency/registry.rb', line 133 def Currency.world_currencies = Registry.world_currencies |
Instance Method Details
#==(other) ⇒ Object
Two Currency objects are equal if they share the same ISO code.
65 |
# File 'lib/minting/currency/currency.rb', line 65 def ==(other) = other.is_a?(self.class) && code == other.code |
#dsymbol ⇒ String?
Returns disambiguate_symbol or code/symbol fallback.
68 |
# File 'lib/minting/currency/currency.rb', line 68 def dsymbol = disambiguate_symbol || (Registry.symbol_shared?(symbol) ? code : symbol) |
#eql?(other) ⇒ Boolean
Currency identity is by code — two objects with the same code are eql?
regardless of other attributes. This makes Currency usable as a Hash key
where lookup is by currency identity (ISO code).
73 |
# File 'lib/minting/currency/currency.rb', line 73 def eql?(other) = other.is_a?(Currency) && code == other.code |
#hash ⇒ Integer
Returns stable hash based on currency code.
76 |
# File 'lib/minting/currency/currency.rb', line 76 def hash = code.hash |
#inspect ⇒ String
Returns debug representation.
79 |
# File 'lib/minting/currency/currency.rb', line 79 def inspect = "<Currency:(#{code} #{symbol} #{subunit} #{name})>" |
#normalize_amount(amount) ⇒ Rational
Normalizes a numeric amount for this currency.
92 93 94 95 96 97 98 |
# File 'lib/minting/currency/currency.rb', line 92 def normalize_amount(amount) if Currency.custom_rounding_active? amount.to_r.round(subunit, half: Thread.current[Currency::ROUNDING_THREAD_KEY]) else amount.to_r.round(subunit) end end |