Class: Money

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

Overview

Represents an amount of money in a given currency.

Defined Under Namespace

Modules: Arithmetic, Bank, Formatting, Parsing Classes: Currency

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Parsing

included

Methods included from Formatting

#decimal_mark, #format, #thousands_separator

Methods included from Arithmetic

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

Constructor Details

#initialize(cents, currency = Money.default_currency, bank = Money.default_bank) ⇒ Money

Creates a new Money object of cents value in cents, with given currency.

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

Examples:

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

Parameters:

  • cents (Integer)

    The money amount, in cents.

  • currency (Currency, String, Symbol) (defaults to: Money.default_currency)

    The currency format.

  • bank (Money::Bank::*) (defaults to: Money.default_bank)

    The exchange bank to use.

See Also:



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

def initialize(cents, currency = Money.default_currency, bank = Money.default_bank)
  @cents = cents.round.to_i
  @currency = Currency.wrap(currency)
  @bank = bank
end

Class Attribute Details

.default_bankMoney::Bank::*

Each Money object is 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 if Bank::VariableExchange. It allows one to specify custom exchange rates.

Returns:



37
38
39
# File 'lib/money/money.rb', line 37

def default_bank
  @default_bank
end

.default_currencyMoney::Currency

The default currency, 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.

Returns:



44
45
46
# File 'lib/money/money.rb', line 44

def default_currency
  @default_currency
end

.use_i18ntrue, false

Use this to disable i18n even if it’s used by other objects in your app.

Returns:

  • (true, false)


49
50
51
# File 'lib/money/money.rb', line 49

def use_i18n
  @use_i18n
end

Instance Attribute Details

#bankMoney::Bank::* (readonly)

The Money::Bank based object used to perform currency exchanges with.

Returns:



27
28
29
# File 'lib/money/money.rb', line 27

def bank
  @bank
end

#centsInteger (readonly)

The value of the money in cents.

Returns:

  • (Integer)


17
18
19
# File 'lib/money/money.rb', line 17

def cents
  @cents
end

#currencyCurrency (readonly)

The currency the money is in.

Returns:



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

def currency
  @currency
end

Class Method Details

.add_rate(from_currency, to_currency, rate) ⇒ Numeric

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

Examples:

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

Parameters:

Returns:



158
159
160
# File 'lib/money/money.rb', line 158

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

.ca_dollar(cents) ⇒ Money

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>

Parameters:

  • cents (Integer)

    The cents value.

Returns:



84
85
86
# File 'lib/money/money.rb', line 84

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

.empty(currency = default_currency) ⇒ Money

Create a new money object with value 0.

Examples:

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

Parameters:

Returns:



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

def self.empty(currency = default_currency)
  Money.new(0, currency)
end

.euro(cents) ⇒ Money

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>

Parameters:

  • cents (Integer)

    The cents value.

Returns:



113
114
115
# File 'lib/money/money.rb', line 113

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

.new_with_dollars(amount, currency = Money.default_currency, bank = Money.default_bank) ⇒ Money

Creates a new Money object of amount value in dollars, with given currency.

The amount value is expressed in dollars where the dollar is the main monetary unit, opposite to the subunit-based representation used internally by this library called cents.

Examples:

Money.new_with_dollars(100)
#=> #<Money @cents=10000 @currency="USD">
Money.new_with_dollars(100, "USD")
#=> #<Money @cents=10000 @currency="USD">
Money.new_with_dollars(100, "EUR")
#=> #<Money @cents=10000 @currency="EUR">

Parameters:

  • amount (Numeric)

    The money amount, in dollars.

  • currency (Currency, String, Symbol) (defaults to: Money.default_currency)

    The currency format.

  • bank (Money::Bank::*) (defaults to: Money.default_bank)

    The exchange bank to use.

Returns:

See Also:

  • new


142
143
144
145
146
147
# File 'lib/money/money.rb', line 142

def self.new_with_dollars(amount, currency = Money.default_currency, bank = Money.default_bank)
  money = from_numeric(amount, currency)
  # Hack! You can't change a bank
  money.instance_variable_set("@bank", bank)
  money
end

.us_dollar(cents) ⇒ Money

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>

Parameters:

  • cents (Integer)

    The cents value.

Returns:



99
100
101
# File 'lib/money/money.rb', line 99

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

Instance Method Details

#allocate(splits) ⇒ Array<Money, Money, Money>

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)]

Parameters:

  • to (0.50, 0.25, 0.25)

    give 50% of the cash to party1, 25% ot party2, and 25% to party3.

