Class: Money

Inherits:
Object
  • Object
show all
Includes:
Comparable, Arithmetic, Formatting
Defined in:
lib/money/money.rb,
lib/money/version.rb,
lib/money/currency.rb,
lib/money/bank/base.rb,
lib/money/currency/loader.rb,
lib/money/money/arithmetic.rb,
lib/money/money/formatting.rb,
lib/money/currency/heuristics.rb,
lib/money/bank/single_currency.rb,
lib/money/bank/variable_exchange.rb

Overview

“Money is any object or record that is generally accepted as payment for goods and services and repayment of debts in a given socio-economic context or country.” -Wikipedia

An instance of Money represents an amount of a specific currency.

Money is a value object and should be treated as immutable.

See Also:

Defined Under Namespace

Modules: Arithmetic, Bank, Formatting Classes: Currency

Constant Summary

VERSION =
"6.1.1"

Class Attribute Summary (collapse)

Instance Attribute Summary (collapse)

Class Method Summary (collapse)

Instance Method Summary (collapse)

Methods included from Arithmetic

#%, #*, #+, #-, #-@, #/, #<=>, #==, #abs, #coerce, #div, #divmod, #eql?, #modulo, #negative?, #nonzero?, #positive?, #remainder, #zero?

Methods included from Formatting

define_i18n_method, #format, included

Constructor Details

- (Money) initialize(obj, currency = Money.default_currency, bank = Money.default_bank)

Creates a new Money object of value given in the fractional unit of the given currency.

Alternatively you can use the convenience methods like ca_dollar and us_dollar.

Examples:

Money.new(100)        #=> #<Money @fractional=100 @currency="USD">
Money.new(100, "USD") #=> #<Money @fractional=100 @currency="USD">
Money.new(100, "EUR") #=> #<Money @fractional=100 @currency="EUR">


240
241
242
243
244
245
# File 'lib/money/money.rb', line 240

def initialize(obj, currency = Money.default_currency, bank = Money.default_bank)
  @fractional = obj.respond_to?(:fractional) ? obj.fractional : as_d(obj)
  @currency   = obj.respond_to?(:currency) ? obj.currency : Currency.wrap(currency)
  @currency ||= Money.default_currency 
  @bank       = obj.respond_to?(:bank) ? obj.bank : bank
end

Class Attribute Details

+ (Object) conversion_precision

associated to a bank object, which is responsible for currency exchange. This property allows you to specify the default bank object. The default value for this property is an instance of Bank::VariableExchange. It allows one to specify custom exchange rates. which is used when Money.new is called without an explicit currency argument. The default value is Currency.new(“USD”). The value must be a valid Money::Currency instance. it's used by other objects in your app. infinite precision cents precision for converting Rational to BigDecimal



79
80
81
# File 'lib/money/money.rb', line 79

def conversion_precision
  @conversion_precision
end

+ (Object) default_bank

associated to a bank object, which is responsible for currency exchange. This property allows you to specify the default bank object. The default value for this property is an instance of Bank::VariableExchange. It allows one to specify custom exchange rates. which is used when Money.new is called without an explicit currency argument. The default value is Currency.new(“USD”). The value must be a valid Money::Currency instance. it's used by other objects in your app. infinite precision cents precision for converting Rational to BigDecimal



79
80
81
# File 'lib/money/money.rb', line 79

def default_bank
  @default_bank
end

+ (Object) default_currency

associated to a bank object, which is responsible for currency exchange. This property allows you to specify the default bank object. The default value for this property is an instance of Bank::VariableExchange. It allows one to specify custom exchange rates. which is used when Money.new is called without an explicit currency argument. The default value is Currency.new(“USD”). The value must be a valid Money::Currency instance. it's used by other objects in your app. infinite precision cents precision for converting Rational to BigDecimal



79
80
81
# File 'lib/money/money.rb', line 79

def default_currency
  @default_currency
end

+ (Object) infinite_precision

