Skip to content

Instantly share code, notes, and snippets.

@dustMason
Forked from dkubb/money.rb
Last active January 13, 2017 01:39
Show Gist options
  • Save dustMason/433437f0746ba54a07f84f2f8d1dc76a to your computer and use it in GitHub Desktop.
Save dustMason/433437f0746ba54a07f84f2f8d1dc76a to your computer and use it in GitHub Desktop.
A modern ruby Money class, for ActiveShipping?
require 'bigdecimal'
module ActiveShipping #:nodoc:
class Money
SCALE = 2
OPERAND_CLASSES = [self, Rational, BigDecimal, Integer].freeze
attr_reader :amount
protected :amount
def initialize numeric
@amount = coerce_numeric numeric
end
def amount_in_cents
(amount * 100).to_i
end
%i[+@ -@ abs].each do |method|
define_method(method) { self.class.new(amount.public_send(method)) }
end
%i[+ - * /].each do |method|
define_method(method) do |other|
self.class.new(amount.public_send(method, coerce_numeric(other)))
end
end
def to_d
(amount.numerator.to_d / amount.denominator).round(
SCALE,
BigDecimal::ROUND_HALF_EVEN
)
end
def to_s
'$%.*f' % [SCALE, to_d]
end
protected
def to_r
amount
end
private
def coerce_numeric numeric
assert_valid_numeric numeric
numeric.to_r
end
def assert_valid_numeric numeric
unless OPERAND_CLASSES.any? { |klass| numeric.kind_of?(klass) }
raise TypeError,
"Operand must be #{OPERAND_CLASSES.join(', ')}, not #{numeric.class}"
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment