simple_money 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +19 -1
- data/README.md +10 -3
- data/lib/simple_money/money.rb +97 -35
- metadata +54 -54
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
SimpleMoney 0.1.1
|
2
|
+
=================
|
3
|
+
|
4
|
+
Features
|
5
|
+
--------
|
6
|
+
- Ensure all calculations are done using BigDecimal
|
7
|
+
- Implemented Money#to_s
|
8
|
+
- Cleaned up documentation
|
9
|
+
- Reorganize lib/spec for compatibility with autotest
|
10
|
+
- Implemented Money.overflow=
|
11
|
+
|
12
|
+
Bug fixes
|
13
|
+
---------
|
14
|
+
- Fixed error where overflow wasn't properly updated after calling Money#/
|
15
|
+
|
1
16
|
SimpleMoney 0.1.0
|
2
|
-
|
17
|
+
=================
|
18
|
+
|
19
|
+
Features
|
20
|
+
--------
|
3
21
|
- Initial release.
|
data/README.md
CHANGED
@@ -10,10 +10,17 @@ Usage:
|
|
10
10
|
require 'simple_money'
|
11
11
|
|
12
12
|
a = Money.new(1_00, :as => :cents)
|
13
|
-
a.cents
|
13
|
+
a.cents #=> 100
|
14
14
|
b = a * 1.555
|
15
|
-
b.cents
|
16
|
-
Money.overflow
|
15
|
+
b.cents #=> 156
|
16
|
+
Money.overflow #=> #<BigDecimal:... '-0.5E0',4(16)>
|
17
|
+
b.to_s #=> "100"
|
18
|
+
b.to_s(:as => :decimal) #=> "1.00"
|
19
|
+
|
20
|
+
Version History
|
21
|
+
---------------
|
22
|
+
|
23
|
+
See {file:CHANGELOG.md} for details.
|
17
24
|
|
18
25
|
Copyright
|
19
26
|
---------
|
data/lib/simple_money/money.rb
CHANGED
@@ -8,17 +8,17 @@ class Money
|
|
8
8
|
class << self
|
9
9
|
|
10
10
|
##
|
11
|
-
# The valid values for
|
11
|
+
# The valid values for as
|
12
12
|
VALID_AS_VALUES = [:cents, :decimal]
|
13
13
|
|
14
14
|
##
|
15
|
-
# The valid
|
15
|
+
# The valid rounding methods
|
16
16
|
VALID_ROUNDING_METHOD_VALUES = [:away_from_zero, :toward_zero,
|
17
17
|
:nearest_up, :nearest_down, :bankers, :up, :down]
|
18
18
|
|
19
19
|
##
|
20
20
|
# Translations from SimpleMoney rounding methods to BigDecimal rounding
|
21
|
-
#
|
21
|
+
# methods.
|
22
22
|
ROUNDING_METHOD_TRANSLATION = {
|
23
23
|
:away_from_zero => BigDecimal::ROUND_UP,
|
24
24
|
:toward_zero => BigDecimal::ROUND_DOWN,
|
@@ -30,12 +30,12 @@ class Money
|
|
30
30
|
}
|
31
31
|
|
32
32
|
##
|
33
|
-
# @return [Symbol] The default
|
33
|
+
# @return [Symbol] The default as used to create a new Money (defaults to
|
34
34
|
# :cents).
|
35
35
|
attr_reader :default_as
|
36
36
|
|
37
37
|
##
|
38
|
-
# Set the default
|
38
|
+
# Set the default as used to create a new Money.
|
39
39
|
#
|
40
40
|
# @param [Symbol] as The default to use.
|
41
41
|
#
|
@@ -68,13 +68,13 @@ class Money
|
|
68
68
|
end
|
69
69
|
|
70
70
|
##
|
71
|
-
# @return [Symbol] The default
|
72
|
-
# not result in an
|
71
|
+
# @return [Symbol] The default rounding method used when calculations do
|
72
|
+
# not result in an Fixnum (defaults to :bankers).
|
73
73
|
attr_reader :default_rounding_method
|
74
74
|
|
75
75
|
##
|
76
|
-
# Set the default
|
77
|
-
#
|
76
|
+
# Set the default rounding method used when calculations do not result in a
|
77
|
+
# Fixnum.
|
78
78
|
#
|
79
79
|
# @param [Symbol] rounding_method The default to use.
|
80
80
|
#
|
@@ -94,8 +94,7 @@ class Money
|
|
94
94
|
end
|
95
95
|
|
96
96
|
##
|
97
|
-
# Returns true if argument is a valid
|
98
|
-
# false.
|
97
|
+
# Returns true if argument is a valid rounding method, otherwise false.
|
99
98
|
#
|
100
99
|
# @param [Symbol] rounding_method The value to check.
|
101
100
|
#
|
@@ -110,29 +109,46 @@ class Money
|
|
110
109
|
|
111
110
|
##
|
112
111
|
# @return [BigDecimal] The factional cents left over from any transactions
|
113
|
-
# that
|
112
|
+
# that overflowed.
|
114
113
|
attr_reader :overflow
|
115
114
|
|
115
|
+
##
|
116
|
+
# Update the overflow to the specified amount (converted to a BigDecimal
|
117
|
+
# object).
|
118
|
+
#
|
119
|
+
# @param [#to_s] n The value to set the overflow to.
|
120
|
+
#
|
121
|
+
# @return [BigDecimal]
|
122
|
+
#
|
123
|
+
# @example
|
124
|
+
# Money.round(1.5)
|
125
|
+
# Money.overflow #=> #<BigDecimal:... '-0.5E0',4(16)>
|
126
|
+
# Money.overflow = 0
|
127
|
+
# Money.overflow #=> #<BigDecimal:... '0.0',4(8)>
|
128
|
+
def overflow=(n)
|
129
|
+
@overflow = BigDecimal(n.to_s)
|
130
|
+
end
|
131
|
+
|
116
132
|
##
|
117
133
|
# Resets the overflow bucket to 0.
|
118
134
|
#
|
119
135
|
# @return [BigDecimal]
|
120
136
|
def reset_overflow
|
121
|
-
|
137
|
+
self.overflow = 0
|
122
138
|
end
|
123
139
|
|
124
140
|
##
|
125
141
|
# Returns n rounded to an integer using the given rounding method, or the
|
126
142
|
# default rounding method when none is provided. When rounding, the
|
127
|
-
# fractional cents are added to
|
143
|
+
# fractional cents are added to the overflow bucket.
|
128
144
|
#
|
129
145
|
# @param [#to_s] n The value to round.
|
130
146
|
# @param [Symbol] rounding_method The rounding method to use.
|
131
147
|
#
|
132
148
|
# @return [Fixnum]
|
133
149
|
#
|
134
|
-
# @raise [ArgumentError] Will raise an
|
135
|
-
#
|
150
|
+
# @raise [ArgumentError] Will raise an ArgumentError if an invalid rounding
|
151
|
+
# method is given.
|
136
152
|
#
|
137
153
|
# @example
|
138
154
|
# Money.round(1.5, :bankers) #=> 2
|
@@ -165,17 +181,17 @@ class Money
|
|
165
181
|
attr_reader :rounding_method
|
166
182
|
|
167
183
|
##
|
168
|
-
# Creates a new Money. If
|
169
|
-
#
|
184
|
+
# Creates a new Money object. If as is set to :cents, n will be coerced to a
|
185
|
+
# Fixnum. If as is set to :decimal, n will be coerced to a BigDecimal.
|
170
186
|
#
|
171
187
|
# @param [#to_s] n Value of the new object.
|
172
|
-
# @param [Hash] options options used to build the new object.
|
188
|
+
# @param [Hash] options The options used to build the new object.
|
173
189
|
# @option options [Symbol] :as How n is represented (defaults to
|
174
|
-
# self.class.default_as).
|
190
|
+
# self.class.default_as).
|
175
191
|
# @option options [Symbol] :rounding_method How any calculations resulting in
|
176
192
|
# fractions of a cent should be rounded.
|
177
193
|
#
|
178
|
-
# @raise [ArgumentError] Will raise an ArgumentError if
|
194
|
+
# @raise [ArgumentError] Will raise an ArgumentError if as is not valid.
|
179
195
|
#
|
180
196
|
# @example
|
181
197
|
# Money.new #=> #<Money:... @cents: 0>
|
@@ -202,20 +218,26 @@ class Money
|
|
202
218
|
|
203
219
|
@cents = case options[:as]
|
204
220
|
when :cents
|
205
|
-
Money.round(
|
221
|
+
Money.round(
|
222
|
+
BigDecimal(n.to_s), rounding_method
|
223
|
+
)
|
206
224
|
when :decimal
|
207
|
-
Money.round(
|
225
|
+
Money.round(
|
226
|
+
BigDecimal(n.to_s) * BigDecimal("100"),
|
227
|
+
rounding_method
|
228
|
+
)
|
208
229
|
end
|
209
230
|
end
|
210
231
|
|
211
232
|
##
|
212
|
-
# Add two Money objects; return the results as a new Money.
|
233
|
+
# Add two Money objects; return the results as a new Money object.
|
213
234
|
#
|
214
235
|
# @param [Money] n The object to add.
|
215
236
|
#
|
216
237
|
# @return [Money]
|
217
238
|
#
|
218
|
-
# @raise [ArgumentError] Will raise an ArgumentError unless n is a Money
|
239
|
+
# @raise [ArgumentError] Will raise an ArgumentError unless n is a Money
|
240
|
+
# object.
|
219
241
|
#
|
220
242
|
# @example
|
221
243
|
# Money.new(1) + Money.new(2) #=> #<Money:... @cents: 3>
|
@@ -225,13 +247,14 @@ class Money
|
|
225
247
|
end
|
226
248
|
|
227
249
|
##
|
228
|
-
# Subtract two Money; return the results as a new Money.
|
250
|
+
# Subtract two Money; return the results as a new Money object.
|
229
251
|
#
|
230
252
|
# @param [Money] n The object to subtract.
|
231
253
|
#
|
232
254
|
# @return [Money]
|
233
255
|
#
|
234
|
-
# @raise [ArgumentError] Will raise an ArgumentError unless n is a Money
|
256
|
+
# @raise [ArgumentError] Will raise an ArgumentError unless n is a Money
|
257
|
+
# object.
|
235
258
|
#
|
236
259
|
# @example
|
237
260
|
# Money.new(2) - Money.new(1) #=> #<Money:... @cents: 1>
|
@@ -241,34 +264,37 @@ class Money
|
|
241
264
|
end
|
242
265
|
|
243
266
|
##
|
244
|
-
# Multiply Money by a Numeric; return the results as a new Money.
|
267
|
+
# Multiply Money by a Numeric; return the results as a new Money object.
|
245
268
|
#
|
246
269
|
# @param [Numeric] n The object to multiply. n will be coerced to a
|
247
270
|
# BigDecimal before any calculations are done.
|
248
271
|
#
|
249
272
|
# @return [Money]
|
250
273
|
#
|
251
|
-
# @raise [ArgumentError] Will raise an ArgumentError unless n is a Numeric
|
274
|
+
# @raise [ArgumentError] Will raise an ArgumentError unless n is a Numeric
|
275
|
+
# object.
|
252
276
|
#
|
253
277
|
# @example
|
254
278
|
# Money.new(2) * 2 #=> #<Money:... @cents: 4>
|
255
279
|
def *(n)
|
256
280
|
raise ArgumentError, "n must be a Numeric" unless n.is_a? Numeric
|
257
281
|
|
258
|
-
Money.new(
|
282
|
+
Money.new(
|
283
|
+
BigDecimal(self.cents.to_s) * BigDecimal(n.to_s),
|
284
|
+
:as => :cents
|
285
|
+
)
|
259
286
|
end
|
260
287
|
|
261
288
|
##
|
262
|
-
# Divide
|
263
|
-
# Numeric/Money.
|
289
|
+
# Divide self by a Money/Numeric; return the results as a new Numeric/Money.
|
264
290
|
#
|
265
291
|
# @param [Money,Numeric] n The object to divide. If n is Numeric, it will be
|
266
292
|
# coerced to a BigDecimal before any calculations are done.
|
267
293
|
#
|
268
294
|
# @return [Numeric,Money]
|
269
295
|
#
|
270
|
-
# @raise [ArgumentError] Will raise an ArgumentError unless n is a Money
|
271
|
-
# Numeric.
|
296
|
+
# @raise [ArgumentError] Will raise an ArgumentError unless n is a Money
|
297
|
+
# object or Numeric.
|
272
298
|
#
|
273
299
|
# @example
|
274
300
|
# Money.new(10) / Money.new(5) #=> 2
|
@@ -278,10 +304,46 @@ class Money
|
|
278
304
|
when Money
|
279
305
|
BigDecimal(self.cents.to_s) / BigDecimal(n.cents.to_s)
|
280
306
|
when Numeric
|
281
|
-
|
307
|
+
result, overflow = BigDecimal(self.cents.to_s).divmod(BigDecimal(n.to_s))
|
308
|
+
self.class.overflow = self.class.overflow + overflow
|
309
|
+
Money.new(result, :as => :cents)
|
282
310
|
else
|
283
311
|
raise ArgumentError, "n must be a Money or Numeric"
|
284
312
|
end
|
285
313
|
end
|
286
314
|
|
315
|
+
##
|
316
|
+
# Returns cents formatted as a string, based on any options passed.
|
317
|
+
#
|
318
|
+
# @param [Hash] options The options used to format the string.
|
319
|
+
# @option options [Symbol] :as How cents should be returned (defaults to
|
320
|
+
# self.class.default_as).
|
321
|
+
#
|
322
|
+
# @return [String]
|
323
|
+
#
|
324
|
+
# @raise [ArgumentError] Will raise an ArgumentError if as is not valid.
|
325
|
+
#
|
326
|
+
# @example
|
327
|
+
# n = Money.new(1_00, :as => :cents)
|
328
|
+
# n.to_s #=> "100"
|
329
|
+
# n.to_s(:as => :decimal) #=> "1.00"
|
330
|
+
def to_s(options = {})
|
331
|
+
options = {
|
332
|
+
:as => :cents
|
333
|
+
}.merge(options)
|
334
|
+
|
335
|
+
raise ArgumentError, "invalid `as`" unless (
|
336
|
+
self.class.valid_as? options[:as]
|
337
|
+
)
|
338
|
+
|
339
|
+
case options[:as]
|
340
|
+
when :cents
|
341
|
+
cents.to_s
|
342
|
+
when :decimal
|
343
|
+
unit, subunit = cents.divmod(100).map(&:to_s)
|
344
|
+
subunit = "0#{subunit}"[-2,2]
|
345
|
+
"#{unit}.#{subunit}"
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
287
349
|
end
|
metadata
CHANGED
@@ -3,48 +3,48 @@ name: simple_money
|
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
version: 0.1.
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 1
|
9
|
+
version: 0.1.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
|
-
- Shane Emmons
|
12
|
+
- Shane Emmons
|
13
13
|
autorequire:
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-01-
|
17
|
+
date: 2011-01-10 00:00:00 -05:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
|
-
- !ruby/object:Gem::Dependency
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
- !ruby/object:Gem::Dependency
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rspec
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 2
|
30
|
+
- 0
|
31
|
+
- 0
|
32
|
+
version: 2.0.0
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: yard
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
segments:
|
44
|
+
- 0
|
45
|
+
version: "0"
|
46
|
+
type: :development
|
47
|
+
version_requirements: *id002
|
48
48
|
description: This gem is intended for working with financial calculations where you need highly accurate results.
|
49
49
|
email: semmons99@gmail.com
|
50
50
|
executables: []
|
@@ -54,11 +54,11 @@ extensions: []
|
|
54
54
|
extra_rdoc_files: []
|
55
55
|
|
56
56
|
files:
|
57
|
-
- lib/simple_money
|
58
|
-
- lib/simple_money.rb
|
59
|
-
- CHANGELOG.md
|
60
|
-
- LICENSE
|
61
|
-
- README.md
|
57
|
+
- lib/simple_money.rb
|
58
|
+
- lib/simple_money/money.rb
|
59
|
+
- CHANGELOG.md
|
60
|
+
- LICENSE
|
61
|
+
- README.md
|
62
62
|
has_rdoc: true
|
63
63
|
homepage: http://github.com/semmons99/simple_money
|
64
64
|
licenses: []
|
@@ -67,27 +67,27 @@ post_install_message:
|
|
67
67
|
rdoc_options: []
|
68
68
|
|
69
69
|
require_paths:
|
70
|
-
- lib
|
70
|
+
- lib
|
71
71
|
required_ruby_version: !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
segments:
|
77
|
+
- 1
|
78
|
+
- 8
|
79
|
+
- 7
|
80
|
+
version: 1.8.7
|
81
81
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
82
|
none: false
|
83
83
|
requirements:
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
segments:
|
87
|
+
- 1
|
88
|
+
- 3
|
89
|
+
- 7
|
90
|
+
version: 1.3.7
|
91
91
|
requirements: []
|
92
92
|
|
93
93
|
rubyforge_project:
|