Class: Money
- Inherits:
-
Object
- Object
- Money
- Extended by:
- Constructors
- Includes:
- Comparable, Arithmetic
- 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/formatter.rb,
lib/money/money/allocation.rb,
lib/money/money/arithmetic.rb,
lib/money/money/constructors.rb,
lib/money/rates_store/memory.rb,
lib/money/currency/heuristics.rb,
lib/money/locale_backend/base.rb,
lib/money/locale_backend/i18n.rb,
lib/money/bank/single_currency.rb,
lib/money/money/locale_backend.rb,
lib/money/locale_backend/errors.rb,
lib/money/bank/variable_exchange.rb,
lib/money/money/formatting_rules.rb,
lib/money/locale_backend/currency.rb,
sig/lib/money/money.rbs,
sig/lib/money/currency.rbs,
sig/lib/money/bank/base.rbs,
sig/lib/money/money/formatter.rbs,
sig/lib/money/money/allocation.rbs,
sig/lib/money/money/arithmetic.rbs,
sig/lib/money/money/constructors.rbs,
sig/lib/money/rates_store/memory.rbs,
sig/lib/money/currency/heuristics.rbs,
sig/lib/money/locale_backend/base.rbs,
sig/lib/money/locale_backend/i18n.rbs,
sig/lib/money/bank/single_currency.rbs,
sig/lib/money/money/locale_backend.rbs,
sig/lib/money/locale_backend/errors.rbs,
sig/lib/money/bank/variable_exchange.rbs,
sig/lib/money/money/formatting_rules.rbs
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, LocaleBackend, RatesStore Classes: Allocation, Currency, Formatter, FormattingRules, UndefinedSmallestDenomination
Constant Summary collapse
- VERSION =
"7.1.0"
Class Attribute Summary collapse
-
.conversion_precision ⇒ Object
Returns the value of attribute conversion_precision.
-
.default_bank ⇒ Object
Modified to support thread-local bank override.
- .default_currency ⇒ Money::Currency
-
.default_formatting_rules ⇒ Object
Returns the value of attribute default_formatting_rules.
-
.default_infinite_precision ⇒ Object
Returns the value of attribute default_infinite_precision.
-
.locale_backend ⇒ Object
Returns the value of attribute locale_backend.
-
.rounding_mode ⇒ BigDecimal::ROUND_MODE
Use this to return the rounding mode.
-
.strict_eql_compare ⇒ Object
Returns the value of attribute strict_eql_compare.
Instance Attribute Summary collapse
-
#bank ⇒ Object
readonly
Returns the value of attribute bank.
-
#conversion_precision ⇒ Integer
Used to specify precision for converting Rational to BigDecimal.
-
#currency ⇒ Currency
readonly
The money's currency.
-
#default_bank ⇒ Money::Bank::Base
Used to set a default bank 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
Used to define a default hash of rules for every time
Money#formatis called. -
#default_infinite_precision ⇒ Boolean
Use this to enable infinite precision cents as the global default.
-
#strict_eql_compare ⇒ Boolean
Use this to specify how
Money#eql?behaves.
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, options = {}) ⇒ Money
Creates a new Money object of value given in the
unitof the givencurrency. -
.from_dollars(amount, currency = default_currency, options = {}) ⇒ Money
DEPRECATED.
- .inherited(base) ⇒ Object
- .setup_defaults ⇒ Object
-
.with_bank(bank) { ... } ⇒ Object
Temporarily changes the default bank in the current thread only.
-
.with_rounding_mode(mode) { ... } ⇒ Object
Temporarily changes the rounding mode in a given block.
Instance Method Summary collapse
-
#allocate(parts) ⇒ Array<Money>
(also: #split)
Splits a given amount in parts 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_d(num) ⇒ Object
-
#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.
-
#decimal_mark ⇒ String
Returns a decimal mark according to the locale.
-
#dollars ⇒ BigDecimal
DEPRECATED.
- #dup_with(options = {}) ⇒ Object
-
#exchange_to(other_currency) {|n| ... } ⇒ Money
Receive the amount of this money object in another Currency.
-
#format(*rules) ⇒ String
Creates a formatted price string according to several rules.
-
#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 = nil, options = {}) ⇒ Money
constructor
Creates a new Money object of value given in the
fractional unitof the givencurrency. -
#inspect ⇒ String
Common inspect function.
- #locale_backend ⇒ Object
- #return_value(value) ⇒ Object
-
#round(rounding_mode = self.class.rounding_mode, rounding_precision = 0) ⇒ 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.
-
#symbol ⇒ String
Uses
Currency#symbol. -
#thousands_separator ⇒ String
Returns a thousands separator according to the locale.
-
#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
Conversion to
self. -
#to_nearest_cash_value ⇒ Money
Round a given amount of money to the nearest possible money in cash value.
-
#to_s ⇒ String
Returns the amount of money as a string.
-
#with_currency(new_currency) ⇒ self
Returns a new Money instance in a given currency leaving the amount intact and not performing currency conversion.
Methods included from Constructors
ca_dollar, empty, euro, pound_sterling, us_dollar
Constructor Details
#initialize(obj, currency = nil, options = {}) ⇒ 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.
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 |
# File 'lib/money/money.rb', line 357 def initialize(obj, currency = nil, = {}) # For backwards compatibility, if options is not a Hash, treat it as a bank parameter unless .is_a?(Hash) = { bank: } end @fractional = as_d(obj.respond_to?(:fractional) ? obj.fractional : obj) @currency = obj.respond_to?(:currency) ? obj.currency : Currency.wrap(currency) @currency ||= Money.default_currency @bank = obj.respond_to?(:bank) ? obj.bank : [:bank] @bank ||= Money.default_bank # BigDecimal can be Infinity and NaN, money of that amount does not make sense raise ArgumentError, "must be initialized with a finite value" unless @fractional.finite? raise Currency::NoCurrency, "must provide a currency" if @currency.nil? end |
Class Attribute Details
.conversion_precision ⇒ Object
Returns the value of attribute conversion_precision.
160 161 162 163 |
# File 'lib/money/money.rb', line 160 attr_accessor :default_formatting_rules, :default_infinite_precision, :conversion_precision, :strict_eql_compare |
.default_bank ⇒ Object
Modified to support thread-local bank override
160 161 162 163 |
# File 'lib/money/money.rb', line 160 attr_accessor :default_formatting_rules, :default_infinite_precision, :conversion_precision, :strict_eql_compare |
.default_currency ⇒ Money::Currency
177 178 179 180 181 182 183 184 185 |
# File 'lib/money/money.rb', line 177 def self.default_currency if @default_currency.nil? nil elsif @default_currency.respond_to?(:call) Money::Currency.new(@default_currency.call) else Money::Currency.new(@default_currency) end end |
.default_formatting_rules ⇒ Object
Returns the value of attribute default_formatting_rules.
160 161 162 |
# File 'lib/money/money.rb', line 160 def default_formatting_rules @default_formatting_rules end |
.default_infinite_precision ⇒ Object
Returns the value of attribute default_infinite_precision.
160 161 162 163 |
# File 'lib/money/money.rb', line 160 attr_accessor :default_formatting_rules, :default_infinite_precision, :conversion_precision, :strict_eql_compare |
.locale_backend ⇒ Object
Returns the value of attribute locale_backend.
164 165 166 |
# File 'lib/money/money.rb', line 164 def locale_backend @locale_backend end |
.rounding_mode ⇒ BigDecimal::ROUND_MODE
Use this to return the rounding mode.
254 255 256 257 258 |
# File 'lib/money/money.rb', line 254 def self.rounding_mode return Thread.current[:money_rounding_mode] if Thread.current[:money_rounding_mode] @rounding_mode end |
.strict_eql_compare ⇒ Object
Returns the value of attribute strict_eql_compare.
160 161 162 163 |
# File 'lib/money/money.rb', line 160 attr_accessor :default_formatting_rules, :default_infinite_precision, :conversion_precision, :strict_eql_compare |
Instance Attribute Details
#bank ⇒ Object (readonly)
Returns the value of attribute bank.
105 |
# File 'lib/money/money.rb', line 105 attr_reader :currency, :bank |
#conversion_precision ⇒ Integer
Used to specify precision for converting Rational to BigDecimal
107 |
# File 'sig/lib/money/money.rbs', line 107
attr_accessor self.default_formatting_rules: untyped
|
#currency ⇒ Currency (readonly)
Returns The money's currency.
105 106 107 |
# File 'lib/money/money.rb', line 105 def currency @currency end |
#default_bank ⇒ Money::Bank::Base
Used to set a default bank for currency exchange.
Each Money object is associated with 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.
107 |
# File 'sig/lib/money/money.rbs', line 107
attr_accessor self.default_formatting_rules: untyped
|
#default_currency ⇒ Money::Currency
Returns 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.
177 178 179 180 181 182 183 184 185 |
# File 'lib/money/money.rb', line 177 def self.default_currency if @default_currency.nil? nil elsif @default_currency.respond_to?(:call) Money::Currency.new(@default_currency.call) else Money::Currency.new(@default_currency) end end |
#default_formatting_rules ⇒ Hash
Used 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.
107 |
# File 'sig/lib/money/money.rbs', line 107
attr_accessor self.default_formatting_rules: untyped
|
#default_infinite_precision ⇒ Boolean
Returns Use this to enable infinite precision cents as the global default.
107 |
# File 'sig/lib/money/money.rbs', line 107
attr_accessor self.default_formatting_rules: untyped
|
#strict_eql_compare ⇒ Boolean
Use this to specify how Money#eql? behaves. Opt-in to the new
behavior by setting this to true and disable warnings when comparing
zero amounts with different currencies.
197 |
# File 'sig/lib/money/money.rbs', line 197
attr_accessor self.strict_eql_compare: untyped
|
Class Method Details
.add_rate(from_currency, to_currency, rate) ⇒ Numeric
Adds a new exchange rate to the default bank and return the rate.
291 292 293 |
# File 'lib/money/money.rb', line 291 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.
297 298 299 |
# File 'lib/money/money.rb', line 297 def self.disallow_currency_conversion! self.default_bank = Bank::SingleCurrency.instance end |
.from_amount(amount, currency = default_currency, options = {}) ⇒ Money
Creates a new Money object of value given in the unit of the given
currency.
316 317 318 319 320 321 322 323 324 |
# File 'lib/money/money.rb', line 316 def self.from_amount(amount, currency = default_currency, = {}) raise ArgumentError, "'amount' must be numeric" unless amount.is_a?(Numeric) currency = Currency.wrap(currency) || Money.default_currency raise Currency::NoCurrency, "must provide a currency" if currency.nil? value = amount.to_d * currency.subunit_to_unit new(value, currency, ) end |
.from_dollars(amount, currency = default_currency, options = {}) ⇒ Money
DEPRECATED.
329 330 331 332 333 334 |
# File 'lib/money/money.rb', line 329 def self.from_dollars(amount, currency = default_currency, = {}) warn "[DEPRECATION] `Money.from_dollars` is deprecated in favor of " \ "`Money.from_amount`." from_amount(amount, currency, ) end |
.inherited(base) ⇒ Object
243 244 245 246 247 |
# File 'lib/money/money.rb', line 243 def self.inherited(base) base.setup_defaults super end |
.setup_defaults ⇒ Object
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 |
# File 'lib/money/money.rb', line 222 def self.setup_defaults # Set the default bank for creating new +Money+ objects. self.default_bank = Bank::VariableExchange.instance # Default to using currency backend self.locale_backend = :currency # Default to not using infinite precision cents self.default_infinite_precision = false # Default rounding mode toward the nearest neighbor; if the neighbors are equidistant, round away from zero self.rounding_mode = BigDecimal::ROUND_HALF_UP # Default the conversion of Rationals precision to 16 self.conversion_precision = 16 # Defaults to the deprecated behavior where # `Money.new(0, "USD").eql?(Money.new(0, "EUR"))` is true. self.strict_eql_compare = false end |
.with_bank(bank) { ... } ⇒ Object
Temporarily changes the default bank in the current thread only
210 211 212 213 214 215 216 |
# File 'lib/money/money.rb', line 210 def self.with_bank(bank) original_bank = Thread.current[:money_bank] Thread.current[:money_bank] = bank yield ensure Thread.current[:money_bank] = original_bank end |
.with_rounding_mode(mode) { ... } ⇒ Object
Temporarily changes the rounding mode in a given block.
273 274 275 276 277 278 279 |
# File 'lib/money/money.rb', line 273 def self.with_rounding_mode(mode) original_mode = Thread.current[:money_rounding_mode] Thread.current[:money_rounding_mode] = mode yield ensure Thread.current[:money_rounding_mode] = original_mode end |
Instance Method Details
#allocate(parts) ⇒ Array<Money> Also known as: split
Splits a given amount in parts without losing pennies. The left-over pennies will be distributed round-robin amongst the parties. This means that parts listed first will likely receive more pennies than ones listed later.
Pass [2, 1, 1] as input to give twice as much to part1 as part2 or part3 which results in 50% of the cash to party1, 25% to part2, and 25% to part3. Passing a number instead of an array will split the amount evenly (without losing pennies when rounding).
577 578 579 580 |
# File 'lib/money/money.rb', line 577 def allocate(parts) amounts = Money::Allocation.generate(fractional, parts, !Money.default_infinite_precision) amounts.map { |amount| dup_with(fractional: amount) } end |
#amount ⇒ BigDecimal
Returns the numerical value of the money.
393 394 395 |
# File 'lib/money/money.rb', line 393 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.
543 544 545 |
# File 'lib/money/money.rb', line 543 def as_ca_dollar exchange_to("CAD") end |
#as_d(num) ⇒ Object
640 641 642 643 644 645 646 |
# File 'lib/money/money.rb', line 640 def as_d(num) if num.respond_to?(:to_d) num.is_a?(Rational) ? num.to_d(self.class.conversion_precision) : num.to_d else BigDecimal(num.to_s.empty? ? 0 : num.to_s) end end |
#as_euro ⇒ Money
Receive a money object with the same amount as the current Money object in euro.
555 556 557 |
# File 'lib/money/money.rb', line 555 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.
531 532 533 |
# File 'lib/money/money.rb', line 531 def as_us_dollar exchange_to("USD") end |
#cents ⇒ Integer, BigDecimal
Convenience method for fractional part of the amount. Synonym of #fractional
34 35 36 |
# File 'lib/money/money.rb', line 34 def cents fractional end |
#decimal_mark ⇒ String
Returns a decimal mark according to the locale
625 626 627 628 |
# File 'lib/money/money.rb', line 625 def decimal_mark (locale_backend && locale_backend.lookup(:decimal_mark, currency)) || Money::Formatter::DEFAULTS[:decimal_mark] end |
#dollars ⇒ BigDecimal
DEPRECATED.
377 378 379 380 381 382 |
# File 'lib/money/money.rb', line 377 def dollars warn "[DEPRECATION] `Money#dollars` is deprecated in favor of " \ "`Money#amount`." amount end |
#dup_with(options = {}) ⇒ Object
630 631 632 633 634 635 636 |
# File 'lib/money/money.rb', line 630 def dup_with( = {}) self.class.new( [:fractional] || fractional, [:currency] || currency, bank: [:bank] || bank, ) end |
#exchange_to(other_currency) {|n| ... } ⇒ Money
Receive the amount of this money object in another Currency.
514 515 516 517 518 519 520 521 |
# File 'lib/money/money.rb', line 514 def exchange_to(other_currency, &) other_currency = Currency.wrap(other_currency) if currency == other_currency self else @bank.exchange_with(self, other_currency, &) end end |
#format(*rules) ⇒ String
Creates a formatted price string according to several rules.
608 609 610 |
# File 'lib/money/money.rb', line 608 def format(*rules) Money::Formatter.new(self, *rules).to_s 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.
54 55 56 57 58 59 60 |
# File 'lib/money/money.rb', line 54 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.
404 405 406 |
# File 'lib/money/money.rb', line 404 def hash [fractional, currency].hash end |
#inspect ⇒ String
Common inspect function
421 422 423 |
# File 'lib/money/money.rb', line 421 def inspect "#<#{self.class.name} fractional:#{fractional} currency:#{currency}>" end |
#locale_backend ⇒ Object
656 657 658 |
# File 'lib/money/money.rb', line 656 def locale_backend self.class.locale_backend end |
#return_value(value) ⇒ Object
648 649 650 651 652 653 654 |
# File 'lib/money/money.rb', line 648 def return_value(value) if self.class.default_infinite_precision value else value.round(0, self.class.rounding_mode).to_i end end |
#round(rounding_mode = self.class.rounding_mode, rounding_precision = 0) ⇒ Money
This method is only useful when operating with Money.default_infinite_precision turned on. Without Money.default_infinite_precision values are rounded to the smallest unit of coinage automatically.
Round the monetary amount to smallest unit of coinage.
597 598 599 600 |
# File 'lib/money/money.rb', line 597 def round(rounding_mode = self.class.rounding_mode, rounding_precision = 0) rounded_amount = as_d(@fractional).round(rounding_precision, rounding_mode) dup_with(fractional: rounded_amount) 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.
71 72 73 74 75 76 |
# File 'lib/money/money.rb', line 71 def round_to_nearest_cash_value warn "[DEPRECATION] `round_to_nearest_cash_value` is deprecated - use " \ "`to_nearest_cash_value.fractional` instead" to_nearest_cash_value.fractional end |
#symbol ⇒ String
Uses Currency#symbol. If nil is returned, defaults to "¤".
414 415 416 |
# File 'lib/money/money.rb', line 414 def symbol currency.symbol || "¤" end |
#thousands_separator ⇒ String
Returns a thousands separator according to the locale
616 617 618 619 |
# File 'lib/money/money.rb', line 616 def thousands_separator (locale_backend && locale_backend.lookup(:thousands_separator, currency)) || Money::Formatter::DEFAULTS[:thousands_separator] end |
#to_d ⇒ BigDecimal
Return the amount of money as a BigDecimal.
444 445 446 |
# File 'lib/money/money.rb', line 444 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.
467 468 469 |
# File 'lib/money/money.rb', line 467 def to_f to_d.to_f end |
#to_i ⇒ Integer
Return the amount of money as a Integer.
454 455 456 |
# File 'lib/money/money.rb', line 454 def to_i to_d.to_i end |
#to_money(given_currency = nil) ⇒ self
Conversion to self.
489 490 491 492 493 494 495 496 |
# File 'lib/money/money.rb', line 489 def to_money(given_currency = nil) given_currency = Currency.wrap(given_currency) if given_currency.nil? || currency == given_currency self else exchange_to(given_currency) end end |
#to_nearest_cash_value ⇒ Money
Round a given amount of money to the nearest possible money 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.
84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/money/money.rb', line 84 def to_nearest_cash_value unless currency.smallest_denomination raise UndefinedSmallestDenomination, "Smallest denomination of this currency is not defined" end fractional = as_d(@fractional) smallest_denomination = as_d(currency.smallest_denomination) rounded_value = (fractional / smallest_denomination) .round(0, self.class.rounding_mode) * smallest_denomination dup_with(fractional: return_value(rounded_value)) end |
#to_s ⇒ String
Returns the amount of money as a string.
431 432 433 434 435 436 |
# File 'lib/money/money.rb', line 431 def to_s format thousands_separator: "", no_cents_if_whole: currency.decimal_places == 0, symbol: false, ignore_defaults: true end |
#with_currency(new_currency) ⇒ self
Returns a new Money instance in a given currency leaving the amount intact and not performing currency conversion.
477 478 479 480 481 482 483 484 |
# File 'lib/money/money.rb', line 477 def with_currency(new_currency) new_currency = Currency.wrap(new_currency) if !new_currency || currency == new_currency self else dup_with(currency: new_currency) end end |