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/locale_backend/legacy.rb,
lib/money/bank/variable_exchange.rb,
lib/money/money/formatting_rules.rb,
lib/money/locale_backend/currency.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, LocaleBackend, RatesStore Classes: Allocation, Currency, Formatter, FormattingRules, UndefinedSmallestDenomination
Constant Summary collapse
- VERSION =
'6.19.0'.freeze
Class Attribute Summary collapse
-
.conversion_precision ⇒ Integer
Used to specify precision for converting Rational to BigDecimal.
-
.default_bank ⇒ Money::Bank::Base
Used to set a default bank for currency exchange.
-
.default_formatting_rules ⇒ Hash
Used to define a default hash of rules for every time Money#format is called.
-
.default_infinite_precision ⇒ Boolean
Use this to enable infinite precision cents as the global default.
-
.locale_backend ⇒ Object
Returns the value of attribute locale_backend.
-
.use_i18n ⇒ Boolean
Used to disable i18n even if it’s used by other components of your app.
Instance Attribute Summary collapse
-
#bank ⇒ Object
readonly
Returns the value of attribute bank.
-
#currency ⇒ Currency
readonly
The money’s currency.
-
#default_currency ⇒ Money::Currency
The default currency, which is used when
Money.new
is called without an explicit currency argument.
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.
- .default_currency ⇒ Object
- .default_currency=(currency) ⇒ Object
-
.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
(also: from_dollars)
Creates a new Money object of value given in the
unit
of the givencurrency
. - .infinite_precision ⇒ Object
- .infinite_precision=(value) ⇒ Object
- .inherited(base) ⇒ Object
-
.rounding_mode(mode = nil) ⇒ BigDecimal::ROUND_MODE
Use this to return the rounding mode.
- .rounding_mode=(new_rounding_mode) ⇒ Object
- .setup_defaults ⇒ Object
-
.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_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.
-
#decimal_mark ⇒ String
Returns a decimal mark according to the locale.
-
#dollars ⇒ BigDecimal
Assuming using a currency using dollars: Returns the value of the money in dollars, instead of in the fractional unit cents.
- #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
fractional
andcurrency
attributes in order to use functions like & (intersection), group_by, etc. -
#initialize(obj, currency = Money.default_currency, options = {}) ⇒ Money
constructor
Creates a new Money object of value given in the fractional unit of the given
currency
. -
#inspect ⇒ String
Common inspect function.
-
#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_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
Methods included from Arithmetic
#%, #*, #+, #-, #-@, #/, #<=>, #==, #abs, #coerce, #div, #divmod, #eql?, #modulo, #negative?, #nonzero?, #positive?, #remainder, #zero?
Constructor Details
#initialize(obj, currency = Money.default_currency, 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.
346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 |
# File 'lib/money/money.rb', line 346 def initialize(obj, currency = Money.default_currency, = {}) # 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 ⇒ Integer
Used to specify precision for converting Rational to BigDecimal
133 |
# File 'lib/money/money.rb', line 133 attr_accessor :default_formatting_rules, :default_infinite_precision, :conversion_precision |
.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.
133 |
# File 'lib/money/money.rb', line 133 attr_accessor :default_formatting_rules, :default_infinite_precision, :conversion_precision |
.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
.
133 134 135 |
# File 'lib/money/money.rb', line 133 def default_formatting_rules @default_formatting_rules end |
.default_infinite_precision ⇒ Boolean
Returns Use this to enable infinite precision cents as the global default.
133 |
# File 'lib/money/money.rb', line 133 attr_accessor :default_formatting_rules, :default_infinite_precision, :conversion_precision |
.locale_backend ⇒ Object
Returns the value of attribute locale_backend.
134 135 136 |
# File 'lib/money/money.rb', line 134 def locale_backend @locale_backend end |
.use_i18n ⇒ Boolean
Used to disable i18n even if it’s used by other components of your app.
133 |
# File 'lib/money/money.rb', line 133 attr_accessor :default_formatting_rules, :default_infinite_precision, :conversion_precision |
Instance Attribute Details
#bank ⇒ Object (readonly)
Returns the value of attribute bank.
89 |
# File 'lib/money/money.rb', line 89 attr_reader :currency, :bank |
#currency ⇒ Currency (readonly)
Returns The money’s currency.
89 90 91 |
# File 'lib/money/money.rb', line 89 def currency @currency end |
#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.
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/money/money.rb', line 153 def self.default_currency if @using_deprecated_default_currency warn '[WARNING] The default currency will change from `USD` to `nil` in the next major release. Make ' \ 'sure to set it explicitly using `Money.default_currency=` to avoid potential issues' @using_deprecated_default_currency = false end 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 |
Class Method Details
.add_rate(from_currency, to_currency, rate) ⇒ Numeric
Adds a new exchange rate to the default bank and return the rate.
285 286 287 |
# File 'lib/money/money.rb', line 285 def self.add_rate(from_currency, to_currency, rate) Money.default_bank.add_rate(from_currency, to_currency, rate) end |
.default_currency ⇒ Object
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/money/money.rb', line 153 def self.default_currency if @using_deprecated_default_currency warn '[WARNING] The default currency will change from `USD` to `nil` in the next major release. Make ' \ 'sure to set it explicitly using `Money.default_currency=` to avoid potential issues' @using_deprecated_default_currency = false end 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_currency=(currency) ⇒ Object
169 170 171 172 |
# File 'lib/money/money.rb', line 169 def self.default_currency=(currency) @using_deprecated_default_currency = false @default_currency = currency 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.
291 292 293 |
# File 'lib/money/money.rb', line 291 def self.disallow_currency_conversion! self.default_bank = Bank::SingleCurrency.instance end |
.from_amount(amount, currency = default_currency, options = {}) ⇒ Money Also known as: from_dollars
Creates a new Money object of value given in the unit
of the given currency
.
310 311 312 313 314 315 316 317 318 |
# File 'lib/money/money.rb', line 310 def self.from_amount(amount, currency = default_currency, = {}) raise ArgumentError, "'amount' must be numeric" unless Numeric === amount 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 |
.infinite_precision ⇒ Object
137 138 139 140 |
# File 'lib/money/money.rb', line 137 def infinite_precision warn '[DEPRECATION] `Money.infinite_precision` is deprecated - use `Money.default_infinite_precision` instead' default_infinite_precision end |
.infinite_precision=(value) ⇒ Object
142 143 144 145 |
# File 'lib/money/money.rb', line 142 def infinite_precision=(value) warn '[DEPRECATION] `Money.infinite_precision=` is deprecated - use `Money.default_infinite_precision= ` instead' self.default_infinite_precision = value end |
.inherited(base) ⇒ Object
227 228 229 |
# File 'lib/money/money.rb', line 227 def self.inherited(base) base.setup_defaults end |
.rounding_mode(mode = nil) ⇒ BigDecimal::ROUND_MODE
Use this to return the rounding mode.
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 |
# File 'lib/money/money.rb', line 238 def self.rounding_mode(mode = nil) if mode warn "[DEPRECATION] calling `rounding_mode` with a block is deprecated. Please use `.with_rounding_mode` instead." return with_rounding_mode(mode) { yield } end return Thread.current[:money_rounding_mode] if Thread.current[:money_rounding_mode] if @using_deprecated_default_rounding_mode warn '[WARNING] The default rounding mode will change from `ROUND_HALF_EVEN` to `ROUND_HALF_UP` in the ' \ 'next major release. Set it explicitly using `Money.rounding_mode=` to avoid potential problems.' @using_deprecated_default_rounding_mode = false end @rounding_mode end |
.rounding_mode=(new_rounding_mode) ⇒ Object
187 188 189 190 |
# File 'lib/money/money.rb', line 187 def self.rounding_mode=(new_rounding_mode) @using_deprecated_default_rounding_mode = false @rounding_mode = new_rounding_mode end |
.setup_defaults ⇒ Object
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 |
# File 'lib/money/money.rb', line 202 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") @using_deprecated_default_currency = true # Default to using i18n @use_i18n = true # Default to using legacy locale backend self.locale_backend = :legacy # Default to not using infinite precision cents self.default_infinite_precision = false # Default to bankers rounding self.rounding_mode = BigDecimal::ROUND_HALF_EVEN @using_deprecated_default_rounding_mode = true # Default the conversion of Rationals precision to 16 self.conversion_precision = 16 end |
.with_rounding_mode(mode) { ... } ⇒ Object
Temporarily changes the rounding mode in a given block.
268 269 270 271 272 273 |
# File 'lib/money/money.rb', line 268 def self.with_rounding_mode(mode) Thread.current[:money_rounding_mode] = mode yield ensure Thread.current[:money_rounding_mode] = nil 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).
601 602 603 604 |
# File 'lib/money/money.rb', line 601 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
392 393 394 |
# File 'lib/money/money.rb', line 392 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.
567 568 569 |
# File 'lib/money/money.rb', line 567 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.
579 580 581 |
# File 'lib/money/money.rb', line 579 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.
555 556 557 |
# File 'lib/money/money.rb', line 555 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 |
#currency_as_string ⇒ String
Return string representation of currency object
402 403 404 405 |
# File 'lib/money/money.rb', line 402 def currency_as_string warn "[DEPRECATION] `currency_as_string` is deprecated. Please use `.currency.to_s` instead." currency.to_s end |
#currency_as_string=(val) ⇒ Money::Currency
Set currency object using a string
415 416 417 418 419 |
# File 'lib/money/money.rb', line 415 def currency_as_string=(val) warn "[DEPRECATION] `currency_as_string=` is deprecated - Money instances are immutable." \ " Please use `with_currency` instead." @currency = Currency.wrap(val) end |
#decimal_mark ⇒ String
Returns a decimal mark according to the locale
650 651 652 653 |
# File 'lib/money/money.rb', line 650 def decimal_mark (locale_backend && locale_backend.lookup(:decimal_mark, currency)) || Money::Formatter::DEFAULTS[:decimal_mark] 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
378 379 380 |
# File 'lib/money/money.rb', line 378 def dollars amount end |
#dup_with(options = {}) ⇒ Object
655 656 657 658 659 660 661 |
# File 'lib/money/money.rb', line 655 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.
538 539 540 541 542 543 544 545 |
# File 'lib/money/money.rb', line 538 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 |
#format(*rules) ⇒ String
Creates a formatted price string according to several rules.
633 634 635 |
# File 'lib/money/money.rb', line 633 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.
428 429 430 |
# File 'lib/money/money.rb', line 428 def hash [fractional.hash, currency.hash].hash end |
#inspect ⇒ String
Common inspect function
445 446 447 |
# File 'lib/money/money.rb', line 445 def inspect "#<#{self.class.name} fractional:#{fractional} currency:#{currency}>" end |
#round(rounding_mode = self.class.rounding_mode, rounding_precision = 0) ⇒ 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.
622 623 624 625 |
# File 'lib/money/money.rb', line 622 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 77 78 79 80 81 |
# File 'lib/money/money.rb', line 71 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 |
#symbol ⇒ String
Uses Currency#symbol. If nil
is returned, defaults to “¤”.
438 439 440 |
# File 'lib/money/money.rb', line 438 def symbol currency.symbol || "¤" end |
#thousands_separator ⇒ String
Returns a thousands separator according to the locale
641 642 643 644 |
# File 'lib/money/money.rb', line 641 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.
468 469 470 |
# File 'lib/money/money.rb', line 468 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.
491 492 493 |
# File 'lib/money/money.rb', line 491 def to_f to_d.to_f end |
#to_i ⇒ Integer
Return the amount of money as a Integer.
478 479 480 |
# File 'lib/money/money.rb', line 478 def to_i to_d.to_i end |
#to_money(given_currency = nil) ⇒ self
Conversion to self
.
513 514 515 516 517 518 519 520 |
# File 'lib/money/money.rb', line 513 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.
455 456 457 458 459 460 |
# File 'lib/money/money.rb', line 455 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.
501 502 503 504 505 506 507 508 |
# File 'lib/money/money.rb', line 501 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 |