Class: Money
Overview
Usage with ActiveRecord
Use the compose_of helper to let active record deal with embedding the money object in your models. The following example requires a cents and a currency field.
class ProductUnit < ActiveRecord::Base
belongs_to :product
composed_of :price, :class_name => "Money", :mapping => [ %w(cents cents), %w(currency currency) ]
private
validate :cents_not_zero
def cents_not_zero
errors.add("cents", "cannot be zero or less") unless cents > 0
end
validates_presence_of :sku, :currency
validates_uniqueness_of :sku
end
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
-
#cents ⇒ Object
readonly
get the cents value of the object.
-
#currency ⇒ Object
readonly
Returns the value of attribute currency.
-
#precision ⇒ Object
readonly
Returns the value of attribute precision.
Class Method Summary collapse
-
.ca_dollar(num) ⇒ Object
Create a new money object using the Canadian dollar currency.
-
.empty(currency = default_currency) ⇒ Object
Create a new money object with value 0.
-
.euro(num) ⇒ Object
Create a new money object using the Euro currency.
-
.us_dollar(num) ⇒ Object
Create a new money object using the American dollar currency.
Instance Method Summary collapse
-
#*(fixnum) ⇒ Object
multiply money by fixnum.
- #+(other_money) ⇒ Object
- #-(other_money) ⇒ Object
-
#/(fixnum) ⇒ Object
divide money by fixnum.
- #<=>(other_money) ⇒ Object
-
#as_ca_dollar ⇒ Object
Recieve a money object with the same amount as the current Money object in canadian dollar.
-
#as_ca_euro ⇒ Object
Recieve a money object with the same amount as the current Money object in euro.
-
#as_us_dollar ⇒ Object
Recieve a money object with the same amount as the current Money object in american dollar.
-
#eql?(other_money) ⇒ Boolean
Do two money objects equal? Only works if both objects are of the same currency.
-
#exchange_to(other_currency) ⇒ Object
Recieve the amount of this money object in another currency.
-
#format(*rules) ⇒ Object
Format the price according to several rules Currently supported are :with_currency, :no_cents and :html.
-
#initialize(cents, currency = default_currency, precision = 2) ⇒ Money
constructor
Creates a new money object.
-
#to_money ⇒ Object
Conversation to self.
- #to_precision(new_precision) ⇒ Object
-
#to_s(show_precision = precision) ⇒ Object
Money.ca_dollar(100).to_s => “1.00”.
-
#zero? ⇒ Boolean
Test if the money amount is zero.
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
51 52 53 |
# File 'lib/money/money.rb', line 51 def initialize(cents, currency = default_currency, precision = 2) @cents, @currency, @precision = cents.round, currency, precision end |
Instance Attribute Details
#cents ⇒ Object (readonly)
get the cents value of the object
83 84 85 |
# File 'lib/money/money.rb', line 83 def cents @cents end |
#currency ⇒ Object (readonly)
Returns the value of attribute currency.
24 25 26 |
# File 'lib/money/money.rb', line 24 def currency @currency end |
#precision ⇒ Object (readonly)
Returns the value of attribute precision.
24 25 26 |
# File 'lib/money/money.rb', line 24 def precision @precision end |
Class Method Details
.ca_dollar(num) ⇒ Object
Create a new money object using the Canadian dollar currency
166 167 168 |
# File 'lib/money/money.rb', line 166 def self.ca_dollar(num) Money.new(num, "CAD") end |
.empty(currency = default_currency) ⇒ Object
Create a new money object with value 0
161 162 163 |
# File 'lib/money/money.rb', line 161 def self.empty(currency = default_currency) Money.new(0, currency) end |
Instance Method Details
#*(fixnum) ⇒ Object
multiply money by fixnum
88 89 90 |
# File 'lib/money/money.rb', line 88 def *(fixnum) Money.new(cents * fixnum, currency, precision) end |
#+(other_money) ⇒ Object
68 69 70 71 72 73 |
# File 'lib/money/money.rb', line 68 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
75 76 77 78 79 80 |
# File 'lib/money/money.rb', line 75 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 |
#/(fixnum) ⇒ Object
divide money by fixnum
93 94 95 |
# File 'lib/money/money.rb', line 93 def /(fixnum) Money.new(cents / fixnum, currency, precision) end |
#<=>(other_money) ⇒ Object
60 61 62 63 64 65 66 |
# File 'lib/money/money.rb', line 60 def <=>(other_money) if currency == other_money.currency cents <=> other_money.cents else cents <=> other_money.exchange_to(currency).cents end end |
#as_ca_dollar ⇒ Object
Recieve a money object with the same amount as the current Money object in canadian dollar
188 189 190 |
# File 'lib/money/money.rb', line 188 def as_ca_dollar exchange_to("CAD") end |
#as_ca_euro ⇒ Object
Recieve a money object with the same amount as the current Money object in euro
194 195 196 |
# File 'lib/money/money.rb', line 194 def as_ca_euro exchange_to("EUR") end |
#as_us_dollar ⇒ Object
Recieve a money object with the same amount as the current Money object in american dollar
182 183 184 |
# File 'lib/money/money.rb', line 182 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
56 57 58 |
# File 'lib/money/money.rb', line 56 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
150 151 152 |
# File 'lib/money/money.rb', line 150 def exchange_to(other_currency) self.class.bank.reduce(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>"
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/money/money.rb', line 124 def format(*rules) return "free" if cents == 0 rules = rules.flatten formatted = "$" + to_s(rules.include?(:no_cents) ? 0 : 2) 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 |
#to_money ⇒ Object
Conversation to self
199 200 201 |
# File 'lib/money/money.rb', line 199 def to_money self end |
#to_precision(new_precision) ⇒ Object
154 155 156 157 158 |
# File 'lib/money/money.rb', line 154 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, 'USD', new_precision) end |
#to_s(show_precision = precision) ⇒ Object
Money.ca_dollar(100).to_s => “1.00”
141 142 143 144 145 146 147 |
# File 'lib/money/money.rb', line 141 def to_s(show_precision = precision) if show_precision > 0 sprintf("%.#{show_precision}f", cents.to_f / 10 ** precision ) else sprintf("%d", cents.to_f / 10 ** (precision - show_precision) ) end end |
#zero? ⇒ Boolean
Test if the money amount is zero
98 99 100 |
# File 'lib/money/money.rb', line 98 def zero? cents == 0 end |