associated to a bank object, which is responsible for currency exchange. This property allows you to specify the default bank object. The default value for this property is an instance of Bank::VariableExchange. It allows one to specify custom exchange rates. which is used when Money.new is called without an explicit currency argument. The default value is Currency.new(“USD”). The value must be a valid Money::Currency instance. it's used by other objects in your app. infinite precision cents precision for converting Rational to BigDecimal



79
80
81
# File 'lib/money/money.rb', line 79

def infinite_precision
  @infinite_precision
end

+ (BigDecimal::ROUND_MODE, Yield) rounding_mode(mode = nil)

Use this to return the rounding mode. You may also pass a rounding mode and a block to temporatly change it. It will then return the results of the block instead.

Examples:

fee = Money.rounding_mode(BigDecimal::ROUND_HALF_UP) do
  Money.new(1200) * BigDecimal.new('0.029')
end


146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/money/money.rb', line 146

def self.rounding_mode(mode=nil)
  if mode.nil?
    Thread.current[:money_rounding_mode] || @rounding_mode
  else
    begin
      Thread.current[:money_rounding_mode] = mode
      yield
    ensure
      Thread.current[:money_rounding_mode] = nil
    end
  end
end

+ (Object) use_i18n

associated to a bank object, which is responsible for currency exchange. This property allows you to specify the default bank object. The default value for this property is an instance of Bank::VariableExchange. It allows one to specify custom exchange rates. which is used when Money.new is called without an explicit currency argument. The default value is Currency.new(“USD”). The value must be a valid Money::Currency instance. it's used by other objects in your app. infinite precision cents precision for converting Rational to BigDecimal



79
80
81
# File 'lib/money/money.rb', line 79

def use_i18n
  @use_i18n
end

Instance Attribute Details

- (Object) bank (readonly)

perform currency exchanges with.



60
61
62
# File 'lib/money/money.rb', line 60

def bank
  @bank
end

- (Object) currency (readonly)

perform currency exchanges with.



60
61
62
# File 'lib/money/money.rb', line 60

def currency
  @currency
end

Class Method Details

+ (Numeric) add_rate(from_currency, to_currency, rate)

Adds a new exchange rate to the default bank and return the rate.

Examples:

Money.add_rate("USD", "CAD", 1.25) #=> 1.25


213
214
215
# File 'lib/money/money.rb', line 213

def self.add_rate(from_currency, to_currency, rate)
  Money.default_bank.add_rate(from_currency, to_currency, rate)
end

+ (Money) ca_dollar(cents)

Creates a new Money object of the given value, using the Canadian dollar currency.

Examples:

n = Money.ca_dollar(100)
n.cents    #=> 100
n.currency #=> #<Money::Currency id: cad>


170
171
172
# File 'lib/money/money.rb', line 170

def self.ca_dollar(cents)
  Money.new(cents, "CAD")
end

+ (Object) disallow_currency_conversion!

Sets the default bank to be a SingleCurrency bank that raises on currency exchange. Useful when apps operate in a single currency at a time.



219
220
221
# File 'lib/money/money.rb', line 219

def self.disallow_currency_conversion!
  self.default_bank = Bank::SingleCurrency.instance
end

+ (Money) empty(currency = default_currency) Also known as: zero

Create a new money object with value 0.

Examples:

Money.empty #=> #<Money @fractional=0>


93
94
95
96
# File 'lib/money/money.rb', line 93

def empty(currency = default_currency)
  @empty ||= {}
  @empty[currency] ||= Money.new(0, currency).freeze
end

+ (Money) euro(cents)

Creates a new Money object of the given value, using the Euro currency.

Examples:

n = Money.euro(100)
n.cents    #=> 100
n.currency #=> #<Money::Currency id: eur>


199
200
201
# File 'lib/money/money.rb', line 199

def self.euro(cents)
  Money.new(cents, "EUR")
end

+ (Object) inherited(base)



128
129
130
# File 'lib/money/money.rb', line 128

