Module: Money::Arithmetic
- Included in:
- Money
- Defined in:
- lib/money/money/arithmetic.rb,
sig/lib/money/money/arithmetic.rbs
Constant Summary collapse
- CoercedNumeric =
Wrapper for coerced numeric values to distinguish when numeric was on the 1st place in operation.
Instance Method Summary collapse
-
#%(other) ⇒ Money
Synonym for
#modulo. -
#*(other) ⇒ Money
Multiplies the monetary value with the given number and returns a new
Moneyobject with this monetary value and the same currency. -
#+(other) ⇒ Money
Returns a new Money object containing the sum of the two operands' monetary values.
-
#-(other) ⇒ Money
Returns a new Money object containing the difference between the two operands' monetary values.
-
#-@ ⇒ Money
Returns a money object with changed polarity.
-
#/(other) ⇒ Money, Float
Divides the monetary value with the given number and returns a new
Moneyobject with this monetary value and the same currency. -
#<=>(other) ⇒ Integer
Compares two Money objects.
-
#==(other) ⇒ Boolean
Uses Comparable's implementation but raises ArgumentError if non-zero numeric value is given.
-
#abs ⇒ Money
Return absolute value of self as a new Money object.
-
#coerce(other) ⇒ Array
Used to make Money instance handle the operations when arguments order is reversed.
-
#div(value) ⇒ Money, Float
Synonym for
#/. -
#divmod(val) ⇒ Array<Money,Money>, Array<Integer,Money>
Divide money by money or fixnum and return array containing quotient and modulus.
- #divmod_money(val) ⇒ ::Array[untyped]
- #divmod_other(val) ⇒ ::Array[untyped]
-
#eql?(other) ⇒ Boolean
Checks whether two Money objects have the same currency and the same amount.
-
#modulo(val) ⇒ Money
Equivalent to
self.divmod(val)[1]. -
#negative? ⇒ Boolean
Test if the amount is negative.
-
#nonzero? ⇒ Money?
Test if the money amount is non-zero.
-
#positive? ⇒ Boolean
Test if the amount is positive.
-
#remainder(val) ⇒ Money
If different signs
self.modulo(val) - valotherwiseself.modulo(val). -
#zero? ⇒ Boolean
Test if the money amount is zero.
Instance Method Details
#%(other) ⇒ Money
Synonym for #modulo.
289 290 291 |
# File 'lib/money/money/arithmetic.rb', line 289 def %(other) modulo(other) end |
#*(other) ⇒ 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.
180 181 182 183 184 185 186 187 |
# File 'lib/money/money/arithmetic.rb', line 180 def *(other) other = other.value if other.is_a?(CoercedNumeric) if other.is_a? Numeric dup_with(fractional: fractional * other) else raise TypeError, "Can't multiply a #{self.class.name} by a #{other.class.name}'s value" end end |
#+(other) ⇒ 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.
|
|
# File 'lib/money/money/arithmetic.rb', line 119
|
#-(other) ⇒ 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.
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/money/money/arithmetic.rb', line 141 [:+, :-].each do |op| = lambda do |value| "Can't add or subtract a non-zero #{value.class.name} value" end define_method(op) do |other| case other when Money other = other.exchange_to(currency) new_fractional = fractional.public_send(op, other.fractional) dup_with(fractional: new_fractional) when CoercedNumeric raise TypeError, .call(other.value) unless other.zero? dup_with(fractional: other.value.public_send(op, fractional)) when Numeric raise TypeError, .call(other) unless other.zero? self else raise TypeError, "Unsupported argument type: #{other.class.name}" end end end |
#-@ ⇒ Money
Returns a money object with changed polarity.
20 21 22 |
# File 'lib/money/money/arithmetic.rb', line 20 def -@ dup_with(fractional: -fractional) end |
#/(other) ⇒ 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.
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
# File 'lib/money/money/arithmetic.rb', line 204 def /(other) if other.is_a?(self.class) exchanged = other.exchange_to(currency) raise ZeroDivisionError, "divided by Money(0)" if exchanged.zero? fractional / as_d(exchanged.fractional).to_f else raise TypeError, "Can not divide by Money" if other.is_a?(CoercedNumeric) other = as_d(other) raise ZeroDivisionError, "divided by zero" if other.zero? dup_with(fractional: fractional / other) end end |
#<=>(other) ⇒ Integer
Compares two Money objects. If money objects have a different currency it will attempt to convert the currency.
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/money/money/arithmetic.rb', line 65 def <=>(other) unless other.is_a?(Money) return unless other.respond_to?(:zero?) && other.zero? return other.is_a?(CoercedNumeric) ? 0 <=> fractional : fractional <=> 0 end # Always allow comparison with zero if zero? || other.zero? return fractional <=> other.fractional end other = other.exchange_to(currency) fractional <=> other.fractional rescue Money::Bank::UnknownRate nil end |
#==(other) ⇒ Boolean
Uses Comparable's implementation but raises ArgumentError if non-zero numeric value is given.
85 86 87 88 89 90 91 |
# File 'lib/money/money/arithmetic.rb', line 85 def ==(other) if other.is_a?(Numeric) && !other.zero? raise ArgumentError, "Money#== supports only zero numerics" end super end |
#abs ⇒ Money
Return absolute value of self as a new Money object.
319 320 321 |
# File 'lib/money/money/arithmetic.rb', line 319 def abs dup_with(fractional: fractional.abs) end |
#coerce(other) ⇒ Array
Used to make Money instance handle the operations when arguments order is reversed
351 352 353 |
# File 'lib/money/money/arithmetic.rb', line 351 def coerce(other) [self, CoercedNumeric.new(other)] end |
#div(value) ⇒ Money, Float
Synonym for #/.
229 230 231 |
# File 'lib/money/money/arithmetic.rb', line 229 def div(value) self / value end |
#divmod(val) ⇒ Array<Money,Money>, Array<Integer,Money>
Divide money by money or fixnum and return array containing quotient and modulus.
243 244 245 246 247 248 249 |
# File 'lib/money/money/arithmetic.rb', line 243 def divmod(val) if val.is_a?(Money) divmod_money(val) else divmod_other(val) end end |
#divmod_money(val) ⇒ ::Array[untyped]
251 252 253 254 255 256 257 |
# File 'lib/money/money/arithmetic.rb', line 251 def divmod_money(val) cents = val.exchange_to(currency).cents raise ZeroDivisionError, "divided by Money(0)" if cents == 0 quotient, remainder = fractional.divmod(cents) [quotient, dup_with(fractional: remainder)] end |
#divmod_other(val) ⇒ ::Array[untyped]
260 261 262 263 264 265 266 |
# File 'lib/money/money/arithmetic.rb', line 260 def divmod_other(val) val = as_d(val) raise ZeroDivisionError, "divided by zero" if val.zero? quotient, remainder = fractional.divmod(val) [dup_with(fractional: quotient), dup_with(fractional: remainder)] end |
#eql?(other) ⇒ Boolean
Checks whether two Money objects have the same currency and the same amount. Checks against objects that are not Money or a subclass will always return false.
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/money/money/arithmetic.rb', line 40 def eql?(other) if other.is_a?(Money) if !Money.strict_eql_compare && fractional == 0 && other.fractional == 0 warn "[DEPRECATION] Comparing 0 #{currency} with 0 " \ "#{other.currency} using `#eql?` will return false in " \ "future versions of Money. Opt-in to the new behavior by " \ "setting `Money.strict_eql_compare = true`." return true end fractional == other.fractional && currency == other.currency else false end end |
#modulo(val) ⇒ Money
Equivalent to self.divmod(val)[1]
278 279 280 |
# File 'lib/money/money/arithmetic.rb', line 278 def modulo(val) divmod(val)[1] end |
#negative? ⇒ Boolean
Test if the amount is negative. Returns true if the money amount is
less than 0, false otherwise.
115 116 117 |
# File 'lib/money/money/arithmetic.rb', line 115 def negative? fractional < 0 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?.
342 343 344 |
# File 'lib/money/money/arithmetic.rb', line 342 def nonzero? fractional == 0 ? nil : self end |
#positive? ⇒ Boolean
Test if the amount is positive. Returns true if the money amount is
greater than 0, false otherwise.
102 103 104 |
# File 'lib/money/money/arithmetic.rb', line 102 def positive? fractional > 0 end |
#remainder(val) ⇒ Money
If different signs self.modulo(val) - val otherwise self.modulo(val)
301 302 303 304 305 306 307 308 309 310 311 |
# File 'lib/money/money/arithmetic.rb', line 301 def remainder(val) if val.is_a?(Money) && currency != val.currency val = val.exchange_to(currency) end if (fractional < 0 && val < 0) || (fractional > 0 && val > 0) modulo(val) else modulo(val) - (val.is_a?(Money) ? val : dup_with(fractional: val)) end end |
#zero? ⇒ Boolean
Test if the money amount is zero.
330 331 332 |
# File 'lib/money/money/arithmetic.rb', line 330 def zero? fractional == 0 end |