-
-
Save dustMason/433437f0746ba54a07f84f2f8d1dc76a to your computer and use it in GitHub Desktop.
A modern ruby Money class, for ActiveShipping?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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