simple_money 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gemtest ADDED
File without changes
data/Rakefile ADDED
@@ -0,0 +1,49 @@
1
+ require 'rubygems'
2
+ require 'rake/clean'
3
+
4
+ CLOBBER.include('doc', '.yardoc')
5
+
6
+ def gemspec
7
+ @gemspec ||= begin
8
+ file = File.expand_path("../simple_money.gemspec", __FILE__)
9
+ eval(File.read(file), binding, file)
10
+ end
11
+ end
12
+
13
+ begin
14
+ require 'rspec/core/rake_task'
15
+ RSpec::Core::RakeTask.new
16
+ rescue LoadError
17
+ task(:spec){abort "`gem install rspec` to run specs"}
18
+ end
19
+ task :default => :spec
20
+ task :test => :spec
21
+
22
+ begin
23
+ require 'yard'
24
+ YARD::Rake::YardocTask.new do |t|
25
+ t.options << "--files" << "CHANGELOG.md,LICENSE"
26
+ end
27
+ rescue LoadError
28
+ task(:yardoc){abort "`gem install yard` to generate documentation"}
29
+ end
30
+
31
+ begin
32
+ require 'rake/gempackagetask'
33
+ Rake::GemPackageTask.new(gemspec) do |pkg|
34
+ pkg.gem_spec = gemspec
35
+ end
36
+ task :gem => :gemspec
37
+ rescue LoadError
38
+ task(:gem){abort "`gem install rake` to package gems"}
39
+ end
40
+
41
+ desc "Install the gem locally"
42
+ task :install => :gem do
43
+ sh "gem install pkg/#{gemspec.full_name}.gem"
44
+ end
45
+
46
+ desc "Validate the gemspec"
47
+ task :gemspec do
48
+ gemspec.validate
49
+ end
@@ -0,0 +1,23 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "simple_money"
3
+ s.version = "0.3.0"
4
+ s.platform = Gem::Platform::RUBY
5
+ s.authors = ["Shane Emmons"]
6
+ s.email = "semmons99@gmail.com"
7
+ s.homepage = "http://github.com/semmons99/simple_money"
8
+ s.summary = "Library to work with money/currency."
9
+ s.description = "This gem is intended for working with financial calculations (money/currency) where you need highly accurate results."
10
+
11
+ s.required_ruby_version = ">= 1.8.7"
12
+ s.required_rubygems_version = ">= 1.3.7"
13
+
14
+ s.add_development_dependency "rspec", ">= 2.0.0"
15
+ s.add_development_dependency "yard"
16
+
17
+ s.files = Dir.glob("{lib,spec}/**/*")
18
+ s.files += %w(CHANGELOG.md LICENSE README.md)
19
+ s.files += %w(Rakefile .gemtest simple_money.gemspec)
20
+
21
+ s.require_path = "lib"
22
+ end
23
+
@@ -0,0 +1,43 @@
1
+ require 'simple_money/currency'
2
+
3
+ describe "Currency" do
4
+
5
+ USD = Currency::CurrencyStruct.new(
6
+ 1, "USD", "United States Dollar", "$", "Cent", 100, 2, true, "$", ".", ","
7
+ )
8
+
9
+ describe "#[]" do
10
+
11
+ it "should return a Hash pertaining to the requested currency id" do
12
+ Currency[:usd].should == USD
13
+ end
14
+
15
+ it "should work with and uppercase string" do
16
+ Currency["USD"].should == USD
17
+ end
18
+
19
+ it "should work with a lowercase string" do
20
+ Currency["usd"].should == USD
21
+ end
22
+
23
+ it "should work with a uppercase symbol" do
24
+ Currency[:USD].should == USD
25
+ end
26
+
27
+ it "should work with a lowercase symbol" do
28
+ Currency[:usd].should == USD
29
+ end
30
+
31
+ it "should raise an ArgumentError if an invalid currency is requested" do
32
+ lambda{
33
+ Currency[:not_a_real_currency]
34
+ }.should raise_error ArgumentError
35
+ end
36
+
37
+ it "should return the argument if it is already a CurrencyStruct" do
38
+ Currency[USD].should == USD
39
+ end
40
+
41
+ end
42
+
43
+ end
@@ -0,0 +1,840 @@
1
+ require 'simple_money/money'
2
+
3
+ describe "Money" do
4
+
5
+ # Make sure defaults are reset
6
+ after :each do
7
+ Money.default_as = :cents
8
+ Money.default_rounding_method = :bankers
9
+ Money.default_currency = :usd
10
+ Money.reset_overflow
11
+ end
12
+
13
+ describe ".default_as" do
14
+
15
+ it "should return the default as used to create a new Money" do
16
+ Money.default_as.should == :cents
17
+ end
18
+
19
+ end
20
+
21
+ describe ".default_as=" do
22
+
23
+ it "should set the default as used to create a new Money" do
24
+ Money.default_as = :decimal
25
+ Money.default_as.should == :decimal
26
+
27
+ Money.default_as = :cents
28
+ Money.default_as.should == :cents
29
+ end
30
+
31
+ it "should raise an ArgumentError unless as is valid" do
32
+ lambda{Money.default_as = :foo}.should raise_error ArgumentError
33
+ end
34
+
35
+ end
36
+
37
+ describe ".valid_as?" do
38
+
39
+ it "should return true if as is valid" do
40
+ Money.valid_as?(:cents).should == true
41
+ Money.valid_as?(:decimal).should == true
42
+ end
43
+
44
+ it "should return false if as is invalid" do
45
+ Money.valid_as?(:foo).should == false
46
+ end
47
+
48
+ end
49
+
50
+ describe ".default_rounding_method" do
51
+
52
+ it "should return the default rounding method used" do
53
+ Money.default_rounding_method.should == :bankers
54
+ end
55
+
56
+ end
57
+
58
+ describe ".default_rounding_method=" do
59
+
60
+ it "should set the default rounding method" do
61
+ Money.default_rounding_method = :away_from_zero
62
+ Money.default_rounding_method.should == :away_from_zero
63
+ end
64
+
65
+ it "should raise an ArgumentError unless rounding method is valid" do
66
+ lambda{
67
+ Money.default_rounding_method = :foo
68
+ }.should raise_error ArgumentError
69
+ end
70
+
71
+ end
72
+
73
+ describe ".valid_rounding_method?" do
74
+
75
+ it "should return true if rounding method is valid" do
76
+ Money.valid_rounding_method?(:away_from_zero).should == true
77
+ Money.valid_rounding_method?(:toward_zero).should == true
78
+ Money.valid_rounding_method?(:nearest_up).should == true
79
+ Money.valid_rounding_method?(:nearest_down).should == true
80
+ Money.valid_rounding_method?(:bankers).should == true
81
+ Money.valid_rounding_method?(:up).should == true
82
+ Money.valid_rounding_method?(:down).should == true
83
+ end
84
+
85
+ it "should return false if rounding method is invalid" do
86
+ Money.valid_rounding_method?(:foo).should == false
87
+ end
88
+
89
+ end
90
+
91
+ describe ".default_currency" do
92
+
93
+ it "should return the default currency used" do
94
+ Money.default_currency.should == Currency[:usd]
95
+ end
96
+
97
+ end
98
+
99
+ describe ".default_currency=" do
100
+
101
+ it "should set the default currency used" do
102
+ Money.default_currency.should == Currency[:usd]
103
+ Money.default_currency = :eur
104
+ Money.default_currency.should == Currency[:eur]
105
+ end
106
+
107
+ it "should raise and ArgumentError unless the currency is valid" do
108
+ lambda{
109
+ Money.default_currency = :not_a_real_currency
110
+ }.should raise_error ArgumentError
111
+ end
112
+
113
+ end
114
+
115
+ describe ".overflow" do
116
+
117
+ it "should return the sum of all rounded calculations" do
118
+ Money.overflow.should == BigDecimal("0")
119
+ Money.new(1.29)
120
+ Money.overflow.should == BigDecimal("0.29")
121
+ end
122
+
123
+ end
124
+
125
+ describe ".overflow=" do
126
+
127
+ it "should set the overflow to the provided value" do
128
+ Money.overflow.should == BigDecimal("0")
129
+ Money.overflow = 5
130
+ Money.overflow.should == BigDecimal("5")
131
+ end
132
+
133
+ end
134
+
135
+ describe ".reset_overflow" do
136
+
137
+ it "should reset the overflow bucket to 0" do
138
+ Money.overflow.should == BigDecimal("0")
139
+ Money.new(1.29)
140
+ Money.overflow.should == BigDecimal("0.29")
141
+ Money.reset_overflow
142
+ Money.overflow.should == BigDecimal("0")
143
+ end
144
+
145
+ end
146
+
147
+ describe ".round" do
148
+
149
+ context "without rounding method given" do
150
+
151
+ it "should round n using the default rounding method" do
152
+ Money.round(1.5).should == 2
153
+ Money.round(2.5).should == 2
154
+ Money.round(-1.5).should == -2
155
+ Money.round(-2.5).should == -2
156
+ end
157
+
158
+ it "should added rounded fractional cents to the overflow bucket" do
159
+ Money.round(1.5)
160
+ Money.overflow.should == BigDecimal("-0.5")
161
+ end
162
+
163
+ end
164
+
165
+ context "with rounding method given" do
166
+
167
+ it "should round n using the given rounding method" do
168
+ Money.round(1.5, :away_from_zero).should == 2
169
+ Money.round(1.5, :toward_zero).should == 1
170
+ Money.round(1.5, :nearest_up).should == 2
171
+ Money.round(1.5, :nearest_down).should == 1
172
+ Money.round(1.5, :bankers).should == 2
173
+ Money.round(1.5, :up).should == 2
174
+ Money.round(1.5, :down).should == 1
175
+
176
+ Money.round(2.5, :away_from_zero).should == 3
177
+ Money.round(2.5, :toward_zero).should == 2
178
+ Money.round(2.5, :nearest_up).should == 3
179
+ Money.round(2.5, :nearest_down).should == 2
180
+ Money.round(2.5, :bankers).should == 2
181
+ Money.round(2.5, :up).should == 3
182
+ Money.round(2.5, :down).should == 2
183
+
184
+ Money.round(-1.5, :away_from_zero).should == -2
185
+ Money.round(-1.5, :toward_zero).should == -1
186
+ Money.round(-1.5, :nearest_up).should == -2
187
+ Money.round(-1.5, :nearest_down).should == -1
188
+ Money.round(-1.5, :bankers).should == -2
189
+ Money.round(-1.5, :up).should == -1
190
+ Money.round(-1.5, :down).should == -2
191
+
192
+ Money.round(-2.5, :away_from_zero).should == -3
193
+ Money.round(-2.5, :toward_zero).should == -2
194
+ Money.round(-2.5, :nearest_up).should == -3
195
+ Money.round(-2.5, :nearest_down).should == -2
196
+ Money.round(-2.5, :bankers).should == -2
197
+ Money.round(-2.5, :up).should == -2
198
+ Money.round(-2.5, :down).should == -3
199
+ end
200
+
201
+ it "should added rounded fractional cents to the overflow bucket" do
202
+ Money.round(1.5, :away_from_zero)
203
+ Money.overflow.should == BigDecimal("-0.5")
204
+ end
205
+
206
+ it "should raise an ArgumentError unless rounding method is valid" do
207
+ lambda{
208
+ Money.round(1.29, :foo)
209
+ }.should raise_error ArgumentError
210
+ end
211
+
212
+ end
213
+
214
+ end
215
+
216
+ describe "#new" do
217
+
218
+ context "without value given" do
219
+
220
+ it "should default cents to 0" do
221
+ Money.new.cents.should == 0
222
+ end
223
+
224
+ end
225
+
226
+ context "with value given" do
227
+
228
+ it "should set cents appropriately" do
229
+ (0..100).each do |n|
230
+ Money.new(n).cents.should == n
231
+ end
232
+ end
233
+
234
+ it "should added rounded fractional cents to the overflow bucket" do
235
+ Money.new(1.5)
236
+ Money.overflow.should == BigDecimal("-0.5")
237
+ end
238
+
239
+ end
240
+
241
+ context "with :as => :cents" do
242
+
243
+ it "should treat passed value as cents" do
244
+ (0..100).each do |n|
245
+ Money.new(n, :as => :cents).cents.should == n
246
+ end
247
+ end
248
+
249
+ it "should added rounded fractional cents to the overflow bucket" do
250
+ Money.new(1.5, :as => :cents)
251
+ Money.overflow.should == BigDecimal("-0.5")
252
+ end
253
+
254
+ end
255
+
256
+ context "with :as => :decimal" do
257
+
258
+ it "should treat passed value as a decimal" do
259
+ ("0.01".."1.00").map(&:to_f).each do |n|
260
+ Money.new(n, :as => :decimal).cents.should == (
261
+ Money.round BigDecimal(n.to_s) * 100
262
+ )
263
+ end
264
+ end
265
+
266
+ it "should added rounded fractional cents to the overflow bucket" do
267
+ Money.new(1.555, :as => :decimal)
268
+ Money.overflow.should == BigDecimal("-0.5")
269
+ end
270
+
271
+ end
272
+
273
+ context "with invalid :as" do
274
+
275
+ it "should raise an ArgumentError" do
276
+ lambda{
277
+ Money.new(1_00, :as => :foo)
278
+ }.should raise_error ArgumentError
279
+ end
280
+ end
281
+
282
+ it "should use the default :as" do
283
+ Money.default_as = :decimal
284
+ ("0.01".."1.00").map(&:to_f).each do |n|
285
+ Money.new(n).cents.should == (
286
+ Money.round BigDecimal(n.to_s) * 100
287
+ )
288
+ end
289
+
290
+ Money.default_as = :cents
291
+ (0..100).each do |n|
292
+ Money.new(n).cents.should == n
293
+ end
294
+ end
295
+
296
+ context "with valid :rounding_method" do
297
+
298
+ it "should use the provided rounding method" do
299
+ n = Money.new(1_00, :rounding_method => :up)
300
+ n.rounding_method.should == :up
301
+ end
302
+
303
+ end
304
+
305
+ context "with invalid :rounding_method" do
306
+
307
+ it "should raise and ArgumentError" do
308
+ lambda{
309
+ Money.new(1_00, :rounding_method => :fake_rounding_method)
310
+ }.should raise_error ArgumentError
311
+ end
312
+
313
+ end
314
+
315
+ context "with valid :currency" do
316
+
317
+ context "with String" do
318
+
319
+ it "should use the provided currency to create the object" do
320
+ Money.new(1_00, :currency => "EUR").currency.should == Currency[:eur]
321
+ end
322
+
323
+ end
324
+
325
+ context "with Symbol" do
326
+
327
+ it "should use the provided currency to create the object" do
328
+ Money.new(1_00, :currency => :eur).currency.should == Currency[:eur]
329
+ end
330
+
331
+ end
332
+
333
+ context "with CurrencyStruct" do
334
+
335
+ it "should use the provided currency to create the object" do
336
+ c = Currency[:eur]
337
+ Money.new(1_00, :currency => c).currency.should == Currency[:eur]
338
+ end
339
+
340
+ end
341
+
342
+ it "should respect a currency.subunit_to_unit of 10" do
343
+ Money.new(
344
+ 1.9,
345
+ :as => :decimal,
346
+ :currency => :cny
347
+ ).cents.should == 19
348
+ end
349
+
350
+ it "should respect a currency.subunit_to_unit of 100" do
351
+ Money.new(
352
+ 1.99,
353
+ :as => :decimal,
354
+ :currency => :usd
355
+ ).cents.should == 199
356
+ end
357
+
358
+
359
+ it "should respect a currency.subunit_to_unit of 1000" do
360
+ Money.new(
361
+ 1.999,
362
+ :as => :decimal,
363
+ :currency => :bhd
364
+ ).cents.should == 1999
365
+ end
366
+
367
+
368
+ it "should respect a currency.subunit_to_unit of 1" do
369
+ Money.new(
370
+ 1,
371
+ :as => :decimal,
372
+ :currency => :clp
373
+ ).cents.should == 1
374
+ end
375
+
376
+
377
+ it "should respect a currency.subunit_to_unit of 5" do
378
+ Money.new(
379
+ 1.4,
380
+ :as => :decimal,
381
+ :currency => :mga
382
+ ).cents.should == 9
383
+ end
384
+
385
+ end
386
+
387
+ context "with invalid :currency" do
388
+
389
+ it "should raise an ArgumentError" do
390
+ lambda{
391
+ Money.new(1_00, :currency => :not_a_real_currency)
392
+ }.should raise_error ArgumentError
393
+ end
394
+
395
+ end
396
+
397
+ it "should use the default :currency" do
398
+ Money.default_currency = :eur
399
+ Money.new(1_00).currency.should == Currency[:eur]
400
+ end
401
+
402
+ end
403
+
404
+ describe "#+" do
405
+
406
+ it "should add two Money objects together" do
407
+ (0..100).to_a.combination(2).each do |(a,b)|
408
+ (Money.new(a) + Money.new(b)).cents.should == a + b
409
+ end
410
+ end
411
+
412
+ it "should raise an error if argument is not a Money" do
413
+ lambda{
414
+ Money.new + 0
415
+ }.should raise_error ArgumentError
416
+ end
417
+
418
+ it "should raise an error if the currency isn't the same" do
419
+ lambda{
420
+ Money.new(1_00, :currency => :usd) + Money.new(1_00, :currency => :eur)
421
+ }.should raise_error ArgumentError
422
+ end
423
+
424
+ it "should use the base objects rounding method" do
425
+ a = Money.new(1_00, :rounding_method => :up)
426
+ b = Money.new(1_00, :rounding_method => :up)
427
+ (a + b).rounding_method.should == :up
428
+ end
429
+
430
+ it "should use the base objects currency" do
431
+ a = Money.new(1_00, :currency => :eur)
432
+ b = Money.new(1_00, :currency => :eur)
433
+ (a + b).currency.should == Currency[:eur]
434
+ end
435
+
436
+ end
437
+
438
+ describe "#-" do
439
+
440
+ it "should subtract two Money objects from each other" do
441
+ (0..100).to_a.combination(2).each do |(a,b)|
442
+ (Money.new(a) - Money.new(b)).cents.should == a - b
443
+ end
444
+ end
445
+
446
+ it "should raise an error if argument is not a Money" do
447
+ lambda{Money.new - 0}.should raise_error ArgumentError
448
+ end
449
+
450
+ it "should raise an error if the currency isn't the same" do
451
+ lambda{
452
+ Money.new(1_00, :currency => :usd) - Money.new(1_00, :currency => :eur)
453
+ }.should raise_error ArgumentError
454
+ end
455
+
456
+ it "should use the base objects rounding method" do
457
+ a = Money.new(1_00, :rounding_method => :up)
458
+ b = Money.new(1_00, :rounding_method => :up)
459
+ (a - b).rounding_method.should == :up
460
+ end
461
+
462
+ it "should use the base objects currency" do
463
+ a = Money.new(1_00, :currency => :eur)
464
+ b = Money.new(1_00, :currency => :eur)
465
+ (a - b).currency.should == Currency[:eur]
466
+ end
467
+
468
+ end
469
+
470
+ describe "#*" do
471
+
472
+ it "should multiply a Money object by a Numeric" do
473
+ (0..100).to_a.combination(2).each do |(a,b)|
474
+ (Money.new(a) * b).cents.should == a * b
475
+ end
476
+
477
+ ("0.01".."1.00").map(&:to_f).combination(2).each do |(a,b)|
478
+ (Money.new(a, :as => :decimal) * b).cents.should == (
479
+ Money.round BigDecimal(a.to_s) * 100 * BigDecimal(b.to_s)
480
+ )
481
+ end
482
+ end
483
+
484
+ it "should added rounded fractional cents to the overflow bucket" do
485
+ Money.new(2) * 2.1
486
+ Money.overflow.should == BigDecimal("0.2")
487
+ end
488
+
489
+ it "should raise an error unless argument is a Numeric" do
490
+ lambda{Money.new * Money.new}.should raise_error ArgumentError
491
+ end
492
+
493
+ it "should use the base objects rounding method" do
494
+ a = Money.new(1_00, :rounding_method => :up)
495
+ (a * 2).rounding_method.should == :up
496
+ end
497
+
498
+ it "should use the base objects currency" do
499
+ a = Money.new(1_00, :currency => :eur)
500
+ (a * 2).currency.should == Currency[:eur]
501
+ end
502
+
503
+ end
504
+
505
+ describe "#/" do
506
+
507
+ it "should divide two Money objects" do
508
+ (1..100).to_a.combination(2).each do |(a,b)|
509
+ (Money.new(a) / Money.new(b)).should == (
510
+ BigDecimal(a.to_s) / BigDecimal(b.to_s)
511
+ )
512
+ end
513
+ end
514
+
515
+ it "should divide a Money object by a numeric" do
516
+ (1..100).to_a.combination(2).each do |(a,b)|
517
+ (Money.new(a) / b).cents.should == (
518
+ a.divmod(BigDecimal(b.to_s))[0]
519
+ )
520
+ (Money.new(a) / b.to_f).cents.should == (
521
+ a.divmod(BigDecimal(b.to_f.to_s))[0]
522
+ )
523
+ end
524
+ end
525
+
526
+ it "should added rounded fractional cents to the overflow bucket" do
527
+ Money.new(5) / 2
528
+ Money.overflow.should == BigDecimal("1")
529
+ end
530
+
531
+ it "should raise an error unless argument is a Money or Numeric" do
532
+ lambda{Money.new / :foo}.should raise_error ArgumentError
533
+ end
534
+
535
+ it "should raise an error if the currency isn't the same" do
536
+ lambda{
537
+ Money.new(1_00, :currency => :usd) / Money.new(1_00, :currency => :eur)
538
+ }.should raise_error ArgumentError
539
+ end
540
+
541
+ it "should use the base objects rounding method" do
542
+ a = Money.new(1_00, :rounding_method => :up)
543
+ (a / 2).rounding_method.should == :up
544
+ end
545
+
546
+ it "should use the base objects currency" do
547
+ a = Money.new(1_00, :currency => :eur)
548
+ (a / 2).currency.should == Currency[:eur]
549
+ end
550
+
551
+ end
552
+
553
+ describe "#%" do
554
+
555
+ it "should modulo two Money objects" do
556
+ (1..100).to_a.combination(2).each do |(a,b)|
557
+ (Money.new(a) % Money.new(b)).should == (
558
+ BigDecimal(a.to_s) % BigDecimal(b.to_s)
559
+ )
560
+ end
561
+ end
562
+
563
+ it "should modulo a Money object by a numeric" do
564
+ (1..100).to_a.combination(2).each do |(a,b)|
565
+ (Money.new(a) % b).cents.should == (
566
+ a % BigDecimal(b.to_s)
567
+ )
568
+ (Money.new(a) % b.to_f).cents.should == (
569
+ a % BigDecimal(b.to_f.to_s)
570
+ )
571
+ end
572
+ end
573
+
574
+ it "should raise an error unless argument is a Money or Numeric" do
575
+ lambda{Money.new % :foo}.should raise_error ArgumentError
576
+ end
577
+
578
+ it "should raise an error if the currency isn't the same" do
579
+ lambda{
580
+ Money.new(1_00, :currency => :usd) % Money.new(1_00, :currency => :eur)
581
+ }.should raise_error ArgumentError
582
+ end
583
+
584
+ it "should use the base objects rounding method" do
585
+ a = Money.new(1_00, :rounding_method => :up)
586
+ (a % 2).rounding_method.should == :up
587
+ end
588
+
589
+ it "should use the base objects currency" do
590
+ a = Money.new(1_00, :currency => :eur)
591
+ (a % 2).currency.should == Currency[:eur]
592
+ end
593
+
594
+ end
595
+
596
+ describe "#divmod" do
597
+
598
+ context "when n is a Money object" do
599
+
600
+ it "should return an appropriate array of values" do
601
+ Money.new(5).divmod(Money.new(2)).should == [
602
+ BigDecimal("2"), Money.new(1)
603
+ ]
604
+ end
605
+
606
+ it "should raise an ArgumentError if n is an incompatible currency" do
607
+ lambda{
608
+ Money.new(5_00, :currency => :usd).divmod(
609
+ Money.new(2_00, :currency => :eur)
610
+ )
611
+ }.should raise_error ArgumentError
612
+ end
613
+
614
+ it "should use the base objects rounding method" do
615
+ Money.new(
616
+ 5,
617
+ :rounding_method => :up
618
+ ).divmod(Money.new(2))[1].rounding_method.should == :up
619
+ end
620
+
621
+ it "should use the base objects currency" do
622
+ Money.new(
623
+ 5,
624
+ :currency => :eur
625
+ ).divmod(
626
+ Money.new(
627
+ 2,
628
+ :currency => :eur
629
+ )
630
+ )[1].currency.should == Currency[:eur]
631
+ end
632
+
633
+ end
634
+
635
+ context "when n is a Numeric" do
636
+
637
+ it "should return an appropriate array of values" do
638
+ Money.new(5).divmod(2).should == [
639
+ Money.new(2), Money.new(1)
640
+ ]
641
+ end
642
+
643
+ it "should add to overflow when necessary" do
644
+ Money.overflow.should == BigDecimal("0")
645
+ Money.new(5).divmod(2.1)
646
+ Money.overflow.should == BigDecimal("-0.2")
647
+ end
648
+
649
+ it "shoud use the base objects rounding method" do
650
+ n = Money.new(
651
+ 5,
652
+ :rounding_method => :up
653
+ ).divmod(2)
654
+ n[0].rounding_method.should == :up
655
+ n[1].rounding_method.should == :up
656
+ end
657
+
658
+ it "should use the base objects currency" do
659
+ n = Money.new(
660
+ 5,
661
+ :currency => :eur
662
+ ).divmod(2)
663
+ n[0].currency.should == Currency[:eur]
664
+ n[1].currency.should == Currency[:eur]
665
+ end
666
+
667
+ end
668
+
669
+ it "should raise an ArgumentError unless n is a Money/Numeric" do
670
+ lambda{
671
+ Money.new(5).divmod(:foo)
672
+ }.should raise_error ArgumentError
673
+ end
674
+
675
+ end
676
+
677
+ describe "#<=>" do
678
+
679
+ it "should return -1 if self < n" do
680
+ a = Money.new(1_00)
681
+ b = Money.new(2_00)
682
+ (a <=> b).should == -1
683
+ end
684
+
685
+ it "should return 1 if self > n" do
686
+ a = Money.new(1_00)
687
+ b = Money.new(2_00)
688
+ (b <=> a).should == 1
689
+ end
690
+
691
+ it "should return 0 if self == n" do
692
+ a = Money.new(1_00)
693
+ (a <=> a).should == 0
694
+ end
695
+
696
+ it "should raise an ArgumentError unless n is a Money object" do
697
+ lambda{
698
+ a = Money.new(1_00)
699
+ a <=> :foo
700
+ }.should raise_error ArgumentError
701
+ end
702
+
703
+ it "should raise an ArgumentError if currency of n isn't the same" do
704
+ lambda{
705
+ a = Money.new(1_00, :currency => :usd)
706
+ b = Money.new(2_00, :currency => :eur)
707
+ a <=> b
708
+ }.should raise_error ArgumentError
709
+ end
710
+
711
+ end
712
+
713
+ describe "#==" do
714
+
715
+ it "should return true when self == n" do
716
+ a = Money.new(1_00)
717
+ b = Money.new(1_00)
718
+ (a == b).should == true
719
+ end
720
+
721
+ it "should return false when self != n" do
722
+ a = Money.new(1_00)
723
+ b = Money.new(2_00)
724
+ (a == b).should == false
725
+ end
726
+
727
+ it "should raise an ArgumentError unless n is a Money object" do
728
+ lambda{
729
+ a = Money.new(1_00)
730
+ a == :foo
731
+ }.should raise_error ArgumentError
732
+ end
733
+
734
+ it "should raise an ArgumentError if currency of n isn't the same" do
735
+ lambda{
736
+ a = Money.new(1_00, :currency => :usd)
737
+ b = Money.new(2_00, :currency => :eur)
738
+ a == b
739
+ }.should raise_error ArgumentError
740
+ end
741
+
742
+ end
743
+
744
+ describe "abs" do
745
+
746
+ it "should return the a new Money object using cents.abs" do
747
+ Money.new(-1_00).abs.should == Money.new(1_00)
748
+ end
749
+
750
+ it "should use the base objects rounding method" do
751
+ Money.new(
752
+ -1_00,
753
+ :rounding_method => :up
754
+ ).abs.rounding_method.should == :up
755
+ end
756
+
757
+ it "should use the base objects currency" do
758
+ Money.new(
759
+ -1_00,
760
+ :currency => :eur
761
+ ).abs.currency.should == Currency[:eur]
762
+ end
763
+
764
+ end
765
+
766
+ describe "#to_s" do
767
+
768
+ it "should return cents formatted as a string" do
769
+ Money.new(1_00).to_s.should == "100"
770
+ end
771
+
772
+ context "with :as => :cents" do
773
+
774
+ it "should return cents formatted as a string" do
775
+ Money.new(1_00).to_s.should == "100"
776
+ end
777
+
778
+ end
779
+
780
+ context "with :as => :decimal" do
781
+
782
+ it "should return cents formatted as a decimal" do
783
+ Money.new(1_00).to_s(:as => :decimal).should == "1.00"
784
+ end
785
+
786
+ it "should work with a subunit_to_unit of 1" do
787
+ Money.new(
788
+ 1,
789
+ :as => :decimal,
790
+ :currency => :clp
791
+ ).to_s(:as => :decimal).should == "1"
792
+ end
793
+
794
+ it "should work with a subunit_to_unit of 5" do
795
+ Money.new(
796
+ 1.4,
797
+ :as => :decimal,
798
+ :currency => :mga
799
+ ).to_s(:as => :decimal).should == "1.4"
800
+ end
801
+
802
+ it "should work with a subunit_to_unit of 10" do
803
+ Money.new(
804
+ 1.9,
805
+ :as => :decimal,
806
+ :currency => :cny
807
+ ).to_s(:as => :decimal).should == "1.9"
808
+ end
809
+
810
+ it "should work with a subunit_to_unit of 100" do
811
+ Money.new(
812
+ 1.99,
813
+ :as => :decimal,
814
+ :currency => :usd
815
+ ).to_s(:as => :decimal).should == "1.99"
816
+ end
817
+
818
+ it "should work with a subunit_to_unit of 100" do
819
+ Money.new(
820
+ 1.999,
821
+ :as => :decimal,
822
+ :currency => :bhd
823
+ ).to_s(:as => :decimal).should == "1.999"
824
+ end
825
+
826
+ end
827
+
828
+ context "with invalid :as" do
829
+
830
+ it "should raise an ArgumentError" do
831
+ lambda{
832
+ Money.new(1_00).to_s(:as => :foo)
833
+ }.should raise_error ArgumentError
834
+ end
835
+
836
+ end
837
+
838
+ end
839
+
840
+ end
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple_money
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: false
4
+ hash: 19
5
+ prerelease:
5
6
  segments:
