simple_money 0.2.1 → 0.3.0

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