money 6.5.1 → 6.6.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.
@@ -12,13 +12,20 @@ describe Money do
12
12
  end
13
13
 
14
14
  describe "#==" do
15
- it "returns true if and only if their amount and currency are equal" do
15
+ it "returns true if both the amounts and currencies are equal" do
16
16
  expect(Money.new(1_00, "USD")).to eq Money.new(1_00, "USD")
17
17
  expect(Money.new(1_00, "USD")).not_to eq Money.new(1_00, "EUR")
18
18
  expect(Money.new(1_00, "USD")).not_to eq Money.new(2_00, "USD")
19
19
  expect(Money.new(1_00, "USD")).not_to eq Money.new(99_00, "EUR")
20
20
  end
21
21
 
22
+ it "returns true if both amounts are zero, even if currency differs" do
23
+ expect(Money.new(0, "USD")).to eq Money.new(0, "USD")
24
+ expect(Money.new(0, "USD")).to eq Money.new(0, "EUR")
25
+ expect(Money.new(0, "USD")).to eq Money.new(0, "AUD")
26
+ expect(Money.new(0, "USD")).to eq Money.new(0, "JPY")
27
+ end
28
+
22
29
  it "returns false if used to compare with an object that doesn't respond to #to_money" do
23
30
  expect(Money.new(1_00, "USD")).not_to eq Object.new
24
31
  expect(Money.new(1_00, "USD")).not_to eq Class
@@ -116,12 +123,11 @@ describe Money do
116
123
  expect(Money.new(1_00) <=> klass.new(Money.new(2_00))).to be < 0
117
124
  end
118
125
 
119
- it "raises ArgumentError when used to compare with an object that doesn't respond to #to_money" do
120
- expected_message = /Comparison .+ failed/
121
- expect{ Money.new(1_00) <=> Object.new }.to raise_error(ArgumentError, expected_message)
122
- expect{ Money.new(1_00) <=> Class }.to raise_error(ArgumentError, expected_message)
123
- expect{ Money.new(1_00) <=> Kernel }.to raise_error(ArgumentError, expected_message)
124
- expect{ Money.new(1_00) <=> /foo/ }.to raise_error(ArgumentError, expected_message)
126
+ it "returns nil when used to compare with an object that doesn't respond to #to_money" do
127
+ expect(Money.new(1_00) <=> Object.new).to be_nil
128
+ expect(Money.new(1_00) <=> Class).to be_nil
129
+ expect(Money.new(1_00) <=> Kernel).to be_nil
130
+ expect(Money.new(1_00) <=> /foo/).to be_nil
125
131
  end
126
132
  end
127
133
 
@@ -287,15 +293,7 @@ describe Money do
287
293
  end
288
294
  end
289
295
 
290
- context "infinite_precision = true" do
291
- before do
292
- Money.infinite_precision = true
293
- end
294
-
295
- after do
296
- Money.infinite_precision = false
297
- end
298
-
296
+ context "with infinite_precision", :infinite_precision do
299
297
  it "uses BigDecimal division" do
