Class: Money
- Inherits:
-
Object
- Object
- Money
- Extended by:
- Constructors
- Includes:
- Comparable, Arithmetic, Formatting
- Defined in:
- lib/money/money.rb,
lib/money/version.rb,
lib/money/currency.rb,
lib/money/bank/base.rb,
lib/money/currency/loader.rb,
lib/money/money/arithmetic.rb,
lib/money/money/formatting.rb,
lib/money/money/constructors.rb,
lib/money/rates_store/memory.rb,
lib/money/currency/heuristics.rb,
lib/money/bank/single_currency.rb,
lib/money/bank/variable_exchange.rb
Overview
“Money is any object or record that is generally accepted as payment for goods and services and repayment of debts in a given socio-economic context or country.” -Wikipedia
An instance of Money represents an amount of a specific currency.
Money is a value object and should be treated as immutable.
Defined Under Namespace
Modules: Arithmetic, Bank, Constructors, Formatting, RatesStore Classes: Currency, UndefinedSmallestDenomination
Constant Summary collapse
- VERSION =
"6.8.4"
Class Attribute Summary collapse
-
.conversion_precision ⇒ Integer
Use this to specify precision for converting Rational to BigDecimal.
-
.default_bank ⇒ Money::Bank::Base
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.newis called without an explicit currency argument. -
.default_formatting_rules ⇒ Hash
Use this to define a default hash of rules for every time Money#format is called.
-
.infinite_precision ⇒ Boolean
Use this to enable infinite precision cents.
-
.rounding_mode(mode = nil) ⇒ BigDecimal::ROUND_MODE, Yield
Use this to return the rounding mode.
-
.use_i18n ⇒ Boolean
Use this to disable i18n even if it’s used by other objects in your app.
Instance Attribute Summary collapse
-
#bank ⇒ Object
readonly
Returns the value of attribute bank.
-
#currency ⇒ Currency
readonly
The money’s currency.
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.
-
.disallow_currency_conversion! ⇒ Object
Sets the default bank to be a SingleCurrency bank that raises on currency exchange.
-
.from_amount(amount, currency = default_currency, bank = default_bank) ⇒ Money
Creates a new Money object of value given in the
unitof the givencurrency. - .inherited(base) ⇒ Object
- .setup_defaults ⇒ Object
Instance Method Summary collapse
-
#allocate(splits) ⇒ Array<Money>
Allocates money between different parties without losing pennies.
-
#amount ⇒ BigDecimal
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 United States dollar.
-
#cents ⇒ Integer, BigDecimal
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.
- #default_formatting_rules ⇒ Object
-
#dollars ⇒ BigDecimal
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) {|n| ... } ⇒ Money
Receive the amount of this money object in another Currency.
-
#fractional ⇒ Integer, BigDecimal
The value of the monetary amount represented in the fractional or subunit of the currency.
-
#hash ⇒ Integer
Returns a Integer hash value based on the
fractionalandcurrencyattributes in order to use functions like & (intersection), group_by, etc. -
#initialize(obj, 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
-
#round(rounding_mode = self.class.rounding_mode) ⇒ Money
Round the monetary amount to smallest unit of coinage.
-
#round_to_nearest_cash_value ⇒ Integer, BigDecimal
Round a given amount of money to the nearest possible amount in cash value.
-
#split(num) ⇒ Array<Money>
Split money amongst parties evenly without losing pennies.
-
#symbol ⇒ String
Uses Currency#symbol.
- #symbol_position_from(rules) ⇒ Object
- #symbol_value_from(rules) ⇒ Object
-
#to_d ⇒ BigDecimal
Return the amount of money as a BigDecimal.
-
#to_f ⇒ Float
Return the amount of money as a float.
-
#to_i ⇒ Integer
Return the amount of money as a Integer.
-
#to_money(given_currency = nil) ⇒ self
Conversation to
self. -
#to_s ⇒ String
Returns the amount of money as a string.
- #translate_formatting_rules(rules) ⇒ Object
Methods included from Constructors
ca_dollar, empty, euro, pound_sterling, us_dollar
Methods included from Formatting
#decimal_mark, #format, #thousands_separator
Methods included from Arithmetic
#%, #*, #+, #-, #-@, #/, #<=>, #==, #abs, #coerce, #div, #divmod, #eql?, #modulo, #negative?, #nonzero?, #positive?, #remainder, #zero?
Constructor Details
#initialize(obj, currency = Money.default_currency, bank = Money.default_bank) ⇒ Money
Creates a new Money object of value given in the fractional unit of the given currency.
Alternatively you can use the convenience methods like Money::Constructors#ca_dollar and Money::Constructors#us_dollar.
258 259 260 261 262 263 |
# File 'lib/money/money.rb', line 258 def initialize(obj, currency = Money.default_currency, bank = Money.default_bank) @fractional = obj.respond_to?(:fractional) ? obj.fractional : as_d(obj) @currency = obj.respond_to?(:currency) ? obj.currency : Currency.wrap(currency) @currency ||= Money.default_currency @bank = obj.respond_to?(:bank) ? obj.bank : bank end |
Class Attribute Details
.conversion_precision ⇒ Integer
122 123 |
# File 'lib/money/money.rb', line 122 attr_accessor :default_bank, :default_formatting_rules, :use_i18n, :infinite_precision, :conversion_precision |
.default_bank ⇒ Money::Bank::Base
122 123 124 |
# File 'lib/money/money.rb', line 122 def default_bank @default_bank end |
.default_currency ⇒ Money::Currency
132 |
# File 'lib/money/money.rb', line 132 attr_writer :rounding_mode, :default_currency |
.default_formatting_rules ⇒ Hash
Returns Use this to define a default hash of rules for every time Money#format is called. Rules provided on method call will be merged with the default ones. To overwrite a rule, just provide the intended value while calling format.
122 123 |
# File 'lib/money/money.rb', line 122 attr_accessor :default_bank, :default_formatting_rules, :use_i18n, :infinite_precision, :conversion_precision |
.infinite_precision ⇒ Boolean
122 123 |
# File 'lib/money/money.rb', line 122 attr_accessor :default_bank, :default_formatting_rules, :use_i18n, :infinite_precision, :conversion_precision |
.rounding_mode(mode = nil) ⇒ BigDecimal::ROUND_MODE, Yield
Use this to return the rounding mode. You may also pass a rounding mode and a block to temporarily change it. It will then return the results of the block instead.
182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/money/money.rb', line 182 def self.rounding_mode(mode=nil) if mode.nil? Thread.current[:money_rounding_mode] || @rounding_mode else begin Thread.current[:money_rounding_mode] = mode yield ensure Thread.current[:money_rounding_mode] = nil end end end |
.use_i18n ⇒ Boolean
122 123 |
# File 'lib/money/money.rb', line 122 attr_accessor :default_bank, :default_formatting_rules, :use_i18n, :infinite_precision, :conversion_precision |
Instance Attribute Details
#bank ⇒ Object (readonly)
Returns the value of attribute bank.
87 |
# File 'lib/money/money.rb', line 87 attr_reader :currency, :bank |
#currency ⇒ Currency (readonly)
87 88 89 |
# File 'lib/money/money.rb', line 87 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.
206 207 208 |
# File 'lib/money/money.rb', line 206 def self.add_rate(from_currency, to_currency, rate) Money.default_bank.add_rate(from_currency, to_currency, rate) end |
.disallow_currency_conversion! ⇒ Object
Sets the default bank to be a SingleCurrency bank that raises on currency exchange. Useful when apps operate in a single currency at a time.
212 213 214 |
# File 'lib/money/money.rb', line 212 def self.disallow_currency_conversion! self.default_bank = Bank::SingleCurrency.instance end |
.from_amount(amount, currency = default_currency, bank = default_bank) ⇒ Money
Creates a new Money object of value given in the unit of the given currency.
230 231 232 233 234 235 236 |
# File 'lib/money/money.rb', line 230 def self.from_amount(amount, currency = default_currency, bank = default_bank) Numeric === amount or raise ArgumentError, "'amount' must be numeric" currency = Currency.wrap(currency) || Money.default_currency value = amount.to_d * currency.subunit_to_unit value = value.round(0, rounding_mode) unless infinite_precision new(value, currency, bank) end |
.inherited(base) ⇒ Object
164 165 166 |
# File 'lib/money/money.rb', line 164 def self.inherited(base) base.setup_defaults end |
.setup_defaults ⇒ Object
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/money/money.rb', line 144 def self.setup_defaults # Set the default bank for creating new +Money+ objects. self.default_bank = Bank::VariableExchange.instance # Set the default currency for creating new +Money+ object. self.default_currency = Currency.new("USD") # Default to using i18n self.use_i18n = true # Default to not using infinite precision cents self.infinite_precision = false # Default to bankers rounding self.rounding_mode = BigDecimal::ROUND_HALF_EVEN # Default the conversion of Rationals precision to 16 self.conversion_precision = 16 end |
Instance Method Details
#allocate(splits) ⇒ Array<Money>
Allocates money between different parties without losing pennies. After the mathematical split has been performed, leftover pennies will be distributed round-robin amongst the parties. This means that parties listed first will likely receive more pennies than ones that are listed later
489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 |
# File 'lib/money/money.rb', line 489 def allocate(splits) allocations = allocations_from_splits(splits) if (allocations - BigDecimal("1")) > Float::EPSILON raise ArgumentError, "splits add to more then 100%" end amounts, left_over = amounts_from_splits(allocations, splits) unless self.class.infinite_precision delta = left_over > 0 ? 1 : -1 # Distribute left over pennies amongst allocations left_over.to_i.abs.times { |i| amounts[i % amounts.length] += delta } end amounts.collect { |fractional| self.class.new(fractional, currency) } end |
#amount ⇒ BigDecimal
Returns the numerical value of the money
294 295 296 |
# File 'lib/money/money.rb', line 294 def amount to_d end |
#as_ca_dollar ⇒ Money
Receive a money object with the same amount as the current Money object in Canadian dollar.
460 461 462 |
# File 'lib/money/money.rb', line 460 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.
472 473 474 |
# File 'lib/money/money.rb', line 472 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 United States dollar.
448 449 450 |
# File 'lib/money/money.rb', line 448 def as_us_dollar exchange_to("USD") end |
#cents ⇒ Integer, BigDecimal
Convenience method for fractional part of the amount. Synonym of #fractional
32 33 34 |
# File 'lib/money/money.rb', line 32 def cents fractional end |
#currency_as_string ⇒ String
Return string representation of currency object
304 305 306 |
# File 'lib/money/money.rb', line 304 def currency_as_string currency.to_s end |
#currency_as_string=(val) ⇒ Money::Currency
Set currency object using a string
316 317 318 |
# File 'lib/money/money.rb', line 316 def currency_as_string=(val) @currency = Currency.wrap(val) end |
#default_formatting_rules ⇒ Object
355 356 357 |
# File 'lib/money/money/formatting.rb', line 355 def default_formatting_rules self.class.default_formatting_rules || {} end |
#dollars ⇒ BigDecimal
Assuming using a currency using dollars: Returns the value of the money in dollars, instead of in the fractional unit cents.
Synonym of #amount
280 281 282 |
# File 'lib/money/money.rb', line 280 def dollars amount end |
#exchange_to(other_currency) {|n| ... } ⇒ Money
Receive the amount of this money object in another Currency.
431 432 433 434 435 436 437 438 |
# File 'lib/money/money.rb', line 431 def exchange_to(other_currency, &rounding_method) other_currency = Currency.wrap(other_currency) if self.currency == other_currency self else @bank.exchange_with(self, other_currency, &rounding_method) end end |
#fractional ⇒ Integer, BigDecimal
The value of the monetary amount represented in the fractional or subunit of the currency.
For example, in the US dollar currency the fractional unit is cents, and there are 100 cents in one US dollar. So given the Money representation of one US dollar, the fractional interpretation is 100.
Another example is that of the Kuwaiti dinar. In this case the fractional unit is the fils and there 1000 fils to one Kuwaiti dinar. So given the Money representation of one Kuwaiti dinar, the fractional interpretation is 1000.
52 53 54 55 56 57 58 |
# File 'lib/money/money.rb', line 52 def fractional # Ensure we have a BigDecimal. If the Money object is created # from YAML, @fractional can end up being set to a Float. fractional = as_d(@fractional) return_value(fractional) end |
#hash ⇒ Integer
Returns a Integer hash value based on the fractional and currency attributes in order to use functions like & (intersection), group_by, etc.
327 328 329 |
# File 'lib/money/money.rb', line 327 def hash [fractional.hash, currency.hash].hash end |
#inspect ⇒ String
Common inspect function
344 345 346 |
# File 'lib/money/money.rb', line 344 def inspect "#<#{self.class.name} fractional:#{fractional} currency:#{currency}>" end |
#localize_formatting_rules(rules) ⇒ Object
382 383 384 385 386 387 388 389 |
# File 'lib/money/money/formatting.rb', line 382 def localize_formatting_rules(rules) if currency.iso_code == "JPY" && I18n.locale == :ja rules[:symbol] = "円" unless rules[:symbol] == false rules[:symbol_position] = :after rules[:symbol_after_without_space] = true end rules end |
#regexp_format(formatted, rules, decimal_mark, symbol_value) ⇒ Object
359 360 361 362 363 364 365 366 367 368 369 370 371 |
# File 'lib/money/money/formatting.rb', line 359 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.to_s, "") =~ /#{regexp_decimal}/ /(\d)(?=(?:\d{3})+(?:#{regexp_decimal}))/ else /(\d)(?=(?:\d{3})+(?:[^\d]{1}|$))/ end end end |
#round(rounding_mode = self.class.rounding_mode) ⇒ Money
This method is only useful when operating with infinite_precision turned on. Without infinite_precision values are rounded to the smallest unit of coinage automatically.
Round the monetary amount to smallest unit of coinage.
540 541 542 543 544 545 546 |
# File 'lib/money/money.rb', line 540 def round(rounding_mode = self.class.rounding_mode) if self.class.infinite_precision self.class.new(fractional.round(0, rounding_mode), self.currency) else self end end |
#round_to_nearest_cash_value ⇒ Integer, BigDecimal
Round a given amount of money to the nearest possible amount in cash value. For example, in Swiss franc (CHF), the smallest possible amount of cash value is CHF 0.05. Therefore, this method rounds CHF 0.07 to CHF 0.05, and CHF 0.08 to CHF 0.10.
69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/money/money.rb', line 69 def round_to_nearest_cash_value unless self.currency.smallest_denomination raise UndefinedSmallestDenomination, 'Smallest denomination of this currency is not defined' end fractional = as_d(@fractional) smallest_denomination = as_d(self.currency.smallest_denomination) rounded_value = (fractional / smallest_denomination).round(0, self.class.rounding_mode) * smallest_denomination return_value(rounded_value) end |
#split(num) ⇒ Array<Money>
Split money amongst parties evenly without losing pennies.
515 516 517 518 519 520 521 522 523 |
# 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 split_infinite(num) else split_flat(num) end end |
#symbol ⇒ String
Uses Currency#symbol. If nil is returned, defaults to “¤”.
337 338 339 |
# File 'lib/money/money.rb', line 337 def symbol currency.symbol || "¤" end |
#symbol_position_from(rules) ⇒ Object
413 414 415 416 417 418 419 420 421 422 423 424 425 |
# File 'lib/money/money/formatting.rb', line 413 def symbol_position_from(rules) if rules.has_key?(:symbol_position) if [:before, :after].include?(rules[:symbol_position]) return rules[:symbol_position] else raise ArgumentError, ":symbol_position must be ':before' or ':after'" end elsif currency.symbol_first? :before else :after end end |
#symbol_value_from(rules) ⇒ Object
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 |
# File 'lib/money/money/formatting.rb', line 391 def symbol_value_from(rules) if rules.has_key?(:symbol) if rules[:symbol] === true if rules[:disambiguate] && currency.disambiguate_symbol currency.disambiguate_symbol else symbol end elsif rules[:symbol] rules[:symbol] else "" end elsif rules[:html] currency.html_entity == '' ? currency.symbol : currency.html_entity elsif rules[:disambiguate] && currency.disambiguate_symbol currency.disambiguate_symbol else symbol end end |
#to_d ⇒ BigDecimal
Return the amount of money as a BigDecimal.
376 377 378 |
# File 'lib/money/money.rb', line 376 def to_d as_d(fractional) / as_d(currency.subunit_to_unit) 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 floats.
399 400 401 |
# File 'lib/money/money.rb', line 399 def to_f to_d.to_f end |
#to_i ⇒ Integer
Return the amount of money as a Integer.
386 387 388 |
# File 'lib/money/money.rb', line 386 def to_i to_d.to_i end |
#to_money(given_currency = nil) ⇒ self
Conversation to self.
406 407 408 409 410 411 412 413 |
# File 'lib/money/money.rb', line 406 def to_money(given_currency = nil) given_currency = Currency.wrap(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.
354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 |
# File 'lib/money/money.rb', line 354 def to_s unit, subunit, fraction = strings_from_fractional str = if currency.decimal_places == 0 if fraction == "" unit else "#{unit}#{decimal_mark}#{fraction}" end else "#{unit}#{decimal_mark}#{pad_subunit(subunit)}#{fraction}" end fractional < 0 ? "-#{str}" : str end |
#translate_formatting_rules(rules) ⇒ Object
373 374 375 376 377 378 379 380 |
# File 'lib/money/money/formatting.rb', line 373 def translate_formatting_rules(rules) begin rules[:symbol] = I18n.t currency.iso_code, :scope => "number.currency.symbol", :raise => true rescue I18n::MissingTranslationData # Do nothing end rules end |