Class: Money

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/money/money.rb,
lib/money/errors.rb,
lib/money/variable_exchange_bank.rb

Overview

Class for aiding in exchanging money between different currencies. By default, the Money class uses an object of this class (accessible through Money#bank) for performing currency exchanges.

By default, VariableExchangeBank has no knowledge about conversion rates. One must manually specify them with add_rate, after which one can perform exchanges with exchange. For example:

bank = Money::VariableExchangeBank.new
bank.add_rate("USD", "CAD", 1.24515)
bank.add_rate("CAD", "USD", 0.803115)

# Exchange 100 CAD to USD:
bank.exchange(100_00, "CAD", "USD")  # => 124
# Exchange 100 USD to CAD:
bank.exchange(100_00, "USD", "CAD")  # => 80

Defined Under Namespace

Classes: UnknownRate, VariableExchangeBank

Constant Summary collapse

SYMBOLS =

Add more from www.xe.com/symbols.php

{
  "GBP" => "£",
  "JPY" => "¥",
  "EUR" => "€",
  "ZWD" => "Z$",
  "CNY" => "¥",
  "INR" => "₨",
  "NPR" => "₨",
  "SCR" => "₨",
  "LKR" => "₨",
  "SEK" => "kr",
  "GHC" => "¢"

  # Everything else defaults to $
}

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

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

Creates a new money object.

Money.new(100)

Alternativly you can use the convinience methods like Money.ca_dollar and Money.us_dollar



57
58
59
60
61
# File 'lib/money/money.rb', line 57

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

Class Attribute Details

.default_bankObject

Each Money object is associated to a bank object, which is responsible for currency exchange. This property allows one to specify the default bank object.

bank1 = MyBank.new
bank2 = MyOtherBank.new

Money.default_bank = bank1
money1 = Money.new(10)
money1.bank  # => bank1

Money.default_bank = bank2
money2 = Money.new(10)
money2.bank  # => bank2
money1.bank  # => bank1

The default value for this property is an instance if VariableExchangeBank. It allows one to specify custom exchange rates:

Money.default_bank.add_rate("USD", "CAD", 1.24515)
Money.default_bank.add_rate("CAD", "USD", 0.803115)
Money.new(100, "USD").exchange_to("CAD")  # => Money.new(124, "CAD")
Money.new(100, "CAD").exchange_to("USD")  # => Money.new(80, "USD")


33
34
35
# File 'lib/money/money.rb', line 33

def default_bank
  @default_bank
end

.default_currencyObject

The default currency, which is used when Money.new is called without an explicit currency argument. The default value is “USD”.



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

def default_currency
  @default_currency
end

Instance Attribute Details

#bankObject (readonly)

Returns the value of attribute bank.



7
8
9
# File 'lib/money/money.rb', line 7

def bank
  @bank
end

#centsObject (readonly)

Get the cents value of the object



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

def cents
  @cents
end

#currencyObject (readonly)

Returns the value of attribute currency.



7
8
9
# File 'lib/money/money.rb', line 7

def currency
  @currency
end

Class Method Details

.add_rate(from_currency, to_currency, rate) ⇒ Object



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

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

.empty(currency = default_currency) ⇒ Object

Create a new money object with value 0.



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

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

Instance Method Details

#*(fixnum) ⇒ Object

Multiply money by fixnum



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

def *(fixnum)
  Money.new(cents * fixnum, currency)
end

#+(other_money) ⇒ Object



76
77
78
79
80
81
82
# File 'lib/money/money.rb', line 76

def +(other_money)
  if currency == other_money.currency
    Money.new(cents + other_money.cents, other_money.currency)
  else
    Money.new(cents + other_money.exchange_to(currency).cents,currency)
  end
end

#-(other_money) ⇒ Object



84
85
86
87
88
89
90
# File 'lib/money/money.rb', line 84

def -(other_money)
  if currency == other_money.currency
    Money.new(cents - other_money.cents, other_money.currency)
  else
    Money.new(cents - other_money.exchange_to(currency).cents, currency)
  end
end

#/(fixnum) ⇒ Object

Divide money by fixnum



103
104
105
# File 'lib/money/money.rb', line 103

def /(fixnum)
  Money.new(cents / fixnum, currency)
end

#<=>(other_money) ⇒ Object



68
69
70
71
72
73
74
# File 'lib/money/money.rb', line 68

def <=>(other_money)
  if bank.same_currency?(currency, other_money.currency)
    cents <=> other_money.cents
  else
    cents <=> other_money.exchange_to(currency).cents
  end
end

#==(other_money) ⇒ Object

Do two money objects equal? Only works if both objects are of the same currency



64
65
66
# File 'lib/money/money.rb', line 64

def ==(other_money)
  cents == other_money.cents && bank.same_currency?(currency, other_money.currency)
end

#exchange_to(other_currency) ⇒ Object

Recieve the amount of this money object in another currency.



230
231
232
# File 'lib/money/money.rb', line 230

def exchange_to(other_currency)
  Money.new(@bank.exchange(self.cents, currency, other_currency), other_currency)
end

#format(*rules) ⇒ Object

Creates a formatted price string according to several rules. The following options are supported: :display_free, :with_currency, :no_cents, :symbol and :html.

:display_free

Whether a zero amount of money should be formatted of “free” or as the supplied string.

Money.us_dollar(0).format(:display_free => true)      => "free"
Money.us_dollar(0).format(:display_free => "gratis")  => "gratis"
Money.us_dollar(0).format => "$0.00"

:with_currency

Whether the currency name should be appended to the result string.

Money.ca_dollar(100).format => "$1.00"
Money.ca_dollar(100).format(:with_currency => true) => "$1.00 CAD"
Money.us_dollar(85).format(:with_currency => true)  => "$0.85 USD"

:no_cents

Whether cents should be omitted.

Money.ca_dollar(100).format(:no_cents => true) => "$1"
Money.ca_dollar(599).format(:no_cents => true) => "$5"

Money.ca_dollar(570).format(:no_cents => true, :with_currency => true) => "$5 CAD"
Money.ca_dollar(39000).format(:no_cents => true) => "$390"

:symbol

Whether a money symbol should be prepended to the result string. The default is true. This method attempts to pick a symbol that’s suitable for the given currency.

Money.new(100, :currency => "USD")  => "$1.00"
Money.new(100, :currency => "GBP")  => "£1.00"
Money.new(100, :currency => "EUR")  => "€1.00"

# Same thing.
Money.new(100, :currency => "USD").format(:symbol => true)  => "$1.00"
Money.new(100, :currency => "GBP").format(:symbol => true)  => "£1.00"
Money.new(100, :currency => "EUR").format(:symbol => true)  => "€1.00"

You can specify a false expression or an empty string to disable prepending a money symbol:

Money.new(100, :currency => "USD").format(:symbol => false)  => "1.00"
Money.new(100, :currency => "GBP").format(:symbol => nil)    => "1.00"
Money.new(100, :currency => "EUR").format(:symbol => "")     => "1.00"

If the symbol for the given currency isn’t known, then it will default to “$” as symbol:

Money.new(100, :currency => "AWG").format(:symbol => true)  => "$1.00"

You can specify a string as value to enforce using a particular symbol:

Money.new(100, :currency => "AWG").format(:symbol => "ƒ")   => "ƒ1.00"

:html

Whether the currency should be HTML-formatted. Only useful in combination with :with_currency.

Money.ca_dollar(570).format(:html => true, :with_currency => true)
  =>  "$5.70 <span class=\"currency\">CAD</span>"


180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/money/money.rb', line 180

def format(*rules)
  # support for old format parameters
  rules = normalize_formatting_rules(rules)

  if cents == 0
    if rules[:display_free].respond_to?(:to_str)
      return rules[:display_free]
    elsif rules[:display_free]
      return "free"
    end
  end

  if rules.has_key?(:symbol)
    if rules[:symbol] === true
      symbol = SYMBOLS[currency[:currency]] || "$"
    elsif rules[:symbol]
      symbol = rules[:symbol]
    else
      symbol = ""
    end
  else
    symbol = "$"
  end

  if rules[:no_cents]
    formatted = sprintf("#{symbol}%d", cents.to_f / 100)
  else
    formatted = sprintf("#{symbol}%.2f", cents.to_f / 100)
  end

  # Commify ("10000" => "10,000")
  formatted.gsub!(/(\d)(?=\d{3}+(?:\.|$))(\d{3}\..*)?/,'\1,\2')

  if rules[:with_currency]
    formatted << " "
    formatted << '<span class="currency">' if rules[:html]
    formatted << currency
    formatted << '</span>' if rules[:html]
  end
  formatted
end

#to_moneyObject

Conversation to self



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

def to_money
  self
end

#to_sObject

Returns the amount of money as a string.

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


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

def to_s
  sprintf("%.2f", cents / 100.00)
end

#zero?Boolean

Test if the money amount is zero

Returns:

  • (Boolean)


108
109
110
# File 'lib/money/money.rb', line 108

def zero?
  cents == 0
end