Class: Money
- Inherits:
-
Object
- Object
- Money
- 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
-
.assume_from_symbol ⇒ true, false
Use this to enable the ability to assume the currency from a passed symbol.
-
.conversion_precision ⇒ Integer
Use this to specify precision for converting Rational to BigDecimal.
-
.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. -
.infinite_precision ⇒ true, false
Use this to enable infinite precision cents.
-
.rounding_mode ⇒ BigDecimal::ROUND_MODE
Use this to specify the rounding mode.
-
.use_i18n ⇒ true, false
Use this to disable i18n even if it’s used by other objects in your app.
Instance Attribute Summary collapse
-
#bank ⇒ Money::Bank::*
readonly
The
Money::Bank
based object used to perform currency exchanges with. -
#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.
-
.new_with_amount(amount, currency = Money.default_currency, bank = Money.default_bank) ⇒ Money
Creates a new Money object of
amount
value , with givencurrency
. -
.new_with_dollars(*args) ⇒ Object
Synonym of #new_with_amount.
-
.us_dollar(cents) ⇒ Money
Creates a new Money object of the given value, using the American dollar currency.
Instance Method Summary collapse
-
#allocate(splits) ⇒ Array<Money, Money, Money>
Allocates money between different parties without loosing pennies.
-
#amount ⇒ Float
Returns the numerical value of the money.
-
#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.
-
#cents ⇒ Integer
Convenience method for fractional part of the amount.
-
#currency_as_string ⇒ String
Return string representation of currency object.
-
#currency_as_string=(val) ⇒ Money::Currency
Set currency object using a string.
-
#dollars ⇒ Float
Assuming using a currency using dollars: Returns the value of the money in dollars, instead of in the fractional unit cents.
-
#exchange_to(other_currency) ⇒ Money
Receive the amount of this money object in another Currency.
-
#fractional ⇒ Integer
The value of the amount represented in the fractional unit of the currency.
-
#hash ⇒ Fixnum
Returns a Fixnum hash value based on the
fractional
andcurrency
attributes in order to use functions like & (intersection), group_by, etc. -
#initialize(fractional, currency = Money.default_currency, bank = Money.default_bank) ⇒ Money
constructor
Creates a new Money object of value given in the fractional unit of the given
currency
. -
#inspect ⇒ String
Common inspect function.
- #localize_formatting_rules(rules) ⇒ Object
- #regexp_format(formatted, rules, decimal_mark, symbol_value) ⇒ Object
-
#split(num) ⇒ Array<Money, Money, Money>
Split money amongst parties evenly without loosing pennies.
-
#symbol ⇒ String
Uses Currency#symbol.
-
#to_d ⇒ BigDecimal
Return the amount of money as a BigDecimal.
-
#to_f ⇒ Float
Return the amount of money as a float.
-
#to_money(given_currency = nil) ⇒ self
Conversation to
self
. -
#to_s ⇒ String
Returns the amount of money as a string.
Methods included from Parsing
Methods included from Formatting
#decimal_mark, #format, #thousands_separator
Methods included from Arithmetic
#%, #*, #+, #-, #-@, #/, #<=>, #==, #abs, #div, #divmod, #eql?, #modulo, #negative?, #nonzero?, #positive?, #remainder, #zero?
Constructor Details
#initialize(fractional, currency = Money.default_currency, bank = Money.default_bank) ⇒ Money
240 241 242 243 244 245 246 247 248 249 250 |
# File 'lib/money/money.rb', line 240 def initialize(fractional, currency = Money.default_currency, bank = Money.default_bank) @fractional = if fractional.is_a?(Rational) fractional.to_d(self.class.conversion_precision) elsif fractional.respond_to?(:to_d) fractional.to_d else BigDecimal.new(fractional.to_s) end @currency = Currency.wrap(currency) @bank = bank end |
Class Attribute Details
.assume_from_symbol ⇒ true, false
Use this to enable the ability to assume the currency from a passed symbol
71 72 73 |
# File 'lib/money/money.rb', line 71 def assume_from_symbol @assume_from_symbol end |
.conversion_precision ⇒ Integer
Use this to specify precision for converting Rational to BigDecimal
86 87 88 |
# File 'lib/money/money.rb', line 86 def conversion_precision @conversion_precision end |
.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 of Bank::VariableExchange.
It allows one to specify custom exchange rates.
54 55 56 |
# File 'lib/money/money.rb', line 54 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.
61 62 63 |
# File 'lib/money/money.rb', line 61 def default_currency @default_currency end |
.infinite_precision ⇒ true, false
Use this to enable infinite precision cents
76 77 78 |
# File 'lib/money/money.rb', line 76 def infinite_precision @infinite_precision end |
.rounding_mode ⇒ BigDecimal::ROUND_MODE
Use this to specify the rounding mode
81 82 83 |
# File 'lib/money/money.rb', line 81 def rounding_mode @rounding_mode end |
.use_i18n ⇒ true, false
Use this to disable i18n even if it’s used by other objects in your app.
66 67 68 |
# File 'lib/money/money.rb', line 66 def use_i18n @use_i18n end |
Instance Attribute Details
#bank ⇒ Money::Bank::* (readonly)
The Money::Bank
based object used to perform currency exchanges with.
44 45 46 |
# File 'lib/money/money.rb', line 44 def bank @bank end |
#currency ⇒ Currency (readonly)
The currency the money is in.
39 40 41 |
# File 'lib/money/money.rb', line 39 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.
213 214 215 |
# File 'lib/money/money.rb', line 213 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.
133 134 135 |
# File 'lib/money/money.rb', line 133 def self.ca_dollar(cents) Money.new(cents, "CAD") end |
.empty(currency = default_currency) ⇒ Money
Create a new money object with value 0.
118 119 120 |
# File 'lib/money/money.rb', line 118 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.
162 163 164 |
# File 'lib/money/money.rb', line 162 def self.euro(cents) Money.new(cents, "EUR") end |
.new_with_amount(amount, currency = Money.default_currency, bank = Money.default_bank) ⇒ Money
Creates a new Money object of amount
value , with given currency
.
The amount value is expressed in the main monetary unit, opposite to the subunit-based representation used internally by this library called cents
.
189 190 191 192 193 194 |
# File 'lib/money/money.rb', line 189 def self.new_with_amount(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 |
.new_with_dollars(*args) ⇒ Object
Synonym of #new_with_amount
199 200 201 |
# File 'lib/money/money.rb', line 199 def self.new_with_dollars(*args) self.new_with_amount(*args) 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
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 |
# File 'lib/money/money.rb', line 478 def allocate(splits) allocations = splits.inject(BigDecimal("0")) do |sum, n| n = BigDecimal(n.to_s) unless n.is_a?(BigDecimal) sum + n end if (allocations - BigDecimal("1")) > Float::EPSILON raise ArgumentError, "splits add to more then 100%" end left_over = fractional amounts = splits.map do |ratio| if self.class.infinite_precision fraction = fractional * ratio else fraction = (fractional * ratio / allocations).floor left_over -= fraction fraction end end unless self.class.infinite_precision left_over.to_i.times { |i| amounts[i % amounts.length] += 1 } end amounts.collect { |fractional| Money.new(fractional, currency) } end |
#amount ⇒ Float
Returns the numerical value of the money
283 284 285 |
# File 'lib/money/money.rb', line 283 def amount to_f end |
#as_ca_dollar ⇒ Money
Receive a money object with the same amount as the current Money object in canadian dollar.
450 451 452 |
# File 'lib/money/money.rb', line 450 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.
462 463 464 |
# File 'lib/money/money.rb', line 462 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.
438 439 440 |
# File 'lib/money/money.rb', line 438 def as_us_dollar exchange_to("USD") end |
#cents ⇒ Integer
Convenience method for fractional part of the amount. Synonym of #fractional
17 18 19 |
# File 'lib/money/money.rb', line 17 def cents fractional end |
#currency_as_string ⇒ String
Return string representation of currency object
293 294 295 |
# File 'lib/money/money.rb', line 293 def currency_as_string currency.to_s end |
#currency_as_string=(val) ⇒ Money::Currency
Set currency object using a string
305 306 307 |
# File 'lib/money/money.rb', line 305 def currency_as_string=(val) @currency = Currency.wrap(val) end |
#dollars ⇒ Float
Assuming using a currency using dollars: Returns the value of the money in dollars, instead of in the fractional unit cents.
Synonym of #amount
268 269 270 |
# File 'lib/money/money.rb', line 268 def dollars amount end |
#exchange_to(other_currency) ⇒ Money
Receive the amount of this money object in another Currency.
425 426 427 428 |
# File 'lib/money/money.rb', line 425 def exchange_to(other_currency) other_currency = Currency.wrap(other_currency) @bank.exchange_with(self, other_currency) end |
#fractional ⇒ Integer
The value of the amount represented in the fractional unit of the currency. Example: USD, 1 dollar (amount) == 100 cents (fractional unit).
24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/money/money.rb', line 24 def fractional if self.class.infinite_precision @fractional else # If the Money object is created from a serialized YAML string, # @fractional can end up being set to a Float. We need to ensure # it is BigDecimal before calling #round with two paramers. # Float class only provides #round with 0 or 1 parameter. BigDecimal.new(@fractional.to_s, 0).round(0, self.class.rounding_mode).to_i end end |
#hash ⇒ Fixnum
Returns a Fixnum hash value based on the fractional
and currency
attributes in order to use functions like & (intersection), group_by, etc.
316 317 318 |
# File 'lib/money/money.rb', line 316 def hash [fractional.hash, currency.hash].hash end |
#inspect ⇒ String
Common inspect function
333 334 335 |
# File 'lib/money/money.rb', line 333 def inspect "#<Money fractional:#{fractional} currency:#{currency}>" end |
#localize_formatting_rules(rules) ⇒ Object
307 308 309 310 311 312 313 314 |
# File 'lib/money/money/formatting.rb', line 307 def localize_formatting_rules(rules) if currency.iso_code == "JPY" && I18n.locale == :ja rules[:symbol] = "円" rules[:symbol_position] = :after rules[:symbol_after_without_space] = true end rules end |
#regexp_format(formatted, rules, decimal_mark, symbol_value) ⇒ Object
293 294 295 296 297 298 299 300 301 302 303 304 305 |
# File 'lib/money/money/formatting.rb', line 293 def regexp_format(formatted, rules, decimal_mark, symbol_value) regexp_decimal = Regexp.escape(decimal_mark) if rules[:south_asian_number_formatting] /(\d+?)(?=(\d\d)+(\d)(?:\.))/ else # Symbols may contain decimal marks (E.g "դր.") if formatted.sub(symbol_value, "") =~ /#{regexp_decimal}/ /(\d)(?=(?:\d{3})+(?:#{regexp_decimal}))/ else /(\d)(?=(?:\d{3})+(?:[^\d]{1}|$))/ end end end |
#split(num) ⇒ Array<Money, Money, Money>
Split money amongst parties evenly without loosing pennies.
515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 |
# File 'lib/money/money.rb', line 515 def split(num) raise ArgumentError, "need at least one party" if num < 1 if self.class.infinite_precision amt = self.div(BigDecimal(num.to_s)) return 1.upto(num).map{amt} end low = Money.new(fractional / num, self.currency) high = Money.new(low.fractional + 1, self.currency) remainder = fractional % num result = [] num.times do |index| result[index] = index < remainder ? high : low end result end |
#symbol ⇒ String
Uses Currency#symbol. If nil
is returned, defaults to “¤”.
326 327 328 |
# File 'lib/money/money.rb', line 326 def symbol currency.symbol || "¤" end |
#to_d ⇒ BigDecimal
Return the amount of money as a BigDecimal.
387 388 389 |
# File 'lib/money/money.rb', line 387 def to_d BigDecimal.new(fractional.to_s) / BigDecimal.new(currency.subunit_to_unit.to_s) 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.
400 401 402 |
# File 'lib/money/money.rb', line 400 def to_f to_d.to_f end |
#to_money(given_currency = nil) ⇒ self
Conversation to self
.
407 408 409 410 411 412 413 414 |
# File 'lib/money/money.rb', line 407 def to_money(given_currency = nil) given_currency = Currency.wrap(given_currency) if given_currency if given_currency.nil? || self.currency == given_currency self else exchange_to(given_currency) end end |
#to_s ⇒ String
Returns the amount of money as a string.
343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 |
# File 'lib/money/money.rb', line 343 def to_s unit, subunit = fractional().abs.divmod(currency.subunit_to_unit) unit_str = "" subunit_str = "" fraction_str = "" if self.class.infinite_precision subunit, fraction = subunit.divmod(BigDecimal("1")) unit_str = unit.to_i.to_s subunit_str = subunit.to_i.to_s fraction_str = fraction.to_s("F")[2..-1] # want fractional part "0.xxx" fraction_str = "" if fraction_str =~ /^0+$/ else unit_str, subunit_str = unit.to_s, subunit.to_s end absolute_str = if currency.decimal_places == 0 if fraction_str == "" unit_str else "#{unit_str}#{decimal_mark}#{fraction_str}" end else # need to pad subunit to right position, # for example 1 usd 3 cents should be 1.03 not 1.3 subunit_str.insert(0, '0') while subunit_str.length < currency.decimal_places "#{unit_str}#{decimal_mark}#{subunit_str}#{fraction_str}" end absolute_str.tap do |str| str.insert(0, "-") if fractional() < 0 end end |