Class: Mint::Money

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/minting/money/clamp.rb,
lib/minting/money/money.rb,
lib/minting/money/parse.rb,
lib/minting/money/coercion.rb,
lib/minting/money/rounding.rb,
lib/minting/money/comparable.rb,
lib/minting/money/conversion.rb,
lib/minting/money/format/to_s.rb,
lib/minting/money/constructors.rb,
lib/minting/money/format/format.rb,
lib/minting/money/allocation/split.rb,
lib/minting/money/format/formatter.rb,
lib/minting/money/format/validator.rb,
lib/minting/money/arithmetics/methods.rb,
lib/minting/money/allocation/allocation.rb,
lib/minting/money/arithmetics/operators.rb

Overview

:nodoc:

Defined Under Namespace

Modules: FormatterValidator Classes: Formatter

Constant Summary collapse

Currency =

Money::Currency is the canonical way to access Currency class

Mint::Currency
DEFAULT_FORMAT =

The default display format pattern for formatting monetary values. Uses %<symbol>s for the currency symbol and %<amount>f for the rounded amount.

'%<symbol>s%<amount>f'
THOUSAND_RE =

Match a digit followed by groups of 3 digits until end of string — inserts thousand separators.

/(\d)(?=(\d{3})+\z)/

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#amountObject (readonly)

Returns the value of attribute amount.



24
25
26
# File 'lib/minting/money/money.rb', line 24

def amount
  @amount
end

#currencyObject (readonly)

Returns the value of attribute currency.



24
25
26
# File 'lib/minting/money/money.rb', line 24

def currency
  @currency
end

Class Method Details

.from(amount, currency) ⇒ Money

Creates a new Money immutable object with the specified amount and currency

Examples:

Money.from(10, 'USD')  #=> [USD 10.00]

Parameters:

  • amount (Numeric)

    The monetary amount

  • currency (Currency, String)

    The currency code or currency object

Returns:

  • (Money)

    the new Money instance

Raises:

  • (ArgumentError)

    If amount is not numeric

  • (Mint::UnknownCurrency)

    If currency cannot be resolved



14
15
16
17
18
19
20
21
# File 'lib/minting/money/constructors.rb', line 14

def self.from(amount, currency)
  raise ArgumentError, 'amount must be Numeric' unless amount.is_a?(Numeric)

  currency = Currency.resolve!(currency)
  amount = currency.normalize_amount(amount)

  amount.zero? ? currency.zero : new(amount, currency)
end

.from_hash(hash) ⇒ Money

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.

Deserializes a Hash into a Money instance.

Accepts both symbol and string keys, matching the output of #to_hash.

Examples:

Money.from_hash(currency: "USD", amount: "9.99")
#=> [USD 9.99]

Round-trip

m = Money.from(134120, "BRL")
Money.from_hash(m.to_hash) == m  #=> true

Parameters:

  • hash (Hash)

    a hash with :currency (or "currency") and :amount (or "amount") keys

Returns:

  • (Money)

    the deserialized Money instance

Raises:

  • (Mint::UnknownCurrency)

    if the currency can't be resolved

  • (ArgumentError)

    if amount is not parseable as a Rational



60
61
62
63
64
# File 'lib/minting/money/conversion.rb', line 60

def self.from_hash(hash)
  currency = Currency.resolve!(hash[:currency] || hash['currency'])
  amount = currency.normalize_amount(Rational(hash[:amount] || hash['amount']))
  amount.zero? ? currency.zero : new(amount, currency)
end

.from_subunits(subunits, currency) ⇒ Money

Builds a Money from a subunit (smallest-unit) Integer amount. This is the inverse of #subunits: for USD, the subunit is 1 cent; for JPY it is 1 yen; for IQD it is 1 dinar (subunit 3).

Examples:

USD cents

Money.from_subunits(123_456, 'USD') #=> [USD 1234.56]

JPY (subunit 0)

Money.from_subunits(1234, 'JPY')    #=> [JPY 1234]

Round trip

m = Money.from(9.99, 'USD')
Money.from_subunits(m.subunits, 'USD') == m #=> true

Parameters:

  • subunits (Integer)

    the amount expressed in the currency's smallest unit (e.g. cents). Must be an Integer to preserve exactness.

  • currency (String, Symbol, Currency)

    the currency identifier

