simple_money 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. data/CHANGELOG.md +19 -1
  2. data/README.md +10 -3
  3. data/lib/simple_money/money.rb +97 -35
  4. 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 #=> 100
13
+ a.cents #=> 100
14
14
  b = a * 1.555
15
- b.cents #=> 156
16
- Money.overflow #=> #<BigDecimal:... '-0.5E0',4(16)>
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
  ---------
@@ -8,17 +8,17 @@ class Money
8
8
  class << self
9
9
 
10
10
  ##
11
- # The valid values for :as
11
+ # The valid values for as
12
12
  VALID_AS_VALUES = [:cents, :decimal]
13
13
 
14
14
  ##
15
- # The valid values for :rounding_method
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
- # method.
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 :as used to create a new Money (defaults to
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 :as used to create a new Money.
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 :rounding_method used when calculations do
72
- # not result in an Integer (defaults to :bankers).
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 :rounding_method used when calculations do not result in
77
- # and Integer.
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 value for :rounding_method, otherwise
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 were rounded.
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
- @overflow = BigDecimal("0")
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 Money.overflow.
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 argument error if an invalid
135
- # rounding method is given.
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 :as is set to :cents, n will be coerced to an
169
- # Integer. If :as is set to :decimal, n will be coerced to a BigDecimal.
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). Valid values are :cents and :decimal.
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 :as is not valid.
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(BigDecimal(n.to_s), rounding_method)
221
+ Money.round(
222
+ BigDecimal(n.to_s), rounding_method
223
+ )
206
224
  when :decimal
207
- Money.round(BigDecimal(n.to_s) * 100, rounding_method)
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(self.cents * BigDecimal(n.to_s), :as => :cents)
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 Money by a Money/Numeric; return the results as a new
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 or
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
- Money.new(self.cents / BigDecimal(n.to_s), :as => :cents)
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
- - 0
7
- - 1
8
- - 0
9
- version: 0.1.0
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-06 00:00:00 -05:00
17
+ date: 2011-01-10 00:00:00 -05:00
18
18
  default_executable:
19
19
  dependencies:
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
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/money.rb
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
- - !ruby/object:Gem::Version
76
- segments:
77
- - 1
78
- - 8
79
- - 7
80
- version: 1.8.7
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
- - !ruby/object:Gem::Version
86
- segments:
87
- - 1
88
- - 3
89
- - 7
90
- version: 1.3.7
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: