class SpookAndPuff::Money

The money class represents monetary values with a precision of up to seven digits. When used as part of a comparison or mathmatical operation it always ensures the other operand is coerced into a BigDecimal. This ensures the precision is maintained.

Constants

NUMBER_OF_CENTS

Attributes

raw[R]

Stores the raw BigDecimal instance that a Money instance wraps.

Public Class Methods

cents(cents) click to toggle source

Initialize a money instance by providing an number of cents

@return SpookAndPuff::Money

# File lib/spook_and_puff/money.rb, line 36
def self.cents(cents)
  raise TypeError.new('SpookAndPuff::Money#cents expects a number of cents') unless cents.is_a? Numeric
  new((cents / NUMBER_OF_CENTS).to_s)
end
new(value) click to toggle source

Initializes the money class from a BigDecimal instance.

@param [BigDecimal, String, SpookAndPuff::Money] value

@return self

@raise TypeError

# File lib/spook_and_puff/money.rb, line 24
def initialize(value)
  @raw = case value
  when SpookAndPuff::Money then value.raw
  when BigDecimal then value
  when String     then BigDecimal(value.gsub(/\$/, ''))
  else raise TypeError.new("Money can only be initalized with a BigDecimal or String not #{value.class}.")
  end
end
zero() click to toggle source

A convenience method which returns an instance initalized to zero.

@return SpookAndPuff::Money

# File lib/spook_and_puff/money.rb, line 44
def self.zero
  new("0")
end

Public Instance Methods

*(other) click to toggle source

Multiplication. Numerics and strings only.

@param [Integer, Fixnum, String] other

@return Money

@raise ArgumentError

# File lib/spook_and_puff/money.rb, line 76
def *(other)
  Money.new(@raw * coerce(other))
end
+(other) click to toggle source

Add.

@param [Money, Numeric, String] other

@return Money

@raise ArgumentError

# File lib/spook_and_puff/money.rb, line 109
def +(other)
  Money.new(@raw + for_operation(other, 'addition'))
end
+@() click to toggle source

Unary plus. Just returns the reciever.

@return Money

# File lib/spook_and_puff/money.rb, line 123
def +@
  self
end
-(other) click to toggle source

Minus.

@param [Money, Numeric, String] other

@return Money

@raise ArgumentError

# File lib/spook_and_puff/money.rb, line 98
def -(other)
  Money.new(@raw - for_operation(other, 'subtraction'))
end
-@() click to toggle source

Unary minus. This negates the money value

@return Money

# File lib/spook_and_puff/money.rb, line 116
def -@
  Money.new(-@raw)
end
/(other) click to toggle source

Division. Numerics and strings only.

@param [Integer, Fixnum, String] other

@return Money

@raise ArgumentError

# File lib/spook_and_puff/money.rb, line 87
def /(other)
  Money.new(@raw / coerce(other))
end
<=>(other) click to toggle source

@param [Money, Numeric, String] other

@return Money

@raise ArgumentError

# File lib/spook_and_puff/money.rb, line 65
def <=>(other)
  @raw <=> for_comparison(other)
end
==(other) click to toggle source

Value comparison.

@param [Money, Numeric, String] other

@return Money

# File lib/spook_and_puff/money.rb, line 53
def ==(other)
  case other
  when Money then @raw == other.raw
  else false
  end
end
abs() click to toggle source

Returns a new Money instance with the absolute value.

@return Money

# File lib/spook_and_puff/money.rb, line 130
def abs
  Money.new(@raw.abs)
end
cents() click to toggle source

Returns a BigDecimal representation of the value in cents.

@return BigDecimal

# File lib/spook_and_puff/money.rb, line 137
def cents
  @raw * BigDecimal('100')
end
negative?() click to toggle source

Checks to see if the value is less than zero.

@return [true, false]

# File lib/spook_and_puff/money.rb, line 172
def negative?
  @raw < 0
end
non_negative?() click to toggle source

Checks to see if the value is positive.

@return [true, false]

# File lib/spook_and_puff/money.rb, line 165
def non_negative?
  @raw > -1
end
percent(percentage) click to toggle source

Calculates an amount based on the provided percentage.

@param [Numeric, String] percentage

@return Money

@raise TypeError

# File lib/spook_and_puff/money.rb, line 183
def percent(percentage)
  Money.new(@raw * (coerce(percentage) / BigDecimal('100')))
end
positive?() click to toggle source

Checks to see if the value is positive i.e. non-negative, non-zero.

@return [true, false]

# File lib/spook_and_puff/money.rb, line 158
def positive?
  @raw > 0
end
proportion(amount) click to toggle source

Calculates the proportion of the provided amount as a percentage.

@param SpookAndPuff::Money amount

@return BigDecimal

@raise TypeError

# File lib/spook_and_puff/money.rb, line 194
def proportion(amount)
  amount.raw / @raw * BigDecimal('100')
end
round(places = 2) click to toggle source

Rounds to the specified places; defaults to two.

@param Integer places

@return Money

# File lib/spook_and_puff/money.rb, line 203
def round(places = 2)
  Money.new(@raw.round(places))
end
to_big_decimal() click to toggle source

Returns the raw BigDecimal value.

@return BigDecimal

# File lib/spook_and_puff/money.rb, line 144
def to_big_decimal
  @raw
end
to_s(opts = {}) click to toggle source

Returns a currency formatted string, set to two decimal places.

@param Hash opts @option opts [true, false] :prefix @return String

# File lib/spook_and_puff/money.rb, line 212
def to_s(opts = {})
  rounded = @raw.round(2)
  prefix = opts[:prefix] == false ? '' : '$'
  format = (opts[:drop_cents] and rounded == @raw.round) ? "%i" : "%.2f"

  "#{prefix}#{format}" % rounded
end
zero?() click to toggle source

Checks for zero value.

@return [true, false]

# File lib/spook_and_puff/money.rb, line 151
def zero?
  @raw == 0
end

Private Instance Methods

coerce(other) click to toggle source

Coerces the provided value into a BigDecimal. It will handle any Numeric or string.

@param [Numeric, String] other

@return BigDecimal

@raise TypeError

# File lib/spook_and_puff/money.rb, line 263
def coerce(other)
  case other
  when BigDecimal then other
  when String then BigDecimal(other)
  when Integer, Fixnum, Bignum then BigDecimal(other.to_s)
  else raise TypeError
  end
end
for_comparison(other) click to toggle source

Grabs the raw value of a Money instance, erroring with a message about comparison if it’s the wrong type.

@param SpookAndPuff::Money other

@return BigDecimal

@raise ArgumentError

# File lib/spook_and_puff/money.rb, line 230
def for_comparison(other)
  unless other.is_a?(Money)
    raise ArgumentError.new("#{other.class} cannot be compared with SpookAndPuff::Money")
  end

  other.raw
end
for_operation(other, op) click to toggle source

Grabs the raw value of a Money instance, erroring with a message about comparison if it’s the wrong type.

@param SpookAndPuff::Money other @param String op

@return BigDecimal

@raise ArgumentError

# File lib/spook_and_puff/money.rb, line 247
def for_operation(other, op)
  unless other.is_a?(Money)
    raise ArgumentError.new("Cannot perform #{op} on SpookAndPuff::Money with #{other.class}")
  end

  other.raw
end