Returns:

  • (Money)

    the resulting Money instance

Raises:

  • (ArgumentError)

    if subunits is not an Integer

  • (Mint::UnknownCurrency)

    if currency is not registered



59
60
61
62
63
64
65
# File 'lib/minting/money/constructors.rb', line 59

def self.from_subunits(subunits, currency)
  raise ArgumentError, 'subunits must be an Integer' unless subunits.is_a?(Integer)

  currency = Currency.resolve!(currency)
  amount = Rational(subunits, currency.fractional_multiplier)
  amount.zero? ? currency.zero : new(amount, currency)
end

.no_currency(amount) ⇒ Money

Creates a new Money without a currency (ISO 4217 XXX — "No Currency").

Examples:

Money.no_currency(100)  #=> [XXX 100]

Parameters:

  • amount (Numeric)

    The monetary amount

Returns:

  • (Money)

    a Money instance with the XXX currency

Raises:

  • (ArgumentError)

    If amount is not numeric



30
# File 'lib/minting/money/constructors.rb', line 30

def self.no_currency(amount) = from(amount, 'XXX')

.parse(input, currency = nil) ⇒ Money?

Parses a human-readable money string into a Mint::Money object.

Returns nil when the input is invalid or currency cannot be determined.

Examples:

With explicit currency

Money.parse('19.99', 'USD')    #=> [USD 19.99]
Money.parse('garbage', 'USD')  #=> nil

With symbol or code in the string

Money.parse('$19.99')            #=> [USD 19.99]
Money.parse('USD 1,234.56')    #=> [USD 1234.56]

Parameters:

  • input (String)

    Amount input, optionally including a currency symbol or code

  • currency (String, Symbol, Currency, nil) (defaults to: nil)

    ISO code when not present in input

Returns:



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/minting/money/parse.rb', line 21

def self.parse(input, currency = nil)
  return nil unless input.is_a?(String)

  input = input.strip
  return nil if input.empty?

  currency = parse_currency(input, currency)
  return nil unless currency

  amount = parse_amount(input)
  return nil unless amount

  amount = currency.normalize_amount(amount)
  new(amount, currency)
end

.parse!(input, currency = nil) ⇒ Money

Like parse but raises on failure.

Examples:

Money.parse!('19.99', 'USD')    #=> [USD 19.99]
Money.parse!('garbage', 'USD')  #=> ArgumentError

Parameters:

  • input (String)

    Amount input, optionally including a currency symbol or code

  • currency (String, Symbol, Currency, nil) (defaults to: nil)

    ISO code when not present in input

Returns:

Raises:

  • (ArgumentError)

    when input is invalid or currency cannot be determined



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/minting/money/parse.rb', line 47

def self.parse!(input, currency = nil)
  raise ArgumentError, 'input must be a String' unless input.is_a?(String)

  input = input.strip
  raise ArgumentError, 'input cannot be empty' if input.empty?

  currency = parse_currency(input, currency)
  raise ArgumentError, "Currency [#{currency}] not found" unless currency

  amount = parse_amount(input)
  raise ArgumentError, "Could not parse [#{input}]" unless amount

  amount = currency.normalize_amount(amount)
  new(amount, currency)
end