6
7
  - 0
7
- - 2
8
- - 1
9
- version: 0.2.1
8
+ - 3
9
+ - 0
10
+ version: 0.3.0
10
11
  platform: ruby
11
12
  authors:
12
13
  - Shane Emmons
@@ -14,7 +15,7 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2011-01-12 00:00:00 -05:00
18
+ date: 2011-02-18 00:00:00 -05:00
18
19
  default_executable:
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
@@ -25,6 +26,7 @@ dependencies:
25
26
  requirements:
26
27
  - - ">="
27
28
  - !ruby/object:Gem::Version
29
+ hash: 15
28
30
  segments:
29
31
  - 2
30
32
  - 0
@@ -40,12 +42,13 @@ dependencies:
40
42
  requirements:
41
43
  - - ">="
42
44
  - !ruby/object:Gem::Version
45
+ hash: 3
43
46
  segments:
44
47
  - 0
45
48
  version: "0"
46
49
  type: :development
47
50
  version_requirements: *id002
48
- description: This gem is intended for working with financial calculations where you need highly accurate results.
51
+ description: This gem is intended for working with financial calculations (money/currency) where you need highly accurate results.
49
52
  email: semmons99@gmail.com
50
53
  executables: []
51
54
 
@@ -57,9 +60,14 @@ files:
57
60
  - lib/simple_money/currency.rb
58
61
  - lib/simple_money/money.rb
59
62
  - lib/simple_money.rb
63
+ - spec/simple_money/currency_spec.rb
64
+ - spec/simple_money/money_spec.rb
60
65
  - CHANGELOG.md
61
66
  - LICENSE
62
67
  - README.md
68
+ - Rakefile
69
+ - .gemtest
70
+ - simple_money.gemspec
63
71
  has_rdoc: true
64
72
  homepage: http://github.com/semmons99/simple_money
65
73
  licenses: []
@@ -74,6 +82,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
74
82
  requirements:
75
83
  - - ">="
76
84
  - !ruby/object:Gem::Version
85
+ hash: 57
77
86
  segments:
78
87
  - 1
79
88
  - 8
@@ -84,6 +93,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
84
93
  requirements:
85
94
  - - ">="
86
95
  - !ruby/object:Gem::Version
96
+ hash: 21
87
97
  segments:
88
98
  - 1
89
99
  - 3
@@ -92,7 +102,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
92
102
  requirements: []
93
103
 
94
104
  rubyforge_project:
95
- rubygems_version: 1.3.7
105
+ rubygems_version: 1.5.2
96
106
  signing_key:
97
107
  specification_version: 3
98
108
  summary: Library to work with money/currency.