Class: Money
- Inherits:
-
Object
- Object
- Money
- Includes:
- Comparable
- Defined in:
- lib/money/money.rb,
lib/money/currency.rb,
lib/money/bank/base.rb,
lib/money/bank/variable_exchange.rb
Overview
Represents an amount of money in a given currency.
Defined Under Namespace
Modules: Bank Classes: Currency
Class Attribute Summary collapse
-
.default_bank ⇒ Money::Bank::*
Each Money object is associated to a bank object, which is responsible for currency exchange.
-
.default_currency ⇒ Money::Currency
The default currency, which is used when
Money.new
is called without an explicit currency argument.
Instance Attribute Summary collapse
-
#bank ⇒ Money::Bank::*
readonly
The
Money::Bank
based object used to perform currency exchanges with. -
#cents ⇒ Integer
readonly
The value of the money in cents.
-
#currency ⇒ Currency
readonly
The currency the money is in.
Class Method Summary collapse
-
.add_rate(from_currency, to_currency, rate) ⇒ Numeric
Adds a new exchange rate to the default bank and return the rate.
-
.ca_dollar(cents) ⇒ Money
Creates a new Money object of the given value, using the Canadian dollar currency.
-
.empty(currency = default_currency) ⇒ Money
Create a new money object with value 0.
-
.euro(cents) ⇒ Money
Creates a new Money object of the given value, using the Euro currency.
-
.from_bigdecimal(value, currency = Money.default_currency) ⇒ Money
Converts a BigDecimal into a Money object treating the
value
as dollars and converting them to the corresponding cents value, according tocurrency
subunit property, before instantiating the Money object. -
.from_fixnum(value, currency = Money.default_currency) ⇒ Money
Converts a Fixnum into a Money object treating the
value
as dollars and converting them to the corresponding cents value, according tocurrency
subunit property, before instantiating the Money object. -
.from_float(value, currency = Money.default_currency) ⇒ Money
Converts a Float into a Money object treating the
value
as dollars and converting them to the corresponding cents value, according tocurrency
subunit property, before instantiating the Money object. -
.from_numeric(value, currency = Money.default_currency) ⇒ Money
Converts a Numeric value into a Money object treating the
value
as dollars and converting them to the corresponding cents value, according tocurrency
subunit property, before instantiating the Money object. -
.from_string(value, currency = Money.default_currency) ⇒ Money
Converts a String into a Money object treating the
value
as dollars and converting them to the corresponding cents value, according tocurrency
subunit property, before instantiating the Money object. -
.new_with_dollars(amount, currency = Money.default_currency, bank = Money.default_bank) ⇒ Money
Creates a new Money object of
amount
value in dollars, with givencurrency
. -
.parse(input, currency = nil) ⇒ Money
Parses the current string and converts it to a
Money
object. -
.us_dollar(cents) ⇒ Money
Creates a new Money object of the given value, using the American dollar currency.
Instance Method Summary collapse
-
#%(val) ⇒ Money
Synonym for
#modulo
. -
#*(value) ⇒ Money
Multiplies the monetary value with the given number and returns a new
Money
object with this monetary value and the same currency. -
#+(other_money) ⇒ Money
Returns a new Money object containing the sum of the two operands’ monetary values.
-
#-(other_money) ⇒ Money
Returns a new Money object containing the difference between the two operands’ monetary values.
-
#/(value) ⇒ Money, Float
Divides the monetary value with the given number and returns a new
Money
object with this monetary value and the same currency. -
#<=>(other_money) ⇒ -1, ...
Compares this money object against another object.
-
#==(other_money) ⇒ Boolean
Checks whether two money objects have the same currency and the same amount.
-
#abs ⇒ Money
Return absolute value of self as a new Money object.
-
#as_ca_dollar ⇒ Money
Receive a money object with the same amount as the current Money object in canadian dollar.
-
#as_euro ⇒ Money
Receive a money object with the same amount as the current Money object in euro.
-
#as_us_dollar ⇒ Money
Receive a money object with the same amount as the current Money object in american dollars.
-
#currency_as_string ⇒ String
Return string representation of currency object.
-
#currency_as_string=(val) ⇒ Money::Currency
Set currency object using a string.
- #delimiter ⇒ Object
-
#div(value) ⇒ Money, Float
Synonym for
#/
. -
#divmod(val) ⇒ Array<Money,Money>, Array<Fixnum,Money>
Divide money by money or fixnum and return array containing quotient and modulus.
-
#dollars ⇒ Float
Returns the value of the money in dollars, instead of in cents.
-
#eql?(other_money) ⇒ Money
Synonymous with #==.
-
#exchange_to(other_currency) ⇒ Money
Receive the amount of this money object in another Currency.
-
#format(*rules) ⇒ String
Creates a formatted price string according to several rules.
-
#hash ⇒ Fixnum
Returns a Fixnum hash value based on the
cents
andcurrency
attributes in order to use functions like & (intersection), group_by, etc. -
#initialize(cents, currency = Money.default_currency, bank = Money.default_bank) ⇒ Money
constructor
Creates a new Money object of
cents
value in cents, with givencurrency
. -
#modulo(val) ⇒ Money
Equivalent to self.divmod(val).
-
#nonzero? ⇒ Money?
Test if the money amount is non-zero.
-
#remainder(val) ⇒ Money
If different signs self.modulo(val) - val otherwise self.modulo(val).
- #separator ⇒ Object
-
#symbol ⇒ String
Uses Currency#symbol.
-
#to_f ⇒ Float
Return the amount of money as a float.
-
#to_money ⇒ self
Conversation to
self
. -
#to_s ⇒ String
Returns the amount of money as a string.
-
#zero? ⇒ Boolean
Test if the money amount is zero.
Constructor Details
#initialize(cents, currency = Money.default_currency, bank = Money.default_bank) ⇒ Money
388 389 390 391 392 |
# File 'lib/money/money.rb', line 388 def initialize(cents, currency = Money.default_currency, bank = Money.default_bank) @cents = cents.round @currency = Currency.wrap(currency) @bank = bank end |
Class Attribute Details
.default_bank ⇒ Money::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.
31 32 33 |
# File 'lib/money/money.rb', line 31 def default_bank @default_bank end |
.default_currency ⇒ Money::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.
38 39 40 |
# File 'lib/money/money.rb', line 38 def default_currency @default_currency end |
Instance Attribute Details
#bank ⇒ Money::Bank::* (readonly)
The Money::Bank
based object used to perform currency exchanges with.
21 22 23 |
# File 'lib/money/money.rb', line 21 def bank @bank end |
#cents ⇒ Integer (readonly)
The value of the money in cents.
11 12 13 |
# File 'lib/money/money.rb', line 11 def cents @cents end |
#currency ⇒ Currency (readonly)
The currency the money is in.
16 17 18 |
# File 'lib/money/money.rb', line 16 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.
361 362 363 |
# File 'lib/money/money.rb', line 361 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.
70 71 72 |
# File 'lib/money/money.rb', line 70 def self.ca_dollar(cents) Money.new(cents, "CAD") end |
.empty(currency = default_currency) ⇒ Money
Create a new money object with value 0.
55 56 57 |
# File 'lib/money/money.rb', line 55 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.
99 100 101 |
# File 'lib/money/money.rb', line 99 def self.euro(cents) Money.new(cents, "EUR") end |
.from_bigdecimal(value, currency = Money.default_currency) ⇒ Money
Converts a BigDecimal into a Money object treating the value
as dollars and converting them to the corresponding cents value, according to currency
subunit property, before instantiating the Money object.
300 301 302 303 304 |
# File 'lib/money/money.rb', line 300 def self.from_bigdecimal(value, currency = Money.default_currency) currency = Money::Currency.wrap(currency) amount = value * currency.subunit_to_unit Money.new(amount.fix, currency) end |
.from_fixnum(value, currency = Money.default_currency) ⇒ Money
Converts a Fixnum into a Money object treating the value
as dollars and converting them to the corresponding cents value, according to currency
subunit property, before instantiating the Money object.
241 242 243 244 245 |
# File 'lib/money/money.rb', line 241 def self.from_fixnum(value, currency = Money.default_currency) currency = Money::Currency.wrap(currency) amount = value * currency.subunit_to_unit Money.new(amount, currency) end |
.from_float(value, currency = Money.default_currency) ⇒ Money
Converts a Float into a Money object treating the value
as dollars and converting them to the corresponding cents value, according to currency
subunit property, before instantiating the Money object.
Behind the scenes, this method relies on Money.from_bigdecimal to avoid problems with floating point precision.
273 274 275 |
# File 'lib/money/money.rb', line 273 def self.from_float(value, currency = Money.default_currency) from_bigdecimal(BigDecimal.new(value.to_s), currency) end |
.from_numeric(value, currency = Money.default_currency) ⇒ Money
Converts a Numeric value into a Money object treating the value
as dollars and converting them to the corresponding cents value, according to currency
subunit property, before instantiating the Money object.
This method relies on various Money.from_*
methods and tries to forwards the call to the most appropriate method in order to reduce computation effort. For instance, if value
is an Integer, this method calls from_fixnum instead of using the default from_bigdecimal which adds the overload to converts the value into a slower BigDecimal instance.
339 340 341 342 343 344 345 346 347 348 |
# File 'lib/money/money.rb', line 339 def self.from_numeric(value, currency = Money.default_currency) case value when Fixnum from_fixnum(value, currency) when Numeric from_bigdecimal(BigDecimal.new(value.to_s), currency) else raise ArgumentError, "`value' should be a Numeric object" end end |
.from_string(value, currency = Money.default_currency) ⇒ Money
Converts a String into a Money object treating the value
as dollars and converting them to the corresponding cents value, according to currency
subunit property, before instantiating the Money object.
Behind the scenes, this method relies on from_bigdecimal to avoid problems with string-to-numeric conversion.
214 215 216 |
# File 'lib/money/money.rb', line 214 def self.from_string(value, currency = Money.default_currency) from_bigdecimal(BigDecimal.new(value.to_s), currency) 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
.
128 129 130 131 132 133 |
# File 'lib/money/money.rb', line 128 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 |
.parse(input, currency = nil) ⇒ Money
Parses the current string and converts it to a Money
object. Excess characters will be discarded.
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/money/money.rb', line 162 def self.parse(input, currency = nil) i = input.to_s # Get the currency. m = i.scan /([A-Z]{2,3})/ c = m[0] ? m[0][0] : nil # check that currency passed and embedded currency are the same, # and negotiate the final currency if currency.nil? and c.nil? currency = Money.default_currency elsif currency.nil? currency = c elsif c.nil? currency = currency elsif currency != c # TODO: ParseError raise ArgumentError, "Mismatching Currencies" end currency = Money::Currency.wrap(currency) cents = extract_cents(i, currency) Money.new(cents, currency) end |
Instance Method Details
#%(val) ⇒ Money
Synonym for #modulo
.
648 649 650 |
# File 'lib/money/money.rb', line 648 def %(val) self.modulo(val) end |
#*(value) ⇒ Money
Multiplies the monetary value with the given number and returns a new Money
object with this monetary value and the same currency.
Note that you can’t multiply a Money object by an other Money
object.
559 560 561 562 563 564 565 |
# File 'lib/money/money.rb', line 559 def *(value) if value.is_a?(Money) raise ArgumentError, "Can't multiply a Money by a Money" else Money.new(cents * value, currency) end end |
#+(other_money) ⇒ Money
Returns a new Money object containing the sum of the two operands’ monetary values. If other_money
has a different currency then its monetary value is automatically exchanged to this object’s currency using exchange_to
.
518 519 520 521 522 523 524 |
# File 'lib/money/money.rb', line 518 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) ⇒ Money
Returns a new Money object containing the difference between the two operands’ monetary values. If other_money
has a different currency then its monetary value is automatically exchanged to this object’s currency using exchange_to
.
537 538 539 540 541 542 543 |
# File 'lib/money/money.rb', line 537 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 |
#/(value) ⇒ Money, Float
Divides the monetary value with the given number and returns a new Money
object with this monetary value and the same currency. Can also divide by another Money
object to get a ratio.
Money/Numeric
returns Money
. Money/Money
returns Float
.
582 583 584 585 586 587 588 589 590 591 592 |
# File 'lib/money/money.rb', line 582 def /(value) if value.is_a?(Money) if currency == value.currency (cents / BigDecimal.new(value.cents.to_s)).to_f else (cents / BigDecimal(value.exchange_to(currency).cents.to_s)).to_f end else Money.new(cents / value, currency) end end |
#<=>(other_money) ⇒ -1, ...
Compares this money object against another object. other_money
must respond to #to_money. Returns -1 when less than, 0 when equal and 1 when greater than.
If other_money
is a different currency, then other_money
will first be converted into this money object’s currency by calling #exchange
on other_money
.
Comparisons against objects that do not respond to #to_money will cause an ArgumentError
to be raised.
495 496 497 498 499 500 501 502 503 504 505 506 |
# File 'lib/money/money.rb', line 495 def <=>(other_money) if other_money.respond_to?(:to_money) other_money = other_money.to_money if self.currency == other_money.currency cents <=> other_money.cents else cents <=> other_money.exchange_to(currency).cents end else raise ArgumentError, "Comparison of #{self.class} with #{other_money.inspect} failed" end end |
#==(other_money) ⇒ Boolean
Checks whether two money objects have the same currency and the same amount. Checks against money objects with a different currency and checks against objects that do not respond to #to_money will always return false.
443 444 445 446 447 448 449 450 |
# File 'lib/money/money.rb', line 443 def ==(other_money) if other_money.respond_to?(:to_money) other_money = other_money.to_money cents == other_money.cents && self.currency == other_money.currency else false end end |
#abs ⇒ Money
Return absolute value of self as a new Money object.
678 679 680 |
# File 'lib/money/money.rb', line 678 def abs Money.new(self.cents.abs, self.currency) end |
#as_ca_dollar ⇒ Money
Receive a money object with the same amount as the current Money object in canadian dollar.
957 958 959 |
# File 'lib/money/money.rb', line 957 def as_ca_dollar exchange_to("CAD") end |
#as_euro ⇒ Money
Receive a money object with the same amount as the current Money object in euro.
969 970 971 |
# File 'lib/money/money.rb', line 969 def as_euro exchange_to("EUR") end |
#as_us_dollar ⇒ Money
Receive a money object with the same amount as the current Money object in american dollars.
945 946 947 |
# File 'lib/money/money.rb', line 945 def as_us_dollar exchange_to("USD") end |
#currency_as_string ⇒ String
Return string representation of currency object
416 417 418 |
# File 'lib/money/money.rb', line 416 def currency_as_string self.currency.to_s end |
#currency_as_string=(val) ⇒ Money::Currency
Set currency object using a string
428 429 430 |
# File 'lib/money/money.rb', line 428 def currency_as_string=(val) @currency = Currency.wrap(val) end |
#delimiter ⇒ Object
724 725 726 |
# File 'lib/money/money.rb', line 724 def delimiter I18n.t(:"number.format.delimiter", :default => currency.delimiter || ",") end |
#div(value) ⇒ Money, Float
Synonym for #/
.
603 604 605 |
# File 'lib/money/money.rb', line 603 def div(value) self / value end |
#divmod(val) ⇒ Array<Money,Money>, Array<Fixnum,Money>
Divide money by money or fixnum and return array containing quotient and modulus.
617 618 619 620 621 622 623 624 625 626 |
# File 'lib/money/money.rb', line 617 def divmod(val) if val.is_a?(Money) a = self.cents b = self.currency == val.currency ? val.cents : val.exchange_to(self.currency).cents q, m = a.divmod(b) return [q, Money.new(m, self.currency)] else return [self.div(val), Money.new(self.cents.modulo(val), self.currency)] end end |
#dollars ⇒ Float
Returns the value of the money in dollars, instead of in cents.
406 407 408 |
# File 'lib/money/money.rb', line 406 def dollars to_f end |
#eql?(other_money) ⇒ Money
Synonymous with #==.
459 460 461 |
# File 'lib/money/money.rb', line 459 def eql?(other_money) self == other_money end |
#exchange_to(other_currency) ⇒ Money
Receive the amount of this money object in another Currency.
932 933 934 935 |
# File 'lib/money/money.rb', line 932 def exchange_to(other_currency) other_currency = Currency.wrap(other_currency) @bank.exchange_with(self, other_currency) end |
#format(*rules) ⇒ String
Creates a formatted price string according to several rules.
839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 |
# File 'lib/money/money.rb', line 839 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_value = symbol elsif rules[:symbol] symbol_value = rules[:symbol] else symbol_value = "" end else symbol_value = symbol end formatted = case rules[:no_cents] when true "#{symbol_value}#{self.to_s.to_i}" else "#{symbol_value}#{self.to_s}" end if rules.has_key?(:separator) and rules[:separator] and rules[:separator] != separator formatted.sub!(separator, rules[:separator]) end delimiter_value = delimiter # Determine delimiter if rules.has_key?(:delimiter) if rules[:delimiter] === false or rules[:delimiter].nil? delimiter_value = "" elsif rules[:delimiter] delimiter_value = rules[:delimiter] end end # Apply delimiter formatted.gsub!(/(\d)(?=(?:\d{3})+(?:\.|,|$))(\d{3}\..*)?/, "\\1#{delimiter_value}\\2") if rules[:with_currency] formatted << " " formatted << '<span class="currency">' if rules[:html] formatted << currency.to_s formatted << '</span>' if rules[:html] end formatted end |
#hash ⇒ Fixnum
Returns a Fixnum hash value based on the cents
and currency
attributes in order to use functions like & (intersection), group_by, etc.
470 471 472 |
# File 'lib/money/money.rb', line 470 def hash [cents.hash, currency.hash].hash end |
#modulo(val) ⇒ Money
Equivalent to self.divmod(val)
637 638 639 |
# File 'lib/money/money.rb', line 637 def modulo(val) self.divmod(val)[1] end |
#nonzero? ⇒ Money?
Test if the money amount is non-zero. Returns this money object if it is non-zero, or nil otherwise, like Numeric#nonzero?.
701 702 703 |
# File 'lib/money/money.rb', line 701 def nonzero? cents != 0 ? self : nil end |
#remainder(val) ⇒ Money
If different signs self.modulo(val) - val otherwise self.modulo(val)
660 661 662 663 664 665 666 667 668 669 670 |
# File 'lib/money/money.rb', line 660 def remainder(val) a, b = self, val b = b.exchange_to(a.currency) if b.is_a?(Money) and a.currency != b.currency a_sign, b_sign = :pos, :pos a_sign = :neg if a.cents < 0 b_sign = :neg if (b.is_a?(Money) and b.cents < 0) or (b < 0) return a.modulo(b) if a_sign == b_sign a.modulo(b) - (b.is_a?(Money) ? b : Money.new(b, a.currency)) end |
#separator ⇒ Object
742 743 744 |
# File 'lib/money/money.rb', line 742 def separator I18n.t(:"number.format.separator", :default => currency.separator || ".") end |
#symbol ⇒ String
Uses Currency#symbol. If nil
is returned, defaults to “¤”.
711 712 713 |
# File 'lib/money/money.rb', line 711 def symbol currency.symbol || "¤" end |
#to_f ⇒ Float
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.
919 920 921 |
# File 'lib/money/money.rb', line 919 def to_f (BigDecimal.new(cents.to_s) / currency.subunit_to_unit).to_f end |
#to_money ⇒ self
Conversation to self
.
976 977 978 |
# File 'lib/money/money.rb', line 976 def to_money self end |
#to_s ⇒ String
Returns the amount of money as a string.
902 903 904 905 906 907 908 |
# File 'lib/money/money.rb', line 902 def to_s decimal_places = Math.log10(currency.subunit_to_unit).ceil unit, subunit = cents.divmod(currency.subunit_to_unit).map{|o| o.to_s} return unit if decimal_places == 0 subunit = (subunit + ("0" * decimal_places))[0, decimal_places] "#{unit}#{separator}#{subunit}" end |
#zero? ⇒ Boolean
Test if the money amount is zero.
689 690 691 |
# File 'lib/money/money.rb', line 689 def zero? cents == 0 end |