def self.inherited(base)
  base.setup_defaults
end

+ (Object) setup_defaults



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/money/money.rb', line 108

def self.setup_defaults
  # Set the default bank for creating new +Money+ objects.
  self.default_bank = Bank::VariableExchange.instance

  # Set the default currency for creating new +Money+ object.
  self.default_currency = Currency.new("USD")

  # Default to using i18n
  self.use_i18n = true

  # Default to not using infinite precision cents
  self.infinite_precision = false

  # Default to bankers rounding
  self.rounding_mode = BigDecimal::ROUND_HALF_EVEN

  # Default the conversion of Rationals precision to 16
  self.conversion_precision = 16
end

+ (Money) us_dollar(cents)

Creates a new Money object of the given value, using the American dollar currency.

Examples:

n = Money.us_dollar(100)
n.cents    #=> 100
n.currency #=> #<Money::Currency id: usd>


185
186
187
# File 'lib/money/money.rb', line 185

def self.us_dollar(cents)
  Money.new(cents, "USD")
end

Instance Method Details

- (Array<Money>) allocate(splits)

Allocates money between different parties without loosing pennies. After the mathmatically split has been performed, left over pennies will be distributed round-robin amongst the parties. This means that parties listed first will likely recieve more pennies then ones that are listed later

Examples:

Money.new(5,   "USD").allocate([0.3, 0.7])         #=> [Money.new(2), Money.new(3)]
Money.new(100, "USD").allocate([0.33, 0.33, 0.33]) #=> [Money.new(34), Money.new(33), Money.new(33)]


471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
# File 'lib/money/money.rb', line 471

def allocate(splits)
  allocations = allocations_from_splits(splits)

  if (allocations - BigDecimal("1")) > Float::EPSILON
    raise ArgumentError, "splits add to more then 100%"
  end

  amounts, left_over = amounts_from_splits(allocations, splits)

  unless self.class.infinite_precision
    left_over.to_i.times { |i| amounts[i % amounts.length] += 1 }
  end

  amounts.collect { |fractional| Money.new(fractional, currency) }
end

- (BigDecimal) amount

Returns the numerical value of the money

Examples:

Money.new(1_00, "USD").amount    # => BigDecimal.new("1.00")

See Also:



276
277
278
# File 'lib/money/money.rb', line 276

def amount
  to_d
end

- (Money) as_ca_dollar

Receive a money object with the same amount as the current Money object in canadian dollar.

Examples:

n = Money.new(100, "USD").as_ca_dollar
n.currency #=> #<Money::Currency id: cad>


442
443
444
# File 'lib/money/money.rb', line 442

def as_ca_dollar
  exchange_to("CAD")
end

- (Money) as_euro

Receive a money object with the same amount as the current Money object in euro.

Examples:

n = Money.new(100, "USD").as_euro
n.currency #=> #<Money::Currency id: eur>


454
455
456
# File 'lib/money/money.rb', line 454

def as_euro
  exchange_to("EUR")
end

- (Money) as_us_dollar

Receive a money object with the same amount as the current Money object in american dollars.

Examples:

n = Money.new(100, "CAD").as_us_dollar
n.currency #=> #<Money::Currency id: usd>


430
431
432
# File 'lib/money/money.rb', line 430

def as_us_dollar
  exchange_to("USD")
end

- (Integer, BigDecimal) cents

Convenience method for fractional part of the amount. Synonym of #fractional

See Also:



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

def cents
  fractional
end

- (String) currency_as_string

Return string representation of currency object

Examples:

Money.new(100, :USD).currency_as_string #=> "USD"


286
287
288
# File 'lib/money/money.rb', line 286

def currency_as_string
  currency.to_s
end

- (Money::Currency) currency_as_string=(val)

Set currency object using a string

Examples:

Money.new(100).currency_as_string("CAD") #=> #<Money::Currency id: cad>


298
299
300
# File 'lib/money/money.rb', line 298

def currency_as_string=(val)
  @currency = Currency.wrap(val)
end

- (BigDecimal) dollars

Assuming using a currency using dollars: Returns the value of the money in dollars, instead of in the fractional unit cents.

Synonym of #amount

Examples:

Money.new(1_00, "USD").dollars   # => BigDecimal.new("1.00")

See Also:



262
263
264
# File 'lib/money/money.rb', line 262

def dollars
  amount
end

- (Money) exchange_to(other_currency) {|n| ... }

Receive the amount of this money object in another Currency.

Examples:

Money.new(2000, "USD").exchange_to("EUR")
Money.new(2000, "USD").exchange_to("EUR") {|x| x.round}
Money.new(2000, "USD").exchange_to(Currency.new("EUR"))

Yields:

  • (n)

    Optional block to use when rounding after exchanging one currency for another.

Yield Parameters:

  • n (Float)

    The resulting float after exchanging one currency for another.

Yield Returns:

  • (Integer)


413
414
415
416
417
418
419
420
# File 'lib/money/money.rb', line 413

def exchange_to(other_currency, &rounding_method)
  other_currency = Currency.wrap(other_currency)
  if self.currency == other_currency
    self
  else
    @bank.exchange_with(self, other_currency, &rounding_method)
  end
end

- (Integer, BigDecimal) fractional

The value of the monetary amount represented in the fractional or subunit of the currency.

For example, in the US Dollar currency the fractional unit is cents, and there are 100 cents in one US Dollar. So given the Money representation of one US dollar, the fractional interpretation is 100.

Another example is that of the Kuwaiti Dinar. In this case the fractional unit is the Fils and there 1000 Fils to one Kuwaiti Dinar. So given the Money representation of one Kuwaiti Dinar, the fractional interpretation is 1000.

See Also:



45
46
47
48
49
50
51
52
53
54
55
# File 'lib/money/money.rb', line 45

def fractional
  # Ensure we have a BigDecimal. If the Money object is created
  # from YAML, @fractional can end up being set to a Float.
  fractional = as_d(@fractional)

  if self.class.infinite_precision
    fractional
  else
    fractional.round(0, self.class.rounding_mode).to_i
  end
end

- (Fixnum) hash

Returns a Fixnum hash value based on the fractional and currency attributes in order to use functions like & (intersection), group_by, etc.

Examples:

Money.new(100).hash #=> 908351


309
310
311
# File 'lib/money/money.rb', line 309

def hash
  [fractional.hash, currency.hash].hash
end

- (String) inspect

Common inspect function



326
327
328
# File 'lib/money/money.rb', line 326

def inspect
  "#<Money fractional:#{fractional} currency:#{currency}>"
end

- (Object) localize_formatting_rules(rules)



315
316
317
318
319
320
321
322
# File 'lib/money/money/formatting.rb', line 315

def localize_formatting_rules(rules)
  if currency.iso_code == "JPY" && I18n.locale == :ja
    rules[:symbol] = "" unless rules[:symbol] == false
    rules[:symbol_position] = :after
    rules[:symbol_after_without_space] = true
  end
  rules
end

- (Object) regexp_format(formatted, rules, decimal_mark, symbol_value)



301
302
303
304
305
306
307
308
309
310
311
312
313
# File 'lib/money/money/formatting.rb', line 301

def regexp_format(formatted, rules, decimal_mark, symbol_value)
  regexp_decimal = Regexp.escape(decimal_mark)
  if rules[:south_asian_number_formatting]
    /(\d+?)(?=(\d\d)+(\d)(?:\.))/
  else
    # Symbols may contain decimal marks (E.g "դր.")
    if formatted.sub(symbol_value.to_s, "") =~ /#{regexp_decimal}/
      /(\d)(?=(?:\d{3})+(?:#{regexp_decimal}))/
    else
      /(\d)(?=(?:\d{3})+(?:[^\d]{1}|$))/
    end
  end
end

- (Money) round(rounding_mode = self.class.rounding_mode)

Note:

This method is only useful when operating with infinite_precision turned on. Without infinite_precision values are rounded to the smallest unit of coinage automatically.

Round the monetary amount to smallest unit of coinage.

Examples:

Money.new(10.1, 'USD').round #=> Money.new(10, 'USD')

See Also:



520
521
522
523
524
525
526
# File 'lib/money/money.rb', line 520

def round(rounding_mode = self.class.rounding_mode)
  if self.class.infinite_precision
    Money.new(fractional.round(0, rounding_mode), self.currency)
  else
    self
  end
end

- (Array<Money>) split(num)

Split money amongst parties evenly without loosing pennies.

Examples:

Money.new(100, "USD").split(3) #=> [Money.new(34), Money.new(33), Money.new(33)]

Raises:

  • (ArgumentError)


495
496
497
498
499
500
501
502
503
# File 'lib/money/money.rb', line 495

def split(num)
  raise ArgumentError, "need at least one party" if num < 1

  if self.class.infinite_precision
    split_infinite(num)
  else
    split_flat(num)
  end
end

- (String) symbol

Uses Currency#symbol. If nil is returned, defaults to “¤”.

Examples:

Money.new(100, "USD").symbol #=> "$"


319
320
321
# File 'lib/money/money.rb', line 319

def symbol
  currency.symbol || "¤"
end

- (Object) symbol_position_from(rules)



340
341
342
343
344
345
346
347
348
# File 'lib/money/money/formatting.rb', line 340

def symbol_position_from(rules)
  if rules.has_key?(:symbol_position)
    rules[:symbol_position]
  elsif currency.symbol_first?
    :before
  else
    :after
  end
end

- (Object) symbol_value_from(rules)



324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
# File 'lib/money/money/formatting.rb', line 324

def symbol_value_from(rules)
  if rules.has_key?(:symbol)
    if rules[:symbol] === true
      symbol
    elsif rules[:symbol]
      rules[:symbol]
    else
      ""
    end
  elsif rules[:html]
    currency.html_entity == '' ? currency.symbol : currency.html_entity
  else
    symbol
  end
end

- (BigDecimal) to_d

Return the amount of money as a BigDecimal.

Examples:

Money.us_dollar(1_00).to_d #=> BigDecimal.new("1.00")


358
359
360
# File 'lib/money/money.rb', line 358

def to_d
  as_d(fractional) / as_d(currency.subunit_to_unit)
end

- (Float) to_f

Return the amount of money as a float. Floating points cannot guarantee precision. Therefore, this function should only be used when you no longer need to represent currency or working with another system that requires floats.

Examples:

Money.us_dollar(100).to_f #=> 1.0


381
382
383
# File 'lib/money/money.rb', line 381

def to_f
  to_d.to_f
end

- (Integer) to_i

Return the amount of money as a Integer.

Examples:

Money.us_dollar(1_00).to_i #=> 1


368
369
370
# File 'lib/money/money.rb', line 368

def to_i
  to_d.to_i
end

- (self) to_money(given_currency = nil)

Conversation to self.



388
389
390
391
392
393
394
395
# File 'lib/money/money.rb', line 388

def to_money(given_currency = nil)
  given_currency = Currency.wrap(given_currency)
  if given_currency.nil? || self.currency == given_currency
    self
  else
    exchange_to(given_currency)
  end
end

- (String) to_s

Returns the amount of money as a string.

Examples:

Money.ca_dollar(100).to_s #=> "1.00"


336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
# File 'lib/money/money.rb', line 336

def to_s
  unit, subunit, fraction = strings_from_fractional

  str = if currency.decimal_places == 0
          if fraction == ""
            unit
          else
            "#{unit}#{decimal_mark}#{fraction}"
          end
        else
          "#{unit}#{decimal_mark}#{pad_subunit(subunit)}#{fraction}"
        end

  fractional < 0 ? "-#{str}" : str
end