Class: Mint::Money
- Inherits:
-
Object
- Object
- Mint::Money
- Includes:
- Comparable
- Defined in:
- lib/minting/money/money.rb,
lib/minting/money/coercion.rb,
lib/minting/money/allocation.rb,
lib/minting/money/comparable.rb,
lib/minting/money/conversion.rb,
lib/minting/money/arithmetics.rb
Overview
:nodoc Arithmetic funcions for money ojects
Defined Under Namespace
Classes: CoercedNumber
Constant Summary collapse
- DEFAULT_FORMAT =
'%<symbol>s%<amount>f'
Instance Attribute Summary collapse
-
#amount ⇒ Object
readonly
Returns the value of attribute amount.
-
#currency ⇒ Object
readonly
Returns the value of attribute currency.
Instance Method Summary collapse
- #*(multiplicand) ⇒ Object
- #+(addend) ⇒ Object
- #-(subtrahend) ⇒ Object
- #-@ ⇒ Object
- #/(divisor) ⇒ Object
- #<=>(other) ⇒ Object
-
#==(other) ⇒ Object
True if both are zero, or both have same amount and same currency.
- #abs ⇒ Object
- #allocate(proportions) ⇒ Object
- #coerce(other) ⇒ Object
- #currency_code ⇒ Object
- #eql?(other) ⇒ Boolean
- #hash ⇒ Object
-
#initialize(amount, currency) ⇒ Money
constructor
A new instance of Money.
- #inspect ⇒ Object
- #mint(new_amount) ⇒ Object
- #negative? ⇒ Boolean
- #nonzero? ⇒ Boolean
- #positive? ⇒ Boolean
- #same_currency?(other) ⇒ Boolean
- #split(quantity) ⇒ Object
- #to_d ⇒ Object
- #to_f ⇒ Object
- #to_html(format = DEFAULT_FORMAT) ⇒ Object
- #to_i ⇒ Object
- #to_json(*_args) ⇒ Object
- #to_r ⇒ Object
- #to_s(format: '%<symbol>s%<amount>f', delimiter: false, separator: '.') ⇒ Object
- #zero? ⇒ Boolean
Constructor Details
#initialize(amount, currency) ⇒ Money
Returns a new instance of Money.
11 12 13 14 15 16 17 18 19 20 21 |
# File 'lib/minting/money/money.rb', line 11 def initialize(amount, currency) raise ArgumentError, 'amount must be Numeric' unless amount.is_a?(Numeric) unless currency.is_a?(Currency) raise ArgumentError, 'currency must be a Currency object' end @amount = amount.to_r.round(currency.subunit) @currency = currency end |
Instance Attribute Details
#amount ⇒ Object (readonly)
Returns the value of attribute amount.
9 10 11 |
# File 'lib/minting/money/money.rb', line 9 def amount @amount end |
#currency ⇒ Object (readonly)
Returns the value of attribute currency.
9 10 11 |
# File 'lib/minting/money/money.rb', line 9 def currency @currency end |
Instance Method Details
#*(multiplicand) ⇒ Object
37 38 39 40 41 |
# File 'lib/minting/money/arithmetics.rb', line 37 def *(multiplicand) return mint(amount * multiplicand.to_r) if multiplicand.is_a?(Numeric) raise TypeError, "#{self} can't be multiplied by #{multiplicand}" end |
#+(addend) ⇒ Object
19 20 21 22 23 24 |
# File 'lib/minting/money/arithmetics.rb', line 19 def +(addend) return mint(amount + addend.amount) if same_currency?(addend) return self unless addend.is_a?(Money) || addend.nonzero? raise TypeError, "#{addend} can't be added to #{self}" end |
#-(subtrahend) ⇒ Object
26 27 28 29 30 31 |
# File 'lib/minting/money/arithmetics.rb', line 26 def -(subtrahend) return self if subtrahend.zero? return mint(amount - subtrahend.amount) if same_currency?(subtrahend) raise TypeError, "#{subtrahend} can't be subtracted from #{self}" end |
#-@ ⇒ Object
33 34 35 |
# File 'lib/minting/money/arithmetics.rb', line 33 def -@ mint(-amount) end |
#/(divisor) ⇒ Object
43 44 45 46 47 48 |
# File 'lib/minting/money/arithmetics.rb', line 43 def /(divisor) return mint(amount / divisor) if divisor.is_a?(Numeric) return amount / divisor.amount if same_currency? divisor raise TypeError, "#{self} can't be divided by #{divisor}" end |
#<=>(other) ⇒ Object
27 28 29 30 31 32 33 34 35 |
# File 'lib/minting/money/comparable.rb', line 27 def <=>(other) case other when Numeric return amount <=> other if other.zero? when Mint::Money return amount <=> other.amount if currency == other.currency end raise TypeError, "#{inspect} can't be compared to #{other.inspect}" end |
#==(other) ⇒ Object
Returns true if both are zero, or both have same amount and same currency.
10 11 12 13 14 15 16 |
# File 'lib/minting/money/comparable.rb', line 10 def ==(other) return true if other.is_a?(Numeric) && zero? && other.zero? return false unless other.is_a?(Mint::Money) return false if nonzero? && currency != other.currency amount == other.amount end |
#abs ⇒ Object
7 8 9 |
# File 'lib/minting/money/arithmetics.rb', line 7 def abs mint(amount.abs) end |
#allocate(proportions) ⇒ Object
7 8 9 10 11 12 13 14 |
# File 'lib/minting/money/allocation.rb', line 7 def allocate(proportions) raise ArgumentError, 'Need at least 1 proportion element' if proportions.empty? whole = proportions.sum.to_r allocation = proportions.map { |rate| mint(amount * rate.to_r / whole) } left_over = self - allocation.sum allocate_left_over(allocation, left_over) end |
#coerce(other) ⇒ Object
7 8 9 |
# File 'lib/minting/money/coercion.rb', line 7 def coerce(other) [CoercedNumber.new(other), self] end |
#currency_code ⇒ Object
23 24 25 |
# File 'lib/minting/money/money.rb', line 23 def currency_code currency.code end |
#eql?(other) ⇒ Boolean
37 38 39 |
# File 'lib/minting/money/comparable.rb', line 37 def eql?(other) self == other end |
#hash ⇒ Object
41 42 43 |
# File 'lib/minting/money/comparable.rb', line 41 def hash @hash ||= zero? ? 0.hash : [amount, currency].hash end |
#inspect ⇒ Object
31 32 33 |
# File 'lib/minting/money/money.rb', line 31 def inspect Kernel.format "[#{currency_code} %0.#{currency.subunit}f]", amount end |
#mint(new_amount) ⇒ Object
27 28 29 |
# File 'lib/minting/money/money.rb', line 27 def mint(new_amount) new_amount.to_r == amount ? self : Money.new(new_amount, currency) end |
#negative? ⇒ Boolean
11 12 13 |
# File 'lib/minting/money/arithmetics.rb', line 11 def negative? amount.negative? end |
#nonzero? ⇒ Boolean
45 46 47 |
# File 'lib/minting/money/comparable.rb', line 45 def nonzero? amount.nonzero? end |
#positive? ⇒ Boolean
15 16 17 |
# File 'lib/minting/money/arithmetics.rb', line 15 def positive? amount.positive? end |
#same_currency?(other) ⇒ Boolean
35 36 37 |
# File 'lib/minting/money/money.rb', line 35 def same_currency?(other) other.respond_to?(:currency) && other.currency == currency end |
#split(quantity) ⇒ Object
16 17 18 19 20 21 22 23 24 25 26 |
# File 'lib/minting/money/allocation.rb', line 16 def split(quantity) unless quantity.positive? && quantity.integer? raise ArgumentError, 'quantitity must be an integer > 0' end fraction = self / quantity allocation = Array.new(quantity, fraction) left_over = self - (fraction * quantity) allocate_left_over(allocation, left_over) end |
#to_d ⇒ Object
6 7 8 |
# File 'lib/minting/money/conversion.rb', line 6 def to_d amount.to_d 0 end |
#to_f ⇒ Object
10 11 12 |
# File 'lib/minting/money/conversion.rb', line 10 def to_f amount.to_f end |
#to_html(format = DEFAULT_FORMAT) ⇒ Object
14 15 16 17 |
# File 'lib/minting/money/conversion.rb', line 14 def to_html(format = DEFAULT_FORMAT) title = Kernel.format("#{currency_code} %0.#{currency.subunit}f", amount) %(<data class='money' title='#{title}'>#{to_s(format: format)}</data>) end |
#to_i ⇒ Object
19 20 21 |
# File 'lib/minting/money/conversion.rb', line 19 def to_i amount.to_i end |
#to_json(*_args) ⇒ Object
23 24 25 26 27 28 29 |
# File 'lib/minting/money/conversion.rb', line 23 def to_json(*_args) subunit = currency.subunit Kernel.format( %({"currency": "#{currency_code}", "amount": "%0.#{subunit}f"}), amount ) end |
#to_r ⇒ Object
31 32 33 |
# File 'lib/minting/money/conversion.rb', line 31 def to_r amount end |
#to_s(format: '%<symbol>s%<amount>f', delimiter: false, separator: '.') ⇒ Object
35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/minting/money/conversion.rb', line 35 def to_s(format: '%<symbol>s%<amount>f', delimiter: false, separator: '.') format = format.gsub(/%<amount>(\+?\d*)f/, "%<amount>\\1.#{currency.subunit}f") formatted = Kernel.format(format, amount: amount, currency: currency_code, symbol: currency.symbol) if delimiter # Thanks Money gem for the regular expression formatted.gsub!(/(\d)(?=(?:\d{3})+(?:[^\d]{1}|$))/, "\\1#{delimiter}") end formatted.tr!('.', separator) if separator != '.' formatted end |
#zero? ⇒ Boolean
49 50 51 |
# File 'lib/minting/money/comparable.rb', line 49 def zero? amount.zero? end |