Returns:

Raises:

  • (ArgumentError)


366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
# File 'lib/money/money.rb', line 366

def allocate(splits)
  allocations = splits.inject(0.0) {|sum, i| sum += i }
  raise ArgumentError, "splits add to more then 100%" if (allocations - 1.0) > Float::EPSILON

  left_over = cents

  amounts = splits.collect do |ratio|
    fraction = (cents * ratio / allocations).floor
    left_over -= fraction
    fraction
  end

  left_over.times { |i| amounts[i % amounts.length] += 1 }

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

#as_ca_dollarMoney

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>

Returns:



324
325
326
# File 'lib/money/money.rb', line 324

def as_ca_dollar
  exchange_to("CAD")
end

#as_euroMoney

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>

Returns:



336
337
338
# File 'lib/money/money.rb', line 336

def as_euro
  exchange_to("EUR")
end

#as_us_dollarMoney

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>

Returns:



312
313
314
# File 'lib/money/money.rb', line 312

def as_us_dollar
  exchange_to("USD")
end

#currency_as_stringString

Return string representation of currency object

Examples:

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

Returns:



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

def currency_as_string
  self.currency.to_s
end

#currency_as_string=(val) ⇒ Money::Currency

Set currency object using a string

Examples:

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

Parameters:

  • val (String)

    The currency string.

Returns:



225
226
227
# File 'lib/money/money.rb', line 225

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

#dollarsFloat

Returns the value of the money in dollars, instead of in cents.

Examples:

Money.new(100).dollars           # => 1.0
Money.new_with_dollars(1).dollar # => 1.0

Returns:

  • (Float)

See Also:



203
204
205
# File 'lib/money/money.rb', line 203

def dollars
  to_f
end

#exchange_to(other_currency) ⇒ Money

Receive the amount of this money object in another Currency.

Examples:

Money.new(2000, "USD").exchange_to("EUR")
Money.new(2000, "USD").exchange_to(Currency.new("EUR"))

Parameters:

Returns:



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

def exchange_to(other_currency)
  other_currency = Currency.wrap(other_currency)
  @bank.exchange_with(self, other_currency)
end

#hashFixnum

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

Examples:

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

Returns:

  • (Fixnum)


236
237
238
# File 'lib/money/money.rb', line 236

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

#inspectString

Common inspect function

Returns:



350
351
352
# File 'lib/money/money.rb', line 350

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

#split(num) ⇒ Array<Money, Money, Money>

Split money amongst parties evenly without loosing pennies.

Examples:

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

Parameters:

  • number (2)

    of parties.

Returns:

Raises:

  • (ArgumentError)


391
392
393
394
395
396
397
398
399
400
401
402
403
404
# File 'lib/money/money.rb', line 391

def split(num)
  raise ArgumentError, "need at least one party" if num < 1
  low = Money.new(cents / num)
  high = Money.new(low.cents + 1)

  remainder = cents % num
  result = []

  num.times do |index|
    result[index] = index < remainder ? high : low
  end

  return result
end

#symbolString

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

Examples:

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

Returns:



246
247
248
# File 'lib/money/money.rb', line 246

def symbol
  currency.symbol || "¤"
end

#to_dBigDecimal

Return the amount of money as a BigDecimal.

Examples:

Money.us_dollar(100).to_d => BigDecimal.new("1.0")

Returns:

  • (BigDecimal)


273
274
275
# File 'lib/money/money.rb', line 273

def to_d
  BigDecimal.new(cents.to_s) / BigDecimal.new(currency.subunit_to_unit.to_s)
end

#to_fFloat

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 decimals.

Examples:

Money.us_dollar(100).to_f => 1.0

Returns:

  • (Float)


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

def to_f
  to_d.to_f
end

#to_moneyself

Conversation to self.

Returns:

  • (self)


343
344
345
# File 'lib/money/money.rb', line 343

def to_money
  self
end

#to_sString

Returns the amount of money as a string.

Examples:

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

Returns:



256
257
258
259
260
261
262
263
264
265
# File 'lib/money/money.rb', line 256

def to_s
  unit, subunit  = cents.abs.divmod(currency.subunit_to_unit).map{|o| o.to_s}
  if currency.decimal_places == 0
    return "-#{unit}" if cents < 0
    return unit
  end
  subunit = (("0" * currency.decimal_places) + subunit)[(-1*currency.decimal_places)..-1]
  return "-#{unit}#{decimal_mark}#{subunit}" if cents < 0
  "#{unit}#{decimal_mark}#{subunit}"
end