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.
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: