Class: Money

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

Defined Under Namespace

Classes: MoneyError

Constant Summary collapse

@@bank =

Bank lets you exchange the object which is responsible for currency exchange. The default implementation just throws an exception. However money ships with a variable exchange bank implementation which supports custom excahnge rates:

Money.bank = VariableExchangeBank.new
Money.bank.add_rate("USD", "CAD", 1.24515)
Money.bank.add_rate("CAD", "USD", 0.803115)
Money.us_dollar(100).exchange_to("CAD") => Money.ca_dollar(124)
Money.ca_dollar(100).exchange_to("USD") => Money.us_dollar(80)
NoExchangeBank.new
@@default_currency =
"USD"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(cents, currency = default_currency, precision = 2) ⇒ Money

Creates a new money object.

Money.new(100)

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



39
40
41
# File 'lib/money.rb', line 39

def initialize(cents, currency = default_currency, precision = 2)
  @cents, @currency, @precision = cents.round, currency, precision
end

Instance Attribute Details

#centsObject (readonly)

Returns the value of attribute cents.



9
10
11
# File 'lib/money.rb', line 9

def cents
  @cents
end

#currencyObject (readonly)

Returns the value of attribute currency.



9
10
11
# File 'lib/money.rb', line 9

def currency
  @currency
end

#precisionObject (readonly)

Returns the value of attribute precision.



9
10
11
# File 'lib/money.rb', line 9

def precision
  @precision
end

Class Method Details

.ca_dollar(num) ⇒ Object

Create a new money object using the Canadian dollar currency



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

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

.empty(currency = default_currency) ⇒ Object

Create a new money object with value 0



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

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

.euro(num) ⇒ Object

Create a new money object using the Euro currency



228
229
230
# File 'lib/money.rb', line 228

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

.us_dollar(num) ⇒ Object

Create a new money object using the American dollar currency



223
224
225
# File 'lib/money.rb', line 223

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

Instance Method Details

#*(fixnum) ⇒ Object

multiply money by fixnum



75
76
77
# File 'lib/money.rb', line 75

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

#+(other_money) ⇒ Object



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

def +(other_money)
  other_money = other_money.exchange_to(currency) unless other_money.currency == currency
  
  new_precision = [precision, other_money.precision].max
  Money.new(to_precision(new_precision).cents + other_money.to_precision(new_precision).cents, currency, new_precision)
end

#-(other_money) ⇒ Object



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

def -(other_money)
  other_money = other_money.exchange_to(currency) unless other_money.currency == currency
  
  new_precision = [precision, other_money.precision].max
  Money.new(to_precision(new_precision).cents - other_money.to_precision(new_precision).cents, currency, new_precision)
end

#-@Object



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

def -@
  Money.new(-cents, currency, precision)
end

#/(fixnum) ⇒ Object

divide money by fixnum



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

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

#<=>(other_money) ⇒ Object



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

def <=>(other_money)
  if currency == other_money.currency
    cents <=> other_money.cents
  else
    cents <=> other_money.exchange_to(currency).cents
  end
end

#as_ca_dollarObject

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



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

def as_ca_dollar
  exchange_to("CAD")
end

#as_ca_euroObject

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



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

def as_ca_euro
  exchange_to("EUR")
end

#as_us_dollarObject

Recieve a money object with the same amount as the current Money object in american dollar



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

def as_us_dollar
  exchange_to("USD")
end

#eql?(other_money) ⇒ Boolean

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

Returns:

  • (Boolean)


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

def eql?(other_money)
  cents == other_money.cents && currency == other_money.currency
end

#exchange_to(other_currency) ⇒ Object

Recieve the amount of this money object in another currency



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

def exchange_to(other_currency)
  self.class.bank.exchange(self, other_currency)
end

#format(*rules) ⇒ Object

Format the price according to several rules Currently supported are :with_currency, :no_cents and :html

with_currency:

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