.with_rounding(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.

Executes a block with a specific rounding mode applied to all money construction, parsing, change, allocation, and split operations.

Restores the previous mode (or default) when the block exits, even on exception.

Rounding-mode support is activated on first call. Once activated, Currency#normalize_amount dispatches through Currency.rounding_mode, adding ~10–35&ns of overhead to every money creation or mutation. When rounding modes are never used (the common case), the fast path incurs zero overhead.

Parameters:

  • mode (Symbol)

    one of: :up, :down, :even

Yields:

  • block to execute with the rounding mode active

Raises:

  • (ArgumentError)

    if mode is not a recognised rounding mode



21
22
23
24
# File 'lib/minting/money/rounding.rb', line 21

def self.with_rounding(mode, &)
  Currency.activate_custom_rounding!
  Currency.rounding_mode(mode, &)
end

.zero(currency) ⇒ Money

Returns a frozen zero Money in the given currency.

Parameters:

Returns:

  • (Money)

    a frozen zero-Money

Raises:



39
# File 'lib/minting/money/constructors.rb', line 39

def self.zero(currency) = Currency.resolve!(currency).zero

Instance Method Details

#*(multiplicand) ⇒ Money

Performs multiplication of the monetary value by a standard scalar Numeric.

Parameters:

  • multiplicand (Numeric)

    the scalar multiplier

Returns:

  • (Money)

    the multiplied Money instance

Raises:

  • (TypeError)

    if multiplier is not Numeric or is a Money object



40
41
42
43
44
# File 'lib/minting/money/arithmetics/operators.rb', line 40

def *(multiplicand)
  raise TypeError, "#{self} can't be multiplied by #{multiplicand}" unless multiplicand.is_a?(Numeric)

  copy_with(amount: amount * multiplicand)
end

#**(exponent) ⇒ Money

Performs exponentiation of the monetary value by a standard scalar Numeric.

Parameters:

Returns:

  • (Money)

    reult of amount ** exponent

Raises:

  • (TypeError)

    if exponent is not Numeric



64
65
66
67
68
# File 'lib/minting/money/arithmetics/operators.rb', line 64

def **(exponent)
  return copy_with(amount: amount**exponent) if exponent.is_a?(Numeric)

  raise TypeError, "#{self} can't be powered by #{exponent}"
end

#+(addend) ⇒ Money

Performs addition with another Mint::Money instance or standard zero Numeric.

Parameters:

Returns:

  • (Money)

    the sum of the addition

Raises:

  • (TypeError)

    if addition involves a different currency or incompatible types



11
12
13
14
15
16
# File 'lib/minting/money/arithmetics/operators.rb', line 11

def +(addend)
  return self if addend == 0
  return copy_with(amount: amount + addend.amount) if addend.is_a?(Money) && currency == addend.currency

  raise TypeError, "#{addend} can't be added to #{self}"
end

#-(subtrahend) ⇒ Money

Performs subtraction with another Mint::Money instance or standard zero Numeric.

Parameters:

Returns:

  • (Money)

    the difference of the subtraction

Raises:

  • (TypeError)

    if subtraction involves a different currency or incompatible types



23
24
25
26
27
28
# File 'lib/minting/money/arithmetics/operators.rb', line 23

def -(subtrahend)
  return self if subtrahend == 0
  return copy_with(amount: amount - subtrahend.amount) if subtrahend.is_a?(Money) && currency == subtrahend.currency

  raise TypeError, "#{subtrahend} can't be subtracted from #{self}"
end

#-@Money

Unary negation operator. Returns a new Mint::Money instance with the inverted sign.

Returns:

  • (Money)

    negated Money instance



33
# File 'lib/minting/money/arithmetics/operators.rb', line 33

def -@ = copy_with(amount: -amount)

#/(divisor) ⇒ Money, Numeric

Performs division of the monetary value by a scalar Numeric or identical currency Mint::Money.

Parameters:

Returns:

  • (Money, Numeric)

    a new Money (scalar division) or a numeric ratio (Money division)

Raises:

  • (TypeError)

    if divisor is of incompatible type or different currency

  • (ZeroDivisionError)

    if division by zero is attempted



52
53
54
55
56
57
# File 'lib/minting/money/arithmetics/operators.rb', line 52

def /(divisor)
  return copy_with(amount: amount / divisor) if divisor.is_a? Numeric
  return amount / divisor.amount if divisor.is_a?(Money) && currency == divisor.currency

  raise TypeError, "#{self} can't be divided by #{divisor}"
end

#<=>(other) ⇒ 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.

Examples:

two_usd == Money.from(2r, 'USD') #=> [$ 2.00]
two_usd > 0                      #=> true
two_usd > Money.from(2, 'USD')   #=> false
two_usd > 1
=> TypeError: [$ 2.00] can't be compared to 1
two_usd > Money.from(2, 'BRL')
=> TypeError: [$ 2.00] can't be compared to [R$ 2.00]


36
37
38
39
40
41
42
# File 'lib/minting/money/comparable.rb', line 36

def <=>(other)
  case other
  in 0                                    then amount <=> other
  in Mint::Money if same_currency?(other) then amount <=> other.amount
  else                                    raise TypeError, "#{inspect} can't be compared to #{other.inspect}"
  end
end

#==(other) ⇒ 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.

Returns true if both are zero, or both have same amount and same currency.

Returns:

  • true if both are zero, or both have same amount and same currency



9
10
11
12
13
14
15
# File 'lib/minting/money/comparable.rb', line 9

def ==(other)
  case other
  when 0           then zero?
  when Mint::Money then amount == other.amount && currency == other.currency
  else                  false
  end
end

#absMoney

Returns the absolute value of the monetary amount as a new Mint::Money instance.

Returns:

  • (Money)

    the absolute value



9
# File 'lib/minting/money/arithmetics/methods.rb', line 9

def abs = copy_with(amount: amount.abs)

#allocate(proportions) ⇒ Array<Money>

Proportionally allocates the monetary amount among a list of ratios. Disperses any subunit rounding amounts across the initial slots

Examples:

Proportional allocation

money = Money.from(10.00, 'USD')
money.allocate([1, 2, 3]) #=> [[USD 1.67], [USD 3.33], [USD 5.00]]

Parameters:

  • proportions (Array<Numeric>)

    a list of numeric proportions/ratios to allocate by

Returns:

  • (Array<Money>)

    the list of newly allocated Money objects

Raises:

  • (ArgumentError)

    if the proportions list is empty or sums to zero



15
16
17
18
19
20
21
22
# File 'lib/minting/money/allocation/allocation.rb', line 15

def allocate(proportions)
  whole = proportions.sum.to_r
  raise ArgumentError, 'Need at least 1 proportion element' if proportions.empty?
  raise ArgumentError, 'Proportions total must not be zero' if whole.zero?

  amounts = proportions.map { |rate| currency.normalize_amount(amount * rate / whole) }
  allocate_left_over(amounts: amounts, left_over: amount - amounts.sum)
end

#clamp(min_or_range, max = nil) ⇒ Money

Constrains self to the inclusive range [+min+, +max+].

Bounds may be:

  • nil meaning no boundary
  • same-currency Mint::Money or Range
  • Numeric amount, or Range

Numeric is interpreted as an amount in +self+'s currency, so the common pricing idiom price.clamp(0, 100) reads as "0 to 100 in the same currency as +price+".

When self is already in range the receiver is returned (no new object allocated). When out of range, the nearest bound is returned as a new frozen Mint::Money in +self+'s currency.

Examples:

In range

Money.from(5, 'USD').clamp(0, 10) #=> [USD 5.00]  (returns self)

Out of range, with Numeric bounds

Money.from(50, 'USD').clamp(0, 10) #=> [USD 10.00]

Out of range, with Money bounds

loss  = Money.from(-5, 'USD')
floor = Money.from(0,  'USD')
ceil  = Money.from(10, 'USD')
loss.clamp(floor, ceil) #=> [USD 0.00]

Subunit-0 currency (JPY)

Money.from(500, 'JPY').clamp(0, 100) #=> [JPY 100]

Parameters:

  • min_or_range (Money, Numeric, Range, nil)

    lower bound (inclusive), or range

  • max (Money, Numeric, nil) (defaults to: nil)

    upper bound (inclusive)

Returns:

  • (Money)

    self if in range, otherwise the nearer bound

Raises:

  • (ArgumentError)

    if min or max is not a Money, Numeric or nil; if a Money operand has a different currency; if min > max; if min is a Range, and max is not nil



42
43
44
45
46
47
48
49
50
51
# File 'lib/minting/money/clamp.rb', line 42

def clamp(min_or_range, max = nil)
  if min_or_range.is_a?(Range)
    raise(ArgumentError, "Either amount range alone or two amounts accepted: #{max}") if max

    min, max = min_or_range.minmax
  else
    min = min_or_range
  end
  copy_with(amount: amount.clamp(normalize_boundary(min), normalize_boundary(max)))
end

#coerce(other) ⇒ Array(CoercedNumber, Money)

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.

Allows Mint::Money to interact seamlessly as the right-hand operand in Numeric arithmetic. This enables expressions like 5 * money where 5 is a Numeric and money is a Money object.

Examples:

price = Money.from(10, 'USD')
5 * price  #=> [USD 50.00] (via coercion)

Parameters:

  • other (Numeric)

    the left-hand operand to coerce

Returns:

  • (Array(CoercedNumber, Money))

    coerced operand array



14
15
16
# File 'lib/minting/money/coercion.rb', line 14

def coerce(other)
  [CoercedNumber.new(other), self]
end

#copy_with(amount:) ⇒ Money

Returns a new Money object with the specified amount, or self if unchanged. This is the primary method for creating a modified copy of a Money instance while preserving immutability.

Examples:

price = Money.from(10.00, 'USD')
price.copy_with(amount: 15.00)  #=> [USD 15.00]
price.copy_with(amount: 10.00)  #=> [USD 10.00] (returns self)

Parameters:

  • amount (Numeric)

    The new monetary amount

Returns:

  • (Money)

    A new Money object with the new amount, or self if the amount is unchanged



77
78
79
80
81
82
83
84
85
86
87
# File 'lib/minting/money/constructors.rb', line 77

def copy_with(amount:)
  amount = currency.normalize_amount(amount)

  if amount == self.amount
    self
  elsif amount.zero?
    currency.zero
  else
    Money.new(amount, currency)
  end
end

#currency_codeString

Returns the ISO 3-letter currency code string.

Examples:

Money.from(100, 'USD').currency_code  #=> "USD"

Returns:

  • (String)

    the ISO currency code (e.g., "USD", "EUR", "BRL")



34
# File 'lib/minting/money/money.rb', line 34

def currency_code = currency.code

#eql?(other) ⇒ 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.

Strict equality — both amount and currency must match exactly. Unlike ==, does not treat zero as equivalent across currencies.

Returns:

  • (Boolean)


21
22
23
24
25
# File 'lib/minting/money/comparable.rb', line 21

def eql?(other)
  other.is_a?(Mint::Money) &&
    amount == other.amount &&
    currency == other.currency
end

#format(template = nil, decimal: nil, thousand: nil, width: nil, locale: nil) ⇒ String Also known as: to_fs

Formats money as a string with a customizable template, thousand delimiter, and decimal separator.

Examples:

Basic formatting

money = Money.from(1234.56, 'USD')
money.format                               #=> "$1,234.56"
money.format(thousand: '.', decimal: ',')  #=> "$1.234,56"
money.format(decimal: ',', thousand: '')   #=> "$1234,56"

Custom templates

money.format('%<amount>f')                              #=> "1234.56"
money.format('%<currency>s %<amount>f')                 #=> "USD 1234.56"
money.format('%<amount>f %<symbol>s')                   #=> "1234.56 $"
money.format('%<symbol>s%<amount>+f')                   #=> "$+1234.56"

Integral & fractional parts

money.format('%<integral>d.%<fractional>02d')            #=> "1234.56"
price = Money.from(0.99, 'USD')
price.format('%<integral>d dollars and %<fractional>02d cents')
#=> "0 dollars and 99 cents"

Per-sign Hash format (accounting parentheses)

loss = Money.from(-1234.56, 'USD')
loss.format({ negative: '(%<symbol>s%<amount>f)' })      #=> "($1,234.56)"
Money.from(0, 'BRL').format({ zero: '--' })             #=> "--"

Padding and alignment

money.format('%<amount>10.2f')                          #=> "   1234.56"
money.format('%<symbol>s%<amount>010.2f')               #=> "$0001234.56"

Locale-aware formatting (with Mint.locale_backend set)

money.format                       # decimal and thousand come from locale_backend
money.format(locale: :en)          # locale passed to backend callable
money.format(locale: 'pt-BR')      # strings work too

Parameters:

  • template (String, Hash, nil) (defaults to: nil)

    Either a format string with placeholders (%s, %f, %s, %d, %d, %s), or a Hash with per-sign keys (:positive, :negative, :zero) each holding a format string. A Hash is convenient for sign-aware formats such as accounting parentheses:

    money.format({ negative: '(%<symbol>s%<amount>f)' })
    

    Missing keys fall back to the module default, so a Hash with only :negative will still format positives sensibly. The valid keys are :positive, :negative, :zero; anything else raises ArgumentError. When nil, falls back to Mint.locale_backend if set, otherwise "%<symbol>s%<amount>f".

  • thousand (String, false, nil) (defaults to: nil)

    Thousands delimiter (e.g., ',' for 1,000). When nil, falls back to Mint.locale_backend if set, otherwise ",".

  • decimal (String, nil) (defaults to: nil)

    Decimal separator (e.g., '.' or ','). When nil, falls back to Mint.locale_backend if set, otherwise ".".

  • locale (Symbol, String, nil) (defaults to: nil)

    Locale key passed to the Mint.locale_backend callable when resolving locale-aware separators and format. Ignored when Mint.locale_backend is a Hash or nil. Accepts symbols (+:en+, :'pt-BR') and strings (+"pt-BR"+), passed through as-is (matching Rails I18n.locale convention).

Returns:

  • (String)

    Formatted money string

Raises:

  • (ArgumentError)

    if template is not a String or Hash, the Hash is empty, or the Hash contains an unrecognised key.



68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/minting/money/format/format.rb', line 68

def format(template = nil, decimal: nil, thousand: nil, width: nil, locale: nil)
  template, decimal, thousand = resolve_format_options(template, decimal:, thousand:, locale:)

  case template
  when Hash # :noop - validated in Formatter.for
  when String then template = { positive: template }
  else        raise ArgumentError, 'Invalid template. Only String or Hash are accepted'
  end

  formatted = Formatter.for(template, decimal, thousand).format(self)

  width ? formatted.rjust(width) : formatted
end

#fractionalObject

Returns the fractional part of the amount.

Examples:

Money.from(1234.56, 'USD').fractional  #=> 56
Money.from(1000, 'JPY').fractional     #=> 0
Money.from(123.456, 'IQD').fractional  #=> 456


60
# File 'lib/minting/money/money.rb', line 60

def fractional = ((amount - amount.to_i) * currency.fractional_multiplier).to_i

#hashInteger

Generates a stable hash key for Money instances.

Returns:

  • (Integer)

    the calculated hash value



65
# File 'lib/minting/money/money.rb', line 65

def hash = [amount, currency_code].hash

#inspectString

Returns a standard developer-oriented string inspection of the Money object.

Returns:

  • (String)

    the formatted inspect representation



70
71
72
# File 'lib/minting/money/money.rb', line 70

def inspect
  Kernel.format "[#{currency_code} %0.#{currency.subunit}f]", amount
end

#integralObject Also known as: to_i

Returns the whole-unit (integral) part of the amount.

Examples:

Money.from(1234.56, 'USD').integral  #=> 1234
Money.from(1000, 'JPY').integral     #=> 1000
Money.from(-9.99, 'USD').integral    #=> -9


51
# File 'lib/minting/money/money.rb', line 51

def integral = amount.to_i

#negative?Boolean

Returns true if the monetary amount is less than zero.

Returns:

  • (Boolean)

    true if negative, false otherwise



14
# File 'lib/minting/money/arithmetics/methods.rb', line 14

def negative? = amount.negative?

#nonzero?self?

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 self if amount is non-zero, nil otherwise.

Returns:

  • (self, nil)

    self if amount is non-zero, nil otherwise



45
# File 'lib/minting/money/comparable.rb', line 45

def nonzero? = amount.nonzero?

#positive?Boolean

Returns true if the monetary amount is greater than zero.

Returns:

  • (Boolean)

    true if positive, false otherwise



19
# File 'lib/minting/money/arithmetics/methods.rb', line 19

def positive? = amount.positive?

#same_currency?(other) ⇒ 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.

Helper method to verify if another Money has the identical currency.

Parameters:

  • other (Money)

    the target currency to compare

Returns:

  • (Boolean)

    true if currencies match, false otherwise



51
# File 'lib/minting/money/comparable.rb', line 51

def same_currency?(other) = other.currency == currency

#split(slices) ⇒ Array<Money>

Splits the monetary amount into a given quantity of equal parts. Disperses any fractional subunit rounding differences across the initial slots so that the sum is preserved.

Examples:

Even split

money = Money.from(10.00, 'USD')
money.split(3) #=> [[USD 3.34], [USD 3.33], [USD 3.33]]

Parameters:

  • slices (Integer)

    the number of equal parts to divide the money into (must be > 0)

Returns:

  • (Array<Money>)

    the list of newly split Money objects

Raises:

  • (ArgumentError)

    if quantity is not a positive integer



17
18
19
20
21
22
23
# File 'lib/minting/money/allocation/split.rb', line 17

def split(slices)
  raise ArgumentError, 'Slices quantity must be a positive integer' unless slices.positive? && slices.integer?

  fraction = currency.normalize_amount(amount / slices)
  allocate_left_over(amounts: Array.new(slices, fraction),
                     left_over: amount - (fraction * slices))
end

#subunitsInteger

Returns the monetary amount expressed in the currency's smallest unit (fractional units). For example, cents for USD (subunit 2), yen for JPY (subunit 0), fils for IQD (subunit 3).

Examples:

Money.from(1234.56, 'USD').subunits  #=> 123456
Money.from(1000, 'JPY').subunits     #=> 1000
Money.from(123.456, 'IQD').subunits  #=> 123456

Returns:

  • (Integer)

    the amount in fractional units



44
# File 'lib/minting/money/money.rb', line 44

def subunits = (amount * currency.fractional_multiplier).to_i

#succMoney

Returns the successor of the Money instance by adding the minimum possible subunit amount. Enables standard ranges and stepping (e.g. 1.dollar..10.dollars).

Returns:

  • (Money)

    successor Money instance



25
# File 'lib/minting/money/arithmetics/methods.rb', line 25

def succ = copy_with(amount: amount + currency.minimum_amount)

#to_dBigDecimal

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.

Converts the monetary amount to a BigDecimal object.

Examples:

Money.from(9.99, 'USD').to_d  #=> 0.999e1

Returns:

  • (BigDecimal)

    the decimal representation of the money amount



15
# File 'lib/minting/money/conversion.rb', line 15

def to_d = amount.to_d 0

#to_fFloat

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.

Converts the monetary amount to a standard float. Note: Using float conversion loses precision guarantees.

Returns:

  • (Float)

    the floating-point representation of the money amount



21
# File 'lib/minting/money/conversion.rb', line 21

def to_f = amount.to_f

#to_hashHash

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 a Hash representation of the money instance.

Examples:

Money.from(134120, 'BRL').to_hash
#=> { currency: "BRL", amount: "134120.00" }

Returns:

  • (Hash)

    hash with :currency (String) and :amount (String) keys



40
41
42
# File 'lib/minting/money/conversion.rb', line 40

def to_hash
  { currency: currency_code, amount: Kernel.format("%0.#{currency.subunit}f", amount) }
end

#to_html(format = DEFAULT_FORMAT) ⇒ String

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.

Renders a safe HTML5 <data> element containing the formatted currency. Embeds the ISO currency description and raw value as the metadata title attribute.

Parameters:

  • format (String) (defaults to: DEFAULT_FORMAT)

    the display format to apply to the visible HTML text

Returns:

  • (String)

    HTML5 <data> representation



28
29
30
31
32
# File 'lib/minting/money/conversion.rb', line 28

def to_html(format = DEFAULT_FORMAT)
  title = Kernel.format("#{currency_code} %0.#{currency.subunit}f", amount)
  body = format(format)
  %(<data class='money' title='#{title}'>#{ERB::Util.html_escape(body)}</data>)
end

#to_rRational

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 exact internal Rational representation of the monetary amount.

Returns:

  • (Rational)

    the rational representation of the money amount



69
# File 'lib/minting/money/conversion.rb', line 69

def to_r = amount

#to_sString

Returns a string representation of the money amount.

When no Mint.locale_backend is configured, uses currency.symbol, comma thousands separators for amounts >= 1000, and decimal for the fractional part. When a locale backend is set, delegates to #format so locale-aware formatting takes effect.

Unlike #format, this method takes no arguments — use #format (alias #to_fs) for custom formatting.

Examples:

Money.from(1234.56, 'USD').to_s  #=> "$1,234.56"
Money.from(0.99, 'USD').to_s     #=> "$0.99"
Money.from(100, 'JPY').to_s      #=> "¥100"

Returns:

  • (String)

    formatted money string



29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/minting/money/format/to_s.rb', line 29

def to_s
  return format unless Mint.locale_backend.nil?

  subunit = currency.subunit
  major = integral.to_s
  major.gsub!(THOUSAND_RE, '\1,') if amount.abs >= 1000
  if subunit > 0
    minor = fractional.abs.to_s.rjust(subunit, '0')
    "#{currency.symbol}#{major}.#{minor}"
  else
    "#{currency.symbol}#{major}"
  end
end

#zero?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 true if amount is zero.

Returns:

  • (Boolean)

    true if amount is zero



54
# File 'lib/minting/money/comparable.rb', line 54

def zero? = amount.zero?