300
298
  ts = [
301
299
  {:a => Money.new( 13, :USD), :b => 4, :c => Money.new( 3.25, :USD)},
@@ -348,15 +346,7 @@ describe Money do
348
346
  end
349
347
  end
350
348
 
351
- context "infinite_precision = true" do
352
- before do
353
- Money.infinite_precision = true
354
- end
355
-
356
- after do
357
- Money.infinite_precision = false
358
- end
359
-
349
+ context "with infinite_precision", :infinite_precision do
360
350
  it "uses BigDecimal division" do
361
351
  ts = [
362
352
  {:a => Money.new( 13, :USD), :b => 4, :c => Money.new( 3.25, :USD)},
@@ -409,15 +399,7 @@ describe Money do
409
399
  end
410
400
  end
411
401
 
412
- context "infinite_precision = true" do
413
- before do
414
- Money.infinite_precision = true
415
- end
416
-
417
- after do
418
- Money.infinite_precision = false
419
- end
420
-
402
+ context "with infinite_precision", :infinite_precision do
421
403
  it "uses BigDecimal division" do
422
404
  ts = [
423
405
  {:a => Money.new( 13, :USD), :b => 4, :c => [Money.new( 3, :USD), Money.new( 1, :USD)]},
@@ -95,6 +95,23 @@ describe Money, "formatting" do
95
95
  expect(money.decimal_mark).to eq ','
96
96
  end
97
97
  end
98
+
99
+ context "with number.currency.symbol.*" do
100
+ before :each do
101
+ reset_i18n
102
+ I18n.locale = :de
103
+ I18n.backend.store_translations(
104
+ :de,
105
+ :number => { :currency => { :symbol => { :CAD => "CAD$" } } }
106
+ )
107
+ end
108
+
109
+ subject(:money) { Money.empty("CAD") }
110
+
111
+ it "should use 'CAD$' as the currency symbol" do
112
+ expect(money.format(:translate => true)).to eq("CAD$0.00")
113
+ end
114
+ end
98
115
  end
99
116
 
100
117
  describe "#format" do
@@ -512,15 +529,7 @@ describe Money, "formatting" do
512
529
  end
513
530
  end
514
531
 
515
- describe ":rounded_infinite_precision option" do
516
- before do
517
- Money.infinite_precision = true
518
- end
519
-
520
- after do
521
- Money.infinite_precision = false
522
- end
523
-
532
+ describe ":rounded_infinite_precision option", :infinite_precision do
524
533
  it "does round fractional when set to true" do
525
534
  expect(Money.new(BigDecimal.new('12.1'), "USD").format(:rounded_infinite_precision => true)).to eq "$0.12"
526
535
  expect(Money.new(BigDecimal.new('12.5'), "USD").format(:rounded_infinite_precision => true)).to eq "$0.13"
@@ -541,15 +550,13 @@ describe Money, "formatting" do
541
550
  expect(Money.new(BigDecimal.new('1'), "MGA").format(:rounded_infinite_precision => false)).to eq "Ar0.1"
542
551
  end
543
552
 
544
- describe ":rounded_infinite_precision option with i18n = false" do
553
+ describe "with i18n = false" do
545
554
  before do
546
555
  Money.use_i18n = false
547
- Money.infinite_precision = true
548
556
  end
549
557
 
550
558
  after do
551
559
  Money.use_i18n = true
552
- Money.infinite_precision = false
553
560
  end
554
561
 
555
562
  it 'does round fractional when set to true' do
data/spec/money_spec.rb CHANGED
@@ -78,8 +78,7 @@ describe Money do
78
78
  end
79
79
  end
80
80
 
81
- context "infinite_precision = true" do
82
- before { expect(Money).to receive(:infinite_precision).and_return(true) }
81
+ context "with infinite_precision", :infinite_precision do
83
82
  context 'given the initializing value is 1.50' do
84
83
  let(:initializing_value) { 1.50 }
85
84
 
@@ -121,6 +120,59 @@ describe Money do
121
120
  end
122
121
  end
123
122
 
123
+ describe ".from_amount" do
124
+ it "accepts numeric values" do
125
+ expect(Money.from_amount(1, "USD")).to eq Money.new(1_00, "USD")
126
+ expect(Money.from_amount(1.0, "USD")).to eq Money.new(1_00, "USD")
127
+ expect(Money.from_amount("1".to_d, "USD")).to eq Money.new(1_00, "USD")
128
+ end
129
+
130
+ it "raises ArgumentError with unsupported argument" do
131
+ expect { Money.from_amount("1") }.to raise_error(ArgumentError)
132
+ expect { Money.from_amount(Object.new) }.to raise_error(ArgumentError)
133
+ end
134
+
135
+ it "converts given amount to subunits according to currency" do
136
+ expect(Money.from_amount(1, "USD")).to eq Money.new(1_00, "USD")
137
+ expect(Money.from_amount(1, "TND")).to eq Money.new(1_000, "TND")
138
+ expect(Money.from_amount(1, "JPY")).to eq Money.new(1, "JPY")
139
+ end
140
+
141
+ it "rounds the given amount to subunits" do
142
+ expect(Money.from_amount(4.444, "USD").amount).to eq "4.44".to_d
143
+ expect(Money.from_amount(5.555, "USD").amount).to eq "5.56".to_d
144
+ expect(Money.from_amount(444.4, "JPY").amount).to eq "444".to_d
145
+ expect(Money.from_amount(555.5, "JPY").amount).to eq "556".to_d
146
+ end
147
+
148
+ it "does not round the given amount when infinite_precision is set", :infinite_precision do
149
+ expect(Money.from_amount(4.444, "USD").amount).to eq "4.444".to_d
150
+ expect(Money.from_amount(5.555, "USD").amount).to eq "5.555".to_d
151
+ expect(Money.from_amount(444.4, "JPY").amount).to eq "444.4".to_d
152
+ expect(Money.from_amount(555.5, "JPY").amount).to eq "555.5".to_d
153
+ end
154
+
155
+ it "accepts an optional currency" do
156
+ expect(Money.from_amount(1).currency).to eq Money.default_currency
157
+ jpy = Money::Currency.wrap("JPY")
158
+ expect(Money.from_amount(1, jpy).currency).to eq jpy
159
+ expect(Money.from_amount(1, "JPY").currency).to eq jpy
160
+ end
161
+
162
+ it "accepts an optional bank" do
163
+ expect(Money.from_amount(1).bank).to eq Money.default_bank
164
+ bank = double "bank"
165
+ expect(Money.from_amount(1, "USD", bank).bank).to eq bank
166
+ end
167
+
168
+ it 'rounds using rounding_mode' do
169
+ expect(Money.from_amount(1.999).to_d).to eq 2
170
+ expect(Money.rounding_mode(BigDecimal::ROUND_DOWN) do
171
+ Money.from_amount(1.999).to_d
172
+ end).to eq 1.99
173
+ end
174
+ end
175
+
124
176
  %w[cents pence].each do |units|
125
177
  describe "##{units}" do
126
178
  it "is a synonym of #fractional" do
@@ -176,19 +228,9 @@ YAML
176
228
  expect(m.fractional).to be_a(Integer)
177
229
  end
178
230
 
179
- context "with infinite_precision" do
180
- before do
181
- Money.infinite_precision = true
182
- end
183
-
184
- after do
185
- Money.infinite_precision = false
186
- end
187
-
188
- it "is a BigDecimal" do
189
- money = YAML::load serialized
190
- expect(money.fractional).to be_a BigDecimal
191
- end
231
+ it "is a BigDecimal when using infinite_precision", :infinite_precision do
232
+ money = YAML::load serialized
233
+ expect(money.fractional).to be_a BigDecimal
192
234
  end
193
235
  end
194
236
 
@@ -234,15 +276,7 @@ YAML
234
276
  end
235
277
  end
236
278
 
237
- context "infinite_precision = true" do
238
- before do
239
- Money.infinite_precision = true
240
- end
241
-
242
- after do
243
- Money.infinite_precision = false
244
- end
245
-
279
+ context "with infinite_precision", :infinite_precision do
246
280
  it "returns the amount in fractional unit" do
247
281
  expect(Money.new(1_00).fractional).to eq BigDecimal("100")
248
282
  end
@@ -254,87 +288,77 @@ YAML
254
288
  end
255
289
  end
256
290
  end
257
-
291
+
258
292
  describe "#round_to_nearest_cash_value" do
259
293
  it "rounds to the nearest possible cash value" do
260
294
  money = Money.new(2350, "AED")
261
295
  expect(money.round_to_nearest_cash_value).to eq 2350
262
-
296
+
263
297
  money = Money.new(-2350, "AED")
264
298
  expect(money.round_to_nearest_cash_value).to eq(-2350)
265
-
299
+
266
300
  money = Money.new(2213, "AED")
267
301
  expect(money.round_to_nearest_cash_value).to eq 2225
268
-
302
+
269
303
  money = Money.new(-2213, "AED")
270
304
  expect(money.round_to_nearest_cash_value).to eq(-2225)
271
-
305
+
272
306
  money = Money.new(2212, "AED")
273
307
  expect(money.round_to_nearest_cash_value).to eq 2200
274
-
308
+
275
309
  money = Money.new(-2212, "AED")
276
310
  expect(money.round_to_nearest_cash_value).to eq(-2200)
277
-
311
+
278
312
  money = Money.new(178, "CHF")
279
313
  expect(money.round_to_nearest_cash_value).to eq 180
280
-
314
+
281
315
  money = Money.new(-178, "CHF")
282
316
  expect(money.round_to_nearest_cash_value).to eq(-180)
283
-
317
+
284
318
  money = Money.new(177, "CHF")
285
319
  expect(money.round_to_nearest_cash_value).to eq 175
286
-
320
+
287
321
  money = Money.new(-177, "CHF")
288
322
  expect(money.round_to_nearest_cash_value).to eq(-175)
289
-
323
+
290
324
  money = Money.new(175, "CHF")
291
325
  expect(money.round_to_nearest_cash_value).to eq 175
292
-
326
+
293
327
  money = Money.new(-175, "CHF")
294
328
  expect(money.round_to_nearest_cash_value).to eq(-175)
295
-
329
+
296
330
  money = Money.new(299, "USD")
297
331
  expect(money.round_to_nearest_cash_value).to eq 299
298
-
332
+
299
333
  money = Money.new(-299, "USD")
300
334
  expect(money.round_to_nearest_cash_value).to eq(-299)
301
-
335
+
302
336
  money = Money.new(300, "USD")
303
337
  expect(money.round_to_nearest_cash_value).to eq 300
304
-
338
+
305
339
  money = Money.new(-300, "USD")
306
340
  expect(money.round_to_nearest_cash_value).to eq(-300)
307
-
341
+
308
342
  money = Money.new(301, "USD")
309
343
  expect(money.round_to_nearest_cash_value).to eq 301
310
-
344
+
311
345
  money = Money.new(-301, "USD")
312
346
  expect(money.round_to_nearest_cash_value).to eq(-301)
313
347
  end
314
-
348
+
315
349
  it "raises an exception if smallest denomination is not defined" do
316
350
  money = Money.new(100, "XAG")
317
351
  expect {money.round_to_nearest_cash_value}.to raise_error(Money::UndefinedSmallestDenomination)
318
352
  end
319
-
353
+
320
354
  it "returns a Fixnum when infinite_precision is not set" do
321
355
  money = Money.new(100, "USD")
322
356
  expect(money.round_to_nearest_cash_value).to be_a Fixnum
323
357
  end
324
-
325
- context "with infinite_precision" do
326
- before do
327
- Money.infinite_precision = true
328
- end
329
358
 
330
- after do
331
- Money.infinite_precision = false
332
- end
333
-
334
- it "returns a BigDecimal" do
335
- money = Money.new(100, "EUR")
336
- expect(money.round_to_nearest_cash_value).to be_a BigDecimal
337
- end
359
+ it "returns a BigDecimal when infinite_precision is set", :infinite_precision do
360
+ money = Money.new(100, "EUR")
361
+ expect(money.round_to_nearest_cash_value).to be_a BigDecimal
338
362
  end
339
363
  end
340
364
 
@@ -347,6 +371,7 @@ YAML
347
371
  expect(Money.new(1_00, "USD").amount).to eq 1
348
372
  expect(Money.new(1_000, "TND").amount).to eq 1
349
373
  expect(Money.new(1, "VUV").amount).to eq 1
374
+ expect(Money.new(1, "CLP").amount).to eq 1
350
375
  end
351
376
 
352
377
  it "does not loose precision" do
@@ -445,15 +470,7 @@ YAML
445
470
  expect(Money.new(10_00, "BRL").to_s).to eq "10,00"
446
471
  end
447
472
 
448
- context "infinite_precision = true" do
449
- before do
450
- Money.infinite_precision = true
451
- end
452
-
453
- after do
454
- Money.infinite_precision = false
455
- end
456
-
473
+ context "with infinite_precision", :infinite_precision do
457
474
  it "shows fractional cents" do
458
475
  expect(Money.new(1.05, "USD").to_s).to eq "0.0105"
459
476
  end
@@ -573,15 +590,7 @@ YAML
573
590
  expect { Money.us_dollar(0.05).allocate([0.5, 0.6]) }.to raise_error(ArgumentError)
574
591
  end
575
592
 
576
- context "infinite_precision = true" do
577
- before do
578
- Money.infinite_precision = true
579
- end
580
-
581
- after do
582
- Money.infinite_precision = false
583
- end
584
-
593
+ context "with infinite_precision", :infinite_precision do
585
594
  it "allows for fractional cents allocation" do
586
595
  one_third = BigDecimal("1") / BigDecimal("3")
587
596
 
@@ -618,15 +627,7 @@ YAML
618
627
  expect(moneys[2].cents).to eq 33
619
628
  end
620
629
 
621
- context "infinite_precision = true" do
622
- before do
623
- Money.infinite_precision = true
624
- end
625
-
626
- after do
627
- Money.infinite_precision = false
628
- end
629
-
630
+ context "with infinite_precision", :infinite_precision do
630
631
  it "allows for splitting by fractional cents" do
631
632
  thirty_three_and_one_third = BigDecimal("100") / BigDecimal("3")
632
633
 
@@ -644,10 +645,6 @@ YAML
644
645
  subject(:rounded) { money.round }
645
646
 
646
647
  context "without infinite_precision" do
647
- before do
648
- Money.infinite_precision = false
649
- end
650
-
651
648
  it "returns self (as it is already rounded)" do
652
649
  rounded = money.round
653
650
  expect(rounded).to be money
@@ -655,15 +652,7 @@ YAML
655
652
  end
656
653
  end
657
654
 
658
- context "with infinite_precision" do
659
- before do
660
- Money.infinite_precision = true
661
- end
662
-
663
- after do
664
- Money.infinite_precision = false
665
- end
666
-
655
+ context "with infinite_precision", :infinite_precision do
667
656
  it "returns a different money" do
668
657
  expect(rounded).not_to be money
669
658
  end
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+
3
+ describe Money::RatesStore::Memory do
4
+ let(:subject) { described_class.new }
5
+
6
+ describe '#add_rate and #get_rate' do
7
+ it 'stores rate in memory' do
8
+ expect(subject.add_rate('USD', 'CAD', 0.9)).to eql 0.9
9
+ expect(subject.get_rate('USD', 'CAD')).to eql 0.9
10
+ end
11
+ end
12
+
13
+ describe 'add_rate' do
14
+ it "uses a mutex by default" do
15
+ expect(subject.instance_variable_get(:@mutex)).to receive(:synchronize)
16
+ subject.add_rate('USD', 'EUR', 1.25)
17
+ end
18
+
19
+ context ':without_mutex' do
20
+ let(:subject) { Money::RatesStore::Memory.new(:without_mutex => true) }
21
+
22
+ it "doesn't use mutex if requested not to" do
23
+ expect(subject.instance_variable_get(:@mutex)).not_to receive(:synchronize)
24
+ subject.add_rate('USD', 'EUR', 1.25)
25
+ end
26
+ end
27
+ end
28
+
29
+ describe '#each_rate' do
30
+ before do
31
+ subject.add_rate('USD', 'CAD', 0.9)
32
+ subject.add_rate('CAD', 'USD', 1.1)
33
+ end
34
+
35
+ it 'iterates over rates' do
36
+ expect{|b| subject.each_rate(&b)}.to yield_successive_args(['USD', 'CAD', 0.9], ['CAD', 'USD', 1.1])
37
+ end
38
+
39
+ it 'is an Enumeator' do
40
+ expect(subject.each_rate).to be_kind_of(Enumerator)
41
+ result = subject.each_rate.each_with_object({}){|(from, to, rate),m| m[[from,to].join] = rate}
42
+ expect(result).to match({'USDCAD' => 0.9, 'CADUSD' => 1.1})
43
+ end
44
+ end
45
+
46
+ describe '#transaction' do
47
+ context 'mutex' do
48
+ it 'uses mutex' do
49
+ expect(subject.instance_variable_get('@mutex')).to receive(:synchronize)
50
+ subject.transaction{ a = 1}
51
+ end
52
+
53
+ it 'wraps block in mutex transaction only once' do
54
+ expect{
55
+ subject.transaction do
56
+ subject.add_rate('USD', 'CAD', 1)
57
+ end
58
+ }.not_to raise_error
59
+ end
60
+ end
61
+
62
+ context 'no mutex' do
63
+ let(:subject) { Money::RatesStore::Memory.new(:without_mutex => true) }
64
+
65
+ it 'does not use mutex' do
66
+ expect(subject.instance_variable_get('@mutex')).not_to receive(:synchronize)
67
+ subject.transaction{ a = 1}
68
+ end
69
+ end
70
+ end
71
+ end
data/spec/spec_helper.rb CHANGED
@@ -21,3 +21,13 @@ end
21
21
  def reset_i18n
22
22
  I18n.backend = I18n::Backend::Simple.new
23
23
  end
24
+
25
+ RSpec.shared_context "with infinite precision", :infinite_precision do
26
+ before do
27
+ Money.infinite_precision = true
28
+ end
29
+
30
+ after do
31
+ Money.infinite_precision = false
32
+ end
33
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: money
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.5.1
4
+ version: 6.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shane Emmons
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-03 00:00:00.000000000 Z
11
+ date: 2015-07-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: i18n
@@ -64,14 +64,14 @@ dependencies:
64
64
  requirements:
65
65
  - - "~>"
66
66
  - !ruby/object:Gem::Version
67
- version: 3.0.0
67
+ version: 3.2.0
68
68
  type: :development
69
69
  prerelease: false
70
70
  version_requirements: !ruby/object:Gem::Requirement
71
71
  requirements:
72
72
  - - "~>"
73
73
  - !ruby/object:Gem::Version
74
- version: 3.0.0
74
+ version: 3.2.0
75
75
  - !ruby/object:Gem::Dependency
76
76
  name: yard
77
77
  requirement: !ruby/object:Gem::Requirement
@@ -131,17 +131,20 @@ files:
131
131
  - lib/money/money/arithmetic.rb
132
132
  - lib/money/money/constructors.rb
133
133
  - lib/money/money/formatting.rb
134
+ - lib/money/rates_store/memory.rb
134
135
  - lib/money/version.rb
135
136
  - money.gemspec
136
137
  - spec/bank/base_spec.rb
137
138
  - spec/bank/single_currency_spec.rb
138
139
  - spec/bank/variable_exchange_spec.rb
139
140
  - spec/currency/heuristics_spec.rb
141
+ - spec/currency/loader_spec.rb
140
142
  - spec/currency_spec.rb
141
143
  - spec/money/arithmetic_spec.rb
142
144
  - spec/money/constructors_spec.rb
143
145
  - spec/money/formatting_spec.rb
144
146
  - spec/money_spec.rb
147
+ - spec/rates_store/memory_spec.rb
145
148
  - spec/spec_helper.rb
146
149
  homepage: http://rubymoney.github.io/money
147
150
  licenses:
@@ -171,7 +174,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
171
174
  version: '0'
172
175
  requirements: []
173
176
  rubyforge_project:
174
- rubygems_version: 2.2.2
177
+ rubygems_version: 2.4.5
175
178
  signing_key:
176
179
  specification_version: 4
177
180
  summary: A Ruby Library for dealing with money and currency conversion.
@@ -180,10 +183,12 @@ test_files:
180
183
  - spec/bank/single_currency_spec.rb
181
184
  - spec/bank/variable_exchange_spec.rb
182
185
  - spec/currency/heuristics_spec.rb
186
+ - spec/currency/loader_spec.rb
183
187
  - spec/currency_spec.rb
184
188
  - spec/money/arithmetic_spec.rb
185
189
  - spec/money/constructors_spec.rb
186
190
  - spec/money/formatting_spec.rb
187
191
  - spec/money_spec.rb
192
+ - spec/rates_store/memory_spec.rb
188
193
  - spec/spec_helper.rb
189
194
  has_rdoc: