Class: MonetaryValue

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/monetary_value.rb,
lib/monetary_value/version.rb

Constant Summary collapse

VERSION =
"1.0.0"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(denomination = 0, currency = Currency.new) ⇒ MonetaryValue

Returns a new instance of MonetaryValue.



8
9
10
11
# File 'lib/monetary_value.rb', line 8

def initialize(denomination = 0, currency = Currency.new)
	@denomination = denomination
	@currency = currency
end

Instance Attribute Details

#currencyObject (readonly)

Returns the value of attribute currency.



6
7
8
# File 'lib/monetary_value.rb', line 6

def currency
  @currency
end

#denominationObject (readonly)

Returns the value of attribute denomination.



6
7
8
# File 'lib/monetary_value.rb', line 6

def denomination
  @denomination
end

Class Method Details

.from_xml(xml) ⇒ Object



195
196
197
198
# File 'lib/monetary_value.rb', line 195

def self.from_xml(xml)
	attributes = Hash.from_xml(xml)[xml_root].symbolize_keys
	new( attributes[:denomination] || attributes[:minor_value], Currency.new(attributes[:currency_id]) )
end

.parse(string) ⇒ Object

Raises:

  • (ArgumentError)


39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/monetary_value.rb', line 39

def self.parse(string)
	currency = Currency.new
	string.strip!
	denomination = nil
	nonnegative_string_formats = [
		/^(\d+)$/, # "123"
		/^\$(\d+)$/, # "$123"
		/^(\d*)\.(\d{1,2})$/, # "123.4", ".4", "123.45", ".45"
		/^\$(\d*)\.(\d{1,2})$/, # "$123.4", "$.4", "$123.45", "$.45"
	]
	
	nonnegative_string_formats.each do |format|
		result = string.scan(format)
		if result.size == 1
			denominations = result.first
			major_denomination = denominations[0].to_i
			minor_denomination = denominations[1].nil? ? 0 : denominations[1].ljust(2, "0").to_i
			denomination = major_denomination * 100 + minor_denomination
			return MonetaryValue.new(denomination, currency)
		end
	end
	
	negative_string_formats = [
		/^-(\d+)$/, # "-123"
		/^-\$(\d+)$/, # "-$123"
		/^\$-(\d+)$/, # "$-123"
		/^-(\d*)\.(\d{1,2})$/, # "-123.4", "-.4", "-123.45", "-.45"
		/^-\$(\d*)\.(\d{1,2})$/, # "-$123.4", "-$.4", "-$123.45", "-$.45"
		/^\$-(\d*)\.(\d{1,2})$/, # "$-123.4", "$-.4", "$-123.45", "$-.45"
	]
	
	negative_string_formats.each do |format|
		result = string.scan(format)
		if result.size == 1
			denominations = result.first
			major_denomination = denominations[0].to_i
			minor_denomination = denominations[1].nil? ? 0 : denominations[1].ljust(2, "0").to_i
			denomination = major_denomination * 100 + minor_denomination
			return MonetaryValue.new(-denomination, currency)
		end
	end
	
	raise ArgumentError, "invalid money_value"
end

.typecast(object) ⇒ Object



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/monetary_value.rb', line 85

def typecast(object)
	return nil if object.nil?
	return object if object.is_a? self
	
	case object
	when String
		begin
			parse(object)
		rescue ArgumentError => e
			raise UntypecastableArgumentError, "#{object.inspect}:#{object.class} cannot be cast as #{self}"
		end
	else
		raise UntypecastableArgumentError, "#{object.inspect}:#{object.class} cannot be cast as #{self}"
	end
end

.xml_rootObject

Serialization #



186
187
188
# File 'lib/monetary_value.rb', line 186

def self.xml_root
	"money"
end

Instance Method Details

#*(num) ⇒ Object

Multiplication



127
128
129
# File 'lib/monetary_value.rb', line 127

def *(num)
	MonetaryValue.new(denomination * num, currency)
end

#+(other) ⇒ Object

Addition

Raises:

  • (ArgumentError)


115
116
117
118
# File 'lib/monetary_value.rb', line 115

def +(other)
	raise ArgumentError, "can't add values in difference currencies" unless self =~ other
	MonetaryValue.new(denomination + other.denomination, currency)
end

#+@Object

Unary plus



142
143
144
# File 'lib/monetary_value.rb', line 142

def +@
	MonetaryValue.new(denomination, currency)
end

#-(other) ⇒ Object

Subtraction

Raises:

  • (ArgumentError)


121
122
123
124
# File 'lib/monetary_value.rb', line 121

def -(other)
	raise ArgumentError, "can't subtract values in difference currencies" unless self =~ other
	MonetaryValue.new(denomination - other.denomination, currency)
end

#-@Object

Unary minus



147
148
149
# File 'lib/monetary_value.rb', line 147

def -@
	MonetaryValue.new(-denomination, currency)
end

#/(num) ⇒ Object

Division



132
133
134
# File 'lib/monetary_value.rb', line 132

def /(num)
	MonetaryValue.new(denomination / num, currency)
end

#<=>(other) ⇒ Object

Raises:

  • (ArgumentError)


109
110
111
112
# File 'lib/monetary_value.rb', line 109

def <=>(other)
	raise ArgumentError, "can't compare values in difference currencies" unless self =~ other
	denomination <=> other.denomination
end

#=~(other) ⇒ Object

Currency matching



152
153
154
# File 'lib/monetary_value.rb', line 152

def =~(other)
	currency == other.currency
end

#absObject

Absolute value



137
138
139
# File 'lib/monetary_value.rb', line 137

def abs
	MonetaryValue.new(denomination.abs, currency)
end

#inspectObject



35
36
37
# File 'lib/monetary_value.rb', line 35

def inspect
	to_s(:long)
end

#major_denominationObject



19
20
21
# File 'lib/monetary_value.rb', line 19

def major_denomination
	"%01.2f" % (currency.convert_to_major_denomination(denomination))
end

#minor_denominationObject

Backwards compatibility TODO: Remove minor_denomination from MonetaryValue



15
16
17
# File 'lib/monetary_value.rb', line 15

def minor_denomination
	denomination
end

#negative?Boolean

Returns:

  • (Boolean)


178
179
180
# File 'lib/monetary_value.rb', line 178

def negative?
	denomination.negative?
end

#nextObject Also known as: succ

Next



157
158
159
# File 'lib/monetary_value.rb', line 157

def next
	MonetaryValue.new(denomination.next, currency)
end

#positive?Boolean

Returns:

  • (Boolean)


174
175
176
# File 'lib/monetary_value.rb', line 174

def positive?
	denomination.positive?
end

#signObject



170
171
172
# File 'lib/monetary_value.rb', line 170

def sign
	denomination.sign
end

#to_s(format = :default) ⇒ Object

Display



24
25
26
27
28
29
30
31
32
33
# File 'lib/monetary_value.rb', line 24

def to_s(format = :default)
	case format
	when :default, :short
		"$#{major_denomination}"
	when :long
		"#{major_denomination} #{currency.code}"
	else
		"$#{major_denomination}"
	end
end

#to_xml(options = {}) ⇒ Object



190
191
192
193
# File 'lib/monetary_value.rb', line 190

def to_xml(options = {})
	options[:root] ||= self.class.xml_root
	{ :currency_id => currency.id, :denomination => denomination }.to_xml(options)
end

#zero?Boolean

Sign tests #

Returns:

  • (Boolean)


166
167
168
# File 'lib/monetary_value.rb', line 166

def zero?
	denomination.zero?
end