no_cents:

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

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

html:

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


111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/money.rb', line 111

def format(*rules)
  return self.class.zero if zero? && self.class.zero
  euro_symbol = [8364].pack("U")  
  rules = rules.flatten
   case self.currency
    when 'EUR'
      formatted = to_format(rules.include?(:no_cents) ? 0 : 2) +"#{euro_symbol}" 
    when 'GBP'
      formatted = "\u00A3" + to_format(rules.include?(:no_cents) ? 0 : 2)
    when 'USD'
      formatted = "$" + to_format(rules.include?(:no_cents) ? 0 : 2)
    when 'CAD'
     formatted = "$" + to_format(rules.include?(:no_cents) ? 0 : 2)
    else
      formatted = "$" + to_format(rules.include?(:no_cents) ? 0 : 2)
    end
    
  

  if rules.include?(:with_currency)
    formatted << " "
    formatted << '<span class="currency">' if rules.include?(:html)
    formatted << currency
    formatted << '</span>' if rules.include?(:html)
  end
  formatted
end

#separatorObject



182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/money.rb', line 182

def separator
  case self.currency
    when 'EUR'
        ','
    when 'GBP'
      ','
    when 'USD'
      '.'
    when 'CAD'
     '.'
    else
      '.'
    end
end

#to_chart(*rules) ⇒ Object



165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/money.rb', line 165

def to_chart(*rules)
  rules = rules.flatten
  case self.currency
    when 'EUR'
      formatted =  to_s(rules.include?(:no_cents) ? 0 : 2) +"&#x20AC;" 
    when 'GBP'
      formatted = "&#x00A3;" +  to_s(rules.include?(:no_cents) ? 0 : 2)
    when 'USD'
      formatted = "&#x0024;" +  to_s(rules.include?(:no_cents) ? 0 : 2)
    when 'CAD'
     formatted = "&#x0024;" + to_s(rules.include?(:no_cents) ? 0 : 2)
    else
      formatted = "&#x0024;" +  to_s(rules.include?(:no_cents) ? 0 : 2)
    end
  formatted
end

#to_fObject



197
198
199
# File 'lib/money.rb', line 197

def to_f
  cents.to_f / 10 ** precision
end

#to_format(show_precision = precision) ⇒ Object



157
158
159
160
161
162
163
# File 'lib/money.rb', line 157

def to_format(show_precision = precision)
  if show_precision > 0
    sprintf("%.#{show_precision}f", to_f  ).gsub('.', separator)
  else
    sprintf("%d", cents.to_f / 10 ** (precision - show_precision)  ).gsub('.', separator)
  end
end

#to_money(precision = nil) ⇒ Object

Conversation to self



251
252
253
# File 'lib/money.rb', line 251

def to_money(precision = nil)
  precision ? to_precision(precision) : self
end

#to_precision(new_precision) ⇒ Object



206
207
208
209
210
# File 'lib/money.rb', line 206

def to_precision(new_precision)
  difference = new_precision - precision
  new_cents = difference > 0 ? cents * 10**difference : (cents.to_f / 10**difference.abs).round
  Money.new(new_cents, currency, new_precision)
end

#to_s(show_precision = precision) ⇒ Object

Money.ca_dollar(100).to_s => “1.00”

Locale support:

 If
  number.currency.separator = ","
  number.currency.separator = "."
Then
  Money.ca_dollar(100).to_s => "1,00"


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

def to_s(show_precision = precision)
  s_separator = I18n.translate("number.format.separator", :default => ".")
  if show_precision > 0
    sprintf("%.#{show_precision}f", to_f  ).gsub('.', s_separator)
  else
    sprintf("%d", cents.to_f / 10 ** (precision - show_precision)  ).gsub('.', s_separator)
  end
end

#zero?Boolean

Test if the money amount is zero

Returns:

  • (Boolean)


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

def zero?
  cents == 0 
end