money 6.7.0 → 6.13.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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +2 -1
  3. data/.travis.yml +22 -5
  4. data/AUTHORS +5 -0
  5. data/CHANGELOG.md +109 -3
  6. data/Gemfile +13 -4
  7. data/LICENSE +2 -0
  8. data/README.md +69 -49
  9. data/config/currency_backwards_compatible.json +30 -0
  10. data/config/currency_iso.json +139 -62
  11. data/config/currency_non_iso.json +66 -2
  12. data/lib/money.rb +0 -13
  13. data/lib/money/bank/variable_exchange.rb +9 -22
  14. data/lib/money/currency.rb +35 -38
  15. data/lib/money/currency/heuristics.rb +1 -144
  16. data/lib/money/currency/loader.rb +1 -1
  17. data/lib/money/locale_backend/base.rb +7 -0
  18. data/lib/money/locale_backend/errors.rb +6 -0
  19. data/lib/money/locale_backend/i18n.rb +24 -0
  20. data/lib/money/locale_backend/legacy.rb +28 -0
  21. data/lib/money/money.rb +120 -151
  22. data/lib/money/money/allocation.rb +37 -0
  23. data/lib/money/money/arithmetic.rb +57 -52
  24. data/lib/money/money/constructors.rb +1 -2
  25. data/lib/money/money/formatter.rb +397 -0
  26. data/lib/money/money/formatting_rules.rb +120 -0
  27. data/lib/money/money/locale_backend.rb +20 -0
  28. data/lib/money/rates_store/memory.rb +1 -2
  29. data/lib/money/version.rb +1 -1
  30. data/money.gemspec +10 -16
  31. data/spec/bank/variable_exchange_spec.rb +7 -3
  32. data/spec/currency/heuristics_spec.rb +2 -153
  33. data/spec/currency_spec.rb +45 -4
  34. data/spec/locale_backend/i18n_spec.rb +62 -0
  35. data/spec/locale_backend/legacy_spec.rb +74 -0
  36. data/spec/money/allocation_spec.rb +130 -0
  37. data/spec/money/arithmetic_spec.rb +217 -104
  38. data/spec/money/constructors_spec.rb +0 -12
  39. data/spec/money/formatting_spec.rb +320 -179
  40. data/spec/money/locale_backend_spec.rb +14 -0
  41. data/spec/money_spec.rb +159 -26
  42. data/spec/rates_store/memory_spec.rb +13 -2
  43. data/spec/spec_helper.rb +2 -0
  44. data/spec/support/shared_examples/money_examples.rb +14 -0
  45. metadata +32 -41
  46. data/lib/money/money/formatting.rb +0 -417
@@ -0,0 +1,62 @@
1
+ # encoding: utf-8
2
+
3
+ describe Money::LocaleBackend::I18n do
4
+ describe '#initialize' do
5
+ it 'raises an error when I18n is not defined' do
6
+ hide_const('I18n')
7
+
8
+ expect { described_class.new }.to raise_error(Money::LocaleBackend::NotSupported)
9
+ end
10
+ end
11
+
12
+ describe '#lookup' do
13
+ after do
14
+ reset_i18n
15
+ I18n.locale = :en
16
+ end
17
+
18
+ subject { described_class.new }
19
+
20
+ context 'with number.currency.format defined' do
21
+ before do
22
+ I18n.locale = :de
23
+ I18n.backend.store_translations(:de, number: {
24
+ currency: { format: { delimiter: '.', separator: ',' } }
25
+ })
26
+ end
27
+
28
+ it 'returns thousands_separator based on the current locale' do
29
+ expect(subject.lookup(:thousands_separator, nil)).to eq('.')
30
+ end
31
+
32
+ it 'returns decimal_mark based on the current locale' do
33
+ expect(subject.lookup(:decimal_mark, nil)).to eq(',')
34
+ end
35
+ end
36
+
37
+ context 'with number.format defined' do
38
+ before do
39
+ I18n.locale = :de
40
+ I18n.backend.store_translations(:de, number: { format: { delimiter: '.', separator: ',' } })
41
+ end
42
+
43
+ it 'returns thousands_separator based on the current locale' do
44
+ expect(subject.lookup(:thousands_separator, nil)).to eq('.')
45
+ end
46
+
47
+ it 'returns decimal_mark based on the current locale' do
48
+ expect(subject.lookup(:decimal_mark, nil)).to eq(',')
49
+ end
50
+ end
51
+
52
+ context 'with no translation defined' do
53
+ it 'returns thousands_separator based on the current locale' do
54
+ expect(subject.lookup(:thousands_separator, nil)).to eq(nil)
55
+ end
56
+
57
+ it 'returns decimal_mark based on the current locale' do
58
+ expect(subject.lookup(:decimal_mark, nil)).to eq(nil)
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,74 @@
1
+ # encoding: utf-8
2
+
3
+ describe Money::LocaleBackend::Legacy do
4
+ after { Money.use_i18n = true }
5
+
6
+ describe '#initialize' do
7
+ it 'raises an error when use_i18n is true and I18n is not defined' do
8
+ Money.use_i18n = true
9
+ hide_const('I18n')
10
+
11
+ expect { described_class.new }.to raise_error(Money::LocaleBackend::NotSupported)
12
+ end
13
+
14
+ it 'does not raise error when use_i18n is false and I18n is not defined' do
15
+ Money.use_i18n = false
16
+ hide_const('I18n')
17
+
18
+ expect { described_class.new }.not_to raise_error
19
+ end
20
+ end
21
+
22
+ describe '#lookup' do
23
+ subject { described_class.new }
24
+ let(:currency) { Money::Currency.new('USD') }
25
+
26
+ context 'use_i18n is true and i18n lookup is successful' do
27
+ before do
28
+ allow(subject.send(:i18n_backend))
29
+ .to receive(:lookup)
30
+ .with(:thousands_separator, nil)
31
+ .and_return('.')
32
+
33
+ allow(subject.send(:i18n_backend))
34
+ .to receive(:lookup)
35
+ .with(:decimal_mark, nil)
36
+ .and_return(',')
37
+ end
38
+
39
+ it 'returns thousands_separator from I18n' do
40
+ expect(subject.lookup(:thousands_separator, currency)).to eq('.')
41
+ end
42
+
43
+ it 'returns decimal_mark based from I18n' do
44
+ expect(subject.lookup(:decimal_mark, currency)).to eq(',')
45
+ end
46
+ end
47
+
48
+ context 'use_i18n is true but i18n lookup is unsuccessful' do
49
+ before do
50
+ allow(subject.send(:i18n_backend)).to receive(:lookup).and_return(nil)
51
+ end
52
+
53
+ it 'returns thousands_separator as defined in currency' do
54
+ expect(subject.lookup(:thousands_separator, currency)).to eq(',')
55
+ end
56
+
57
+ it 'returns decimal_mark based as defined in currency' do
58
+ expect(subject.lookup(:decimal_mark, currency)).to eq('.')
59
+ end
60
+ end
61
+
62
+ context 'use_i18n is false' do
63
+ before { Money.use_i18n = false }
64
+
65
+ it 'returns thousands_separator as defined in currency' do
66
+ expect(subject.lookup(:thousands_separator, currency)).to eq(',')
67
+ end
68
+
69
+ it 'returns decimal_mark based as defined in currency' do
70
+ expect(subject.lookup(:decimal_mark, currency)).to eq('.')
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,130 @@
1
+ # encoding: utf-8
2
+
3
+ describe Money::Allocation do
4
+ describe 'given number as argument' do
5
+ it 'raises an error when invalid argument is given' do
6
+ expect { described_class.generate(100, 0) }.to raise_error(ArgumentError)
7
+ expect { described_class.generate(100, -1) }.to raise_error(ArgumentError)
8
+ end
9
+
10
+ context 'whole amounts' do
11
+ it 'returns the amount when 1 is given' do
12
+ expect(described_class.generate(100, 1)).to eq([100])
13
+ end
14
+
15
+ it 'splits the amount into equal parts' do
16
+ expect(described_class.generate(100, 2)).to eq([50, 50])
17
+ expect(described_class.generate(100, 4)).to eq([25, 25, 25, 25])
18
+ expect(described_class.generate(100, 5)).to eq([20, 20, 20, 20, 20])
19
+ end
20
+
21
+ it 'does not loose pennies' do
22
+ expect(described_class.generate(5, 2)).to eq([3, 2])
23
+ expect(described_class.generate(2, 3)).to eq([1, 1, 0])
24
+ expect(described_class.generate(100, 3)).to eq([34, 33, 33])
25
+ expect(described_class.generate(100, 6)).to eq([17, 17, 17, 17, 16, 16])
26
+ end
27
+ end
28
+
29
+ context 'fractional amounts' do
30
+ it 'returns the amount when 1 is given' do
31
+ expect(described_class.generate(BigDecimal(100), 1, false)).to eq([BigDecimal(100)])
32
+ end
33
+
34
+ it 'splits the amount into equal parts' do
35
+ expect(described_class.generate(BigDecimal(100), 2, false)).to eq([50, 50])
36
+ expect(described_class.generate(BigDecimal(100), 4, false)).to eq([25, 25, 25, 25])
37
+ expect(described_class.generate(BigDecimal(100), 5, false)).to eq([20, 20, 20, 20, 20])
38
+ end
39
+
40
+ it 'splits the amount into equal fractions' do
41
+ expect(described_class.generate(BigDecimal(5), 2, false)).to eq([2.5, 2.5])
42
+ expect(described_class.generate(BigDecimal(5), 4, false)).to eq([1.25, 1.25, 1.25, 1.25])
43
+ end
44
+
45
+ it 'handles splits into repeating decimals' do
46
+ amount = BigDecimal(100)
47
+ parts = described_class.generate(amount, 3, false)
48
+
49
+ # Rounding due to inconsistent BigDecimal size in ruby compared to jruby. In reality the
50
+ # first 2 elements will look like the last one with a '5' at the end, compensating for a
51
+ # missing fraction
52
+ expect(parts.map { |x| x.round(10) }).to eq([
53
+ BigDecimal('33.3333333333'),
54
+ BigDecimal('33.3333333333'),
55
+ BigDecimal('33.3333333333')
56
+ ])
57
+ expect(parts.inject(0, :+)).to eq(amount)
58
+ end
59
+ end
60
+ end
61
+
62
+ describe 'given array as argument' do
63
+ it 'raises an error when invalid argument is given' do
64
+ expect { described_class.generate(100, []) }.to raise_error(ArgumentError)
65
+ end
66
+
67
+ context 'whole amounts' do
68
+ it 'returns the amount when array contains only one element' do
69
+ expect(described_class.generate(100, [1])).to eq([100])
70
+ expect(described_class.generate(100, [5])).to eq([100])
71
+ end
72
+
73
+ it 'splits the amount into whole parts respecting the order' do
74
+ expect(described_class.generate(100, [1, 1])).to eq([50, 50])
75
+ expect(described_class.generate(100, [1, 1, 2])).to eq([25, 25, 50])
76
+ expect(described_class.generate(100, [7, 3])).to eq([70, 30])
77
+ end
78
+
79
+ it 'accepts floats as arguments' do
80
+ expect(described_class.generate(100, [1.0, 1.0])).to eq([50, 50])
81
+ expect(described_class.generate(100, [0.1, 0.1, 0.2])).to eq([25, 25, 50])
82
+ expect(described_class.generate(100, [0.07, 0.03])).to eq([70, 30])
83
+ expect(described_class.generate(10, [0.1, 0.2, 0.1])).to eq([3, 5, 2])
84
+ end
85
+
86
+ it 'does not loose pennies' do
87
+ expect(described_class.generate(10, [1, 1, 2])).to eq([3, 2, 5])
88
+ expect(described_class.generate(100, [1, 1, 1])).to eq([34, 33, 33])
89
+ end
90
+ end
91
+
92
+ context 'fractional amounts' do
93
+ it 'returns the amount when array contains only one element' do
94
+ expect(described_class.generate(BigDecimal(100), [1], false)).to eq([100])
95
+ expect(described_class.generate(BigDecimal(100), [5], false)).to eq([100])
96
+ end
97
+
98
+ it 'splits the amount into whole parts respecting the order' do
99
+ expect(described_class.generate(BigDecimal(100), [1, 1], false)).to eq([50, 50])
100
+ expect(described_class.generate(BigDecimal(100), [1, 1, 2], false)).to eq([25, 25, 50])
101
+ expect(described_class.generate(BigDecimal(100), [7, 3], false)).to eq([70, 30])
102
+ end
103
+
104
+ it 'splits the amount proportionally to the given parts' do
105
+ expect(described_class.generate(BigDecimal(10), [1, 1, 2], false)).to eq([2.5, 2.5, 5])
106
+ expect(described_class.generate(BigDecimal(7), [1, 1], false)).to eq([3.5, 3.5])
107
+ end
108
+
109
+ it 'keeps the class of the splits the same as given amount' do
110
+ # Note that whole_amount is false but result is whole values
111
+ expect(described_class.generate(10, [1, 1, 2], false)).to eq([3, 2, 5])
112
+ end
113
+
114
+ it 'handles splits into repeating decimals' do
115
+ amount = BigDecimal(100)
116
+ parts = described_class.generate(amount, [1, 1, 1], false)
117
+
118
+ # Rounding due to inconsistent BigDecimal size in ruby compared to jruby. In reality the
119
+ # first 2 elements will look like the last one with a '5' at the end, compensating for a
120
+ # missing fraction
121
+ expect(parts.map { |x| x.round(10) }).to eq([
122
+ BigDecimal('33.3333333333'),
123
+ BigDecimal('33.3333333333'),
124
+ BigDecimal('33.3333333333')
125
+ ])
126
+ expect(parts.inject(0, :+)).to eq(amount)
127
+ end
128
+ end
129
+ end
130
+ end
@@ -12,6 +12,8 @@ describe Money do
12
12
  special_money_class = Class.new(Money)
13
13
  expect(- special_money_class.new(10_00)).to be_a special_money_class
14
14
  end
15
+
16
+ it_behaves_like 'instance with custom bank', :-@
15
17
  end
16
18
 
17
19
  describe "#==" do
@@ -45,6 +47,19 @@ describe Money do
45
47
  expect(Money.new(2_50, "USD")).not_to eq klass.new(3_00, "USD")
46
48
  expect(Money.new(1_00, "GBP")).not_to eq klass.new(1_00, "USD")
47
49
  end
50
+
51
+ it 'allows comparison with zero' do
52
+ expect(Money.new(0, :usd)).to eq 0
53
+ expect(Money.new(0, :usd)).to eq 0.0
54
+ expect(Money.new(0, :usd)).to eq BigDecimal(0)
55
+ expect(Money.new(1, :usd)).to_not eq 0
56
+ end
57
+
58
+ it 'raises error for non-zero numerics' do
59
+ expect { Money.new(1_00, :usd) == 1 }.to raise_error ArgumentError
60
+ expect { Money.new(1_00, :usd) == -2.0 }.to raise_error ArgumentError
61
+ expect { Money.new(1_00, :usd) == Float::INFINITY }.to raise_error ArgumentError
62
+ end
48
63
  end
49
64
 
50
65
  describe "#eql?" do
@@ -55,6 +70,12 @@ describe Money do
55
70
  expect(Money.new(1_00, "USD").eql?(Money.new(99_00, "EUR"))).to be false
56
71
  end
57
72
 
73
+ it "returns true when their amounts are zero and currencies differ" do
74
+ expect(Money.new(0, "USD").eql?(Money.new(0, "EUR"))).to be true
75
+ expect(Money.new(0, "USD").eql?(Money.new(0, "USD"))).to be true
76
+ expect(Money.new(0, "AUD").eql?(Money.new(0, "EUR"))).to be true
77
+ end
78
+
58
79
  it "returns false if used to compare with an object that doesn't inherit from Money" do
59
80
  expect(Money.new(1_00, "USD").eql?(Object.new)).to be false
60
81
  expect(Money.new(1_00, "USD").eql?(Class)).to be false
@@ -108,17 +129,45 @@ describe Money do
108
129
  expect(Money.new(1_00) <=> klass.new(2_00)).to be < 0
109
130
  end
110
131
 
111
- it "raises TypeError when used to compare with an object that doesn't inherit from Money" do
132
+ it "returns nill when comparing with an object that doesn't inherit from Money" do
112
133
  expect(Money.new(1_00) <=> 100).to be_nil
113
-
114
134
  expect(Money.new(1_00) <=> Object.new).to be_nil
115
-
116
135
  expect(Money.new(1_00) <=> Class).to be_nil
117
-
118
136
  expect(Money.new(1_00) <=> Kernel).to be_nil
119
-
120
137
  expect(Money.new(1_00) <=> /foo/).to be_nil
121
138
  end
139
+
140
+ context 'when conversions disallowed' do
141
+ around do |example|
142
+ begin
143
+ old_default_bank = Money.default_bank
144
+ Money.disallow_currency_conversion!
145
+ example.run
146
+ ensure
147
+ Money.default_bank = old_default_bank
148
+ end
149
+ end
150
+
151
+ context 'when currencies differ' do
152
+ context 'when both values are 1_00' do
153
+ it 'raises currency error' do
154
+ expect { Money.usd(1_00) <=> Money.gbp(1_00) }.to raise_error Money::Bank::DifferentCurrencyError
155
+ end
156
+ end
157
+
158
+ context 'when both values are 0' do
159
+ it 'considers them equal' do
160
+ expect(Money.usd(0) <=> Money.gbp(0)).to eq(0)
161
+ end
162
+ end
163
+ end
164
+ end
165
+
166
+ it 'compares with numeric 0' do
167
+ expect(Money.usd(1) < 0).to eq false
168
+ expect(Money.usd(1) > 0.0).to eq true
169
+ expect(Money.usd(0) >= 0.0).to eq true
170
+ end
122
171
  end
123
172
 
124
173
  describe "#positive?" do
@@ -160,7 +209,7 @@ describe Money do
160
209
  expect(Money.new(10_00, "USD") + other).to eq Money.new(19_00, "USD")
161
210
  end
162
211
 
163
- it "adds Fixnum 0 to money and returns the same ammount" do
212
+ it "adds Integer 0 to money and returns the same ammount" do
164
213
  expect(Money.new(10_00) + 0).to eq Money.new(10_00)
165
214
  end
166
215
 
@@ -168,6 +217,8 @@ describe Money do
168
217
  special_money_class = Class.new(Money)
169
218
  expect(special_money_class.new(10_00, "USD") + Money.new(90, "USD")).to be_a special_money_class
170
219
  end
220
+
221
+ it_behaves_like 'instance with custom bank', :+, Money.new(1)
171
222
  end
172
223
 
173
224
  describe "#-" do
@@ -181,7 +232,7 @@ describe Money do
181
232
  expect(Money.new(10_00, "USD") - other).to eq Money.new(1_00, "USD")
182
233
  end
183
234
 
184
- it "subtract Fixnum 0 to money and returns the same ammount" do
235
+ it "subtract Integer 0 to money and returns the same ammount" do
185
236
  expect(Money.new(10_00) - 0).to eq Money.new(10_00)
186
237
  end
187
238
 
@@ -189,15 +240,17 @@ describe Money do
189
240
  special_money_class = Class.new(Money)
190
241
  expect(special_money_class.new(10_00, "USD") - Money.new(90, "USD")).to be_a special_money_class
191
242
  end
243
+
244
+ it_behaves_like 'instance with custom bank', :-, Money.new(1)
192
245
  end
193
246
 
194
247
  describe "#*" do
195
- it "multiplies Money by Fixnum and returns Money" do
248
+ it "multiplies Money by Integer and returns Money" do
196
249
  ts = [
197
- {:a => Money.new( 10, :USD), :b => 4, :c => Money.new( 40, :USD)},
198
- {:a => Money.new( 10, :USD), :b => -4, :c => Money.new(-40, :USD)},
199
- {:a => Money.new(-10, :USD), :b => 4, :c => Money.new(-40, :USD)},
200
- {:a => Money.new(-10, :USD), :b => -4, :c => Money.new( 40, :USD)},
250
+ {a: Money.new( 10, :USD), b: 4, c: Money.new( 40, :USD)},
251
+ {a: Money.new( 10, :USD), b: -4, c: Money.new(-40, :USD)},
252
+ {a: Money.new(-10, :USD), b: 4, c: Money.new(-40, :USD)},
253
+ {a: Money.new(-10, :USD), b: -4, c: Money.new( 40, :USD)},
201
254
  ]
202
255
  ts.each do |t|
203
256
  expect(t[:a] * t[:b]).to eq t[:c]
@@ -205,30 +258,32 @@ describe Money do
205
258
  end
206
259
 
207
260
  it "does not multiply Money by Money (same currency)" do
208
- expect { Money.new( 10, :USD) * Money.new( 4, :USD) }.to raise_error(ArgumentError)
261
+ expect { Money.new(10, :USD) * Money.new(4, :USD) }.to raise_error(TypeError)
209
262
  end
210
263
 
211
264
  it "does not multiply Money by Money (different currency)" do
212
- expect { Money.new( 10, :USD) * Money.new( 4, :EUR) }.to raise_error(ArgumentError)
265
+ expect { Money.new(10, :USD) * Money.new(4, :EUR) }.to raise_error(TypeError)
213
266
  end
214
267
 
215
268
  it "does not multiply Money by an object which is NOT a number" do
216
- expect { Money.new( 10, :USD) * 'abc' }.to raise_error(ArgumentError)
269
+ expect { Money.new(10, :USD) * 'abc' }.to raise_error(TypeError)
217
270
  end
218
271
 
219
272
  it "preserves the class in the result when using a subclass of Money" do
220
273
  special_money_class = Class.new(Money)
221
274
  expect(special_money_class.new(10_00, "USD") * 2).to be_a special_money_class
222
275
  end
276
+
277
+ it_behaves_like 'instance with custom bank', :*, 1
223
278
  end
224
279
 
225
280
  describe "#/" do
226
- it "divides Money by Fixnum and returns Money" do
281
+ it "divides Money by Integer and returns Money" do
227
282
  ts = [
228
- {:a => Money.new( 13, :USD), :b => 4, :c => Money.new( 3, :USD)},
229
- {:a => Money.new( 13, :USD), :b => -4, :c => Money.new(-3, :USD)},
230
- {:a => Money.new(-13, :USD), :b => 4, :c => Money.new(-3, :USD)},
231
- {:a => Money.new(-13, :USD), :b => -4, :c => Money.new( 3, :USD)},
283
+ {a: Money.new( 13, :USD), b: 4, c: Money.new( 3, :USD)},
284
+ {a: Money.new( 13, :USD), b: -4, c: Money.new(-3, :USD)},
285
+ {a: Money.new(-13, :USD), b: 4, c: Money.new(-3, :USD)},
286
+ {a: Money.new(-13, :USD), b: -4, c: Money.new( 3, :USD)},
232
287
  ]
233
288
  ts.each do |t|
234
289
  expect(t[:a] / t[:b]).to eq t[:c]
@@ -280,10 +335,10 @@ describe Money do
280
335
 
281
336
  it "divides Money by Money (same currency) and returns Float" do
282
337
  ts = [
283
- {:a => Money.new( 13, :USD), :b => Money.new( 4, :USD), :c => 3.25},
284
- {:a => Money.new( 13, :USD), :b => Money.new(-4, :USD), :c => -3.25},
285
- {:a => Money.new(-13, :USD), :b => Money.new( 4, :USD), :c => -3.25},
286
- {:a => Money.new(-13, :USD), :b => Money.new(-4, :USD), :c => 3.25},
338
+ {a: Money.new( 13, :USD), b: Money.new( 4, :USD), c: 3.25},
339
+ {a: Money.new( 13, :USD), b: Money.new(-4, :USD), c: -3.25},
340
+ {a: Money.new(-13, :USD), b: Money.new( 4, :USD), c: -3.25},
341
+ {a: Money.new(-13, :USD), b: Money.new(-4, :USD), c: 3.25},
287
342
  ]
288
343
  ts.each do |t|
289
344
  expect(t[:a] / t[:b]).to eq t[:c]
@@ -292,10 +347,10 @@ describe Money do
292
347
 
293
348
  it "divides Money by Money (different currency) and returns Float" do
294
349
  ts = [
295
- {:a => Money.new( 13, :USD), :b => Money.new( 4, :EUR), :c => 1.625},
296
- {:a => Money.new( 13, :USD), :b => Money.new(-4, :EUR), :c => -1.625},
297
- {:a => Money.new(-13, :USD), :b => Money.new( 4, :EUR), :c => -1.625},
298
- {:a => Money.new(-13, :USD), :b => Money.new(-4, :EUR), :c => 1.625},
350
+ {a: Money.new( 13, :USD), b: Money.new( 4, :EUR), c: 1.625},
351
+ {a: Money.new( 13, :USD), b: Money.new(-4, :EUR), c: -1.625},
352
+ {a: Money.new(-13, :USD), b: Money.new( 4, :EUR), c: -1.625},
353
+ {a: Money.new(-13, :USD), b: Money.new(-4, :EUR), c: 1.625},
299
354
  ]
300
355
  ts.each do |t|
301
356
  expect(t[:b]).to receive(:exchange_to).once.with(t[:a].currency).and_return(Money.new(t[:b].cents * 2, :USD))
@@ -306,25 +361,27 @@ describe Money do
306
361
  context "with infinite_precision", :infinite_precision do
307
362
  it "uses BigDecimal division" do
308
363
  ts = [
309
- {:a => Money.new( 13, :USD), :b => 4, :c => Money.new( 3.25, :USD)},
310
- {:a => Money.new( 13, :USD), :b => -4, :c => Money.new(-3.25, :USD)},
311
- {:a => Money.new(-13, :USD), :b => 4, :c => Money.new(-3.25, :USD)},
312
- {:a => Money.new(-13, :USD), :b => -4, :c => Money.new( 3.25, :USD)},
364
+ {a: Money.new( 13, :USD), b: 4, c: Money.new( 3.25, :USD)},
365
+ {a: Money.new( 13, :USD), b: -4, c: Money.new(-3.25, :USD)},
366
+ {a: Money.new(-13, :USD), b: 4, c: Money.new(-3.25, :USD)},
367
+ {a: Money.new(-13, :USD), b: -4, c: Money.new( 3.25, :USD)},
313
368
  ]
314
369
  ts.each do |t|
315
370
  expect(t[:a] / t[:b]).to eq t[:c]
316
371
  end
317
372
  end
318
373
  end
374
+
375
+ it_behaves_like 'instance with custom bank', :/, 1
319
376
  end
320
377
 
321
378
  describe "#div" do
322
- it "divides Money by Fixnum and returns Money" do
379
+ it "divides Money by Integer and returns Money" do
323
380
  ts = [
324
- {:a => Money.new( 13, :USD), :b => 4, :c => Money.new( 3, :USD)},
325
- {:a => Money.new( 13, :USD), :b => -4, :c => Money.new(-3, :USD)},
326
- {:a => Money.new(-13, :USD), :b => 4, :c => Money.new(-3, :USD)},
327
- {:a => Money.new(-13, :USD), :b => -4, :c => Money.new( 3, :USD)},
381
+ {a: Money.new( 13, :USD), b: 4, c: Money.new( 3, :USD)},
382
+ {a: Money.new( 13, :USD), b: -4, c: Money.new(-3, :USD)},
383
+ {a: Money.new(-13, :USD), b: 4, c: Money.new(-3, :USD)},
384
+ {a: Money.new(-13, :USD), b: -4, c: Money.new( 3, :USD)},
328
385
  ]
329
386
  ts.each do |t|
330
387
  expect(t[:a].div(t[:b])).to eq t[:c]
@@ -333,10 +390,10 @@ describe Money do
333
390
 
334
391
  it "divides Money by Money (same currency) and returns Float" do
335
392
  ts = [
336
- {:a => Money.new( 13, :USD), :b => Money.new( 4, :USD), :c => 3.25},
337
- {:a => Money.new( 13, :USD), :b => Money.new(-4, :USD), :c => -3.25},
338
- {:a => Money.new(-13, :USD), :b => Money.new( 4, :USD), :c => -3.25},
339
- {:a => Money.new(-13, :USD), :b => Money.new(-4, :USD), :c => 3.25},
393
+ {a: Money.new( 13, :USD), b: Money.new( 4, :USD), c: 3.25},
394
+ {a: Money.new( 13, :USD), b: Money.new(-4, :USD), c: -3.25},
395
+ {a: Money.new(-13, :USD), b: Money.new( 4, :USD), c: -3.25},
396
+ {a: Money.new(-13, :USD), b: Money.new(-4, :USD), c: 3.25},
340
397
  ]
341
398
  ts.each do |t|
342
399
  expect(t[:a].div(t[:b])).to eq t[:c]
@@ -345,10 +402,10 @@ describe Money do
345
402
 
346
403
  it "divides Money by Money (different currency) and returns Float" do
347
404
  ts = [
348
- {:a => Money.new( 13, :USD), :b => Money.new( 4, :EUR), :c => 1.625},
349
- {:a => Money.new( 13, :USD), :b => Money.new(-4, :EUR), :c => -1.625},
350
- {:a => Money.new(-13, :USD), :b => Money.new( 4, :EUR), :c => -1.625},
351
- {:a => Money.new(-13, :USD), :b => Money.new(-4, :EUR), :c => 1.625},
405
+ {a: Money.new( 13, :USD), b: Money.new( 4, :EUR), c: 1.625},
406
+ {a: Money.new( 13, :USD), b: Money.new(-4, :EUR), c: -1.625},
407
+ {a: Money.new(-13, :USD), b: Money.new( 4, :EUR), c: -1.625},
408
+ {a: Money.new(-13, :USD), b: Money.new(-4, :EUR), c: 1.625},
352
409
  ]
353
410
  ts.each do |t|
354
411
  expect(t[:b]).to receive(:exchange_to).once.with(t[:a].currency).and_return(Money.new(t[:b].cents * 2, :USD))
@@ -359,10 +416,10 @@ describe Money do
359
416
  context "with infinite_precision", :infinite_precision do
360
417
  it "uses BigDecimal division" do
361
418
  ts = [
362
- {:a => Money.new( 13, :USD), :b => 4, :c => Money.new( 3.25, :USD)},
363
- {:a => Money.new( 13, :USD), :b => -4, :c => Money.new(-3.25, :USD)},
364
- {:a => Money.new(-13, :USD), :b => 4, :c => Money.new(-3.25, :USD)},
365
- {:a => Money.new(-13, :USD), :b => -4, :c => Money.new( 3.25, :USD)},
419
+ {a: Money.new( 13, :USD), b: 4, c: Money.new( 3.25, :USD)},
420
+ {a: Money.new( 13, :USD), b: -4, c: Money.new(-3.25, :USD)},
421
+ {a: Money.new(-13, :USD), b: 4, c: Money.new(-3.25, :USD)},
422
+ {a: Money.new(-13, :USD), b: -4, c: Money.new( 3.25, :USD)},
366
423
  ]
367
424
  ts.each do |t|
368
425
  expect(t[:a].div(t[:b])).to eq t[:c]
@@ -372,12 +429,12 @@ describe Money do
372
429
  end
373
430
 
374
431
  describe "#divmod" do
375
- it "calculates division and modulo with Fixnum" do
432
+ it "calculates division and modulo with Integer" do
376
433
  ts = [
377
- {:a => Money.new( 13, :USD), :b => 4, :c => [Money.new( 3, :USD), Money.new( 1, :USD)]},
378
- {:a => Money.new( 13, :USD), :b => -4, :c => [Money.new(-3, :USD), Money.new(-3, :USD)]},
379
- {:a => Money.new(-13, :USD), :b => 4, :c => [Money.new(-3, :USD), Money.new( 3, :USD)]},
380
- {:a => Money.new(-13, :USD), :b => -4, :c => [Money.new( 3, :USD), Money.new(-1, :USD)]},
434
+ {a: Money.new( 13, :USD), b: 4, c: [Money.new( 3, :USD), Money.new( 1, :USD)]},
435
+ {a: Money.new( 13, :USD), b: -4, c: [Money.new(-4, :USD), Money.new(-3, :USD)]},
436
+ {a: Money.new(-13, :USD), b: 4, c: [Money.new(-4, :USD), Money.new( 3, :USD)]},
437
+ {a: Money.new(-13, :USD), b: -4, c: [Money.new( 3, :USD), Money.new(-1, :USD)]},
381
438
  ]
382
439
  ts.each do |t|
383
440
  expect(t[:a].divmod(t[:b])).to eq t[:c]
@@ -386,10 +443,10 @@ describe Money do
386
443
 
387
444
  it "calculates division and modulo with Money (same currency)" do
388
445
  ts = [
389
- {:a => Money.new( 13, :USD), :b => Money.new( 4, :USD), :c => [ 3, Money.new( 1, :USD)]},
390
- {:a => Money.new( 13, :USD), :b => Money.new(-4, :USD), :c => [-4, Money.new(-3, :USD)]},
391
- {:a => Money.new(-13, :USD), :b => Money.new( 4, :USD), :c => [-4, Money.new( 3, :USD)]},
392
- {:a => Money.new(-13, :USD), :b => Money.new(-4, :USD), :c => [ 3, Money.new(-1, :USD)]},
446
+ {a: Money.new( 13, :USD), b: Money.new( 4, :USD), c: [ 3, Money.new( 1, :USD)]},
447
+ {a: Money.new( 13, :USD), b: Money.new(-4, :USD), c: [-4, Money.new(-3, :USD)]},
448
+ {a: Money.new(-13, :USD), b: Money.new( 4, :USD), c: [-4, Money.new( 3, :USD)]},
449
+ {a: Money.new(-13, :USD), b: Money.new(-4, :USD), c: [ 3, Money.new(-1, :USD)]},
393
450
  ]
394
451
  ts.each do |t|
395
452
  expect(t[:a].divmod(t[:b])).to eq t[:c]
@@ -398,10 +455,10 @@ describe Money do
398
455
 
399
456
  it "calculates division and modulo with Money (different currency)" do
400
457
  ts = [
401
- {:a => Money.new( 13, :USD), :b => Money.new( 4, :EUR), :c => [ 1, Money.new( 5, :USD)]},
402
- {:a => Money.new( 13, :USD), :b => Money.new(-4, :EUR), :c => [-2, Money.new(-3, :USD)]},
403
- {:a => Money.new(-13, :USD), :b => Money.new( 4, :EUR), :c => [-2, Money.new( 3, :USD)]},
404
- {:a => Money.new(-13, :USD), :b => Money.new(-4, :EUR), :c => [ 1, Money.new(-5, :USD)]},
458
+ {a: Money.new( 13, :USD), b: Money.new( 4, :EUR), c: [ 1, Money.new( 5, :USD)]},
459
+ {a: Money.new( 13, :USD), b: Money.new(-4, :EUR), c: [-2, Money.new(-3, :USD)]},
460
+ {a: Money.new(-13, :USD), b: Money.new( 4, :EUR), c: [-2, Money.new( 3, :USD)]},
461
+ {a: Money.new(-13, :USD), b: Money.new(-4, :EUR), c: [ 1, Money.new(-5, :USD)]},
405
462
  ]
406
463
  ts.each do |t|
407
464
  expect(t[:b]).to receive(:exchange_to).once.with(t[:a].currency).and_return(Money.new(t[:b].cents * 2, :USD))
@@ -412,10 +469,10 @@ describe Money do
412
469
  context "with infinite_precision", :infinite_precision do
413
470
  it "uses BigDecimal division" do
414
471
  ts = [
415
- {:a => Money.new( 13, :USD), :b => 4, :c => [Money.new( 3, :USD), Money.new( 1, :USD)]},
416
- {:a => Money.new( 13, :USD), :b => -4, :c => [Money.new(-4, :USD), Money.new(-3, :USD)]},
417
- {:a => Money.new(-13, :USD), :b => 4, :c => [Money.new(-4, :USD), Money.new( 3, :USD)]},
418
- {:a => Money.new(-13, :USD), :b => -4, :c => [Money.new( 3, :USD), Money.new(-1, :USD)]},
472
+ {a: Money.new( 13, :USD), b: 4, c: [Money.new( 3, :USD), Money.new( 1, :USD)]},
473
+ {a: Money.new( 13, :USD), b: -4, c: [Money.new(-4, :USD), Money.new(-3, :USD)]},
474
+ {a: Money.new(-13, :USD), b: 4, c: [Money.new(-4, :USD), Money.new( 3, :USD)]},
475
+ {a: Money.new(-13, :USD), b: -4, c: [Money.new( 3, :USD), Money.new(-1, :USD)]},
419
476
  ]
420
477
  ts.each do |t|
421
478
  expect(t[:a].divmod(t[:b])).to eq t[:c]
@@ -432,15 +489,18 @@ describe Money do
432
489
  special_money_class = Class.new(Money)
433
490
  expect(special_money_class.new(10_00, "USD").divmod(special_money_class.new(4_00)).last).to be_a special_money_class
434
491
  end
492
+
493
+ it_behaves_like 'instance with custom bank', :divmod, Money.new(1)
494
+ it_behaves_like 'instance with custom bank', :divmod, 1
435
495
  end
436
496
 
437
497
  describe "#modulo" do
438
- it "calculates modulo with Fixnum" do
498
+ it "calculates modulo with Integer" do
439
499
  ts = [
440
- {:a => Money.new( 13, :USD), :b => 4, :c => Money.new( 1, :USD)},
441
- {:a => Money.new( 13, :USD), :b => -4, :c => Money.new(-3, :USD)},
442
- {:a => Money.new(-13, :USD), :b => 4, :c => Money.new( 3, :USD)},
443
- {:a => Money.new(-13, :USD), :b => -4, :c => Money.new(-1, :USD)},
500
+ {a: Money.new( 13, :USD), b: 4, c: Money.new( 1, :USD)},
501
+ {a: Money.new( 13, :USD), b: -4, c: Money.new(-3, :USD)},
502
+ {a: Money.new(-13, :USD), b: 4, c: Money.new( 3, :USD)},
503
+ {a: Money.new(-13, :USD), b: -4, c: Money.new(-1, :USD)},
444
504
  ]
445
505
  ts.each do |t|
446
506
  expect(t[:a].modulo(t[:b])).to eq t[:c]
@@ -449,10 +509,10 @@ describe Money do
449
509
 
450
510
  it "calculates modulo with Money (same currency)" do
451
511
  ts = [
452
- {:a => Money.new( 13, :USD), :b => Money.new( 4, :USD), :c => Money.new( 1, :USD)},
453
- {:a => Money.new( 13, :USD), :b => Money.new(-4, :USD), :c => Money.new(-3, :USD)},
454
- {:a => Money.new(-13, :USD), :b => Money.new( 4, :USD), :c => Money.new( 3, :USD)},
455
- {:a => Money.new(-13, :USD), :b => Money.new(-4, :USD), :c => Money.new(-1, :USD)},
512
+ {a: Money.new( 13, :USD), b: Money.new( 4, :USD), c: Money.new( 1, :USD)},
513
+ {a: Money.new( 13, :USD), b: Money.new(-4, :USD), c: Money.new(-3, :USD)},
514
+ {a: Money.new(-13, :USD), b: Money.new( 4, :USD), c: Money.new( 3, :USD)},
515
+ {a: Money.new(-13, :USD), b: Money.new(-4, :USD), c: Money.new(-1, :USD)},
456
516
  ]
457
517
  ts.each do |t|
458
518
  expect(t[:a].modulo(t[:b])).to eq t[:c]
@@ -461,10 +521,10 @@ describe Money do
461
521
 
462
522
  it "calculates modulo with Money (different currency)" do
463
523
  ts = [
464
- {:a => Money.new( 13, :USD), :b => Money.new( 4, :EUR), :c => Money.new( 5, :USD)},
465
- {:a => Money.new( 13, :USD), :b => Money.new(-4, :EUR), :c => Money.new(-3, :USD)},
466
- {:a => Money.new(-13, :USD), :b => Money.new( 4, :EUR), :c => Money.new( 3, :USD)},
467
- {:a => Money.new(-13, :USD), :b => Money.new(-4, :EUR), :c => Money.new(-5, :USD)},
524
+ {a: Money.new( 13, :USD), b: Money.new( 4, :EUR), c: Money.new( 5, :USD)},
525
+ {a: Money.new( 13, :USD), b: Money.new(-4, :EUR), c: Money.new(-3, :USD)},
526
+ {a: Money.new(-13, :USD), b: Money.new( 4, :EUR), c: Money.new( 3, :USD)},
527
+ {a: Money.new(-13, :USD), b: Money.new(-4, :EUR), c: Money.new(-5, :USD)},
468
528
  ]
469
529
  ts.each do |t|
470
530
  expect(t[:b]).to receive(:exchange_to).once.with(t[:a].currency).and_return(Money.new(t[:b].cents * 2, :USD))
@@ -474,12 +534,12 @@ describe Money do
474
534
  end
475
535
 
476
536
  describe "#%" do
477
- it "calculates modulo with Fixnum" do
537
+ it "calculates modulo with Integer" do
478
538
  ts = [
479
- {:a => Money.new( 13, :USD), :b => 4, :c => Money.new( 1, :USD)},
480
- {:a => Money.new( 13, :USD), :b => -4, :c => Money.new(-3, :USD)},
481
- {:a => Money.new(-13, :USD), :b => 4, :c => Money.new( 3, :USD)},
482
- {:a => Money.new(-13, :USD), :b => -4, :c => Money.new(-1, :USD)},
539
+ {a: Money.new( 13, :USD), b: 4, c: Money.new( 1, :USD)},
540
+ {a: Money.new( 13, :USD), b: -4, c: Money.new(-3, :USD)},
541
+ {a: Money.new(-13, :USD), b: 4, c: Money.new( 3, :USD)},
542
+ {a: Money.new(-13, :USD), b: -4, c: Money.new(-1, :USD)},
483
543
  ]
484
544
  ts.each do |t|
485
545
  expect(t[:a] % t[:b]).to eq t[:c]
@@ -488,10 +548,10 @@ describe Money do
488
548
 
489
549
  it "calculates modulo with Money (same currency)" do
490
550
  ts = [
491
- {:a => Money.new( 13, :USD), :b => Money.new( 4, :USD), :c => Money.new( 1, :USD)},
492
- {:a => Money.new( 13, :USD), :b => Money.new(-4, :USD), :c => Money.new(-3, :USD)},
493
- {:a => Money.new(-13, :USD), :b => Money.new( 4, :USD), :c => Money.new( 3, :USD)},
494
- {:a => Money.new(-13, :USD), :b => Money.new(-4, :USD), :c => Money.new(-1, :USD)},
551
+ {a: Money.new( 13, :USD), b: Money.new( 4, :USD), c: Money.new( 1, :USD)},
552
+ {a: Money.new( 13, :USD), b: Money.new(-4, :USD), c: Money.new(-3, :USD)},
553
+ {a: Money.new(-13, :USD), b: Money.new( 4, :USD), c: Money.new( 3, :USD)},
554
+ {a: Money.new(-13, :USD), b: Money.new(-4, :USD), c: Money.new(-1, :USD)},
495
555
  ]
496
556
  ts.each do |t|
497
557
  expect(t[:a] % t[:b]).to eq t[:c]
@@ -500,10 +560,10 @@ describe Money do
500
560
 
501
561
  it "calculates modulo with Money (different currency)" do
502
562
  ts = [
503
- {:a => Money.new( 13, :USD), :b => Money.new( 4, :EUR), :c => Money.new( 5, :USD)},
504
- {:a => Money.new( 13, :USD), :b => Money.new(-4, :EUR), :c => Money.new(-3, :USD)},
505
- {:a => Money.new(-13, :USD), :b => Money.new( 4, :EUR), :c => Money.new( 3, :USD)},
506
- {:a => Money.new(-13, :USD), :b => Money.new(-4, :EUR), :c => Money.new(-5, :USD)},
563
+ {a: Money.new( 13, :USD), b: Money.new( 4, :EUR), c: Money.new( 5, :USD)},
564
+ {a: Money.new( 13, :USD), b: Money.new(-4, :EUR), c: Money.new(-3, :USD)},
565
+ {a: Money.new(-13, :USD), b: Money.new( 4, :EUR), c: Money.new( 3, :USD)},
566
+ {a: Money.new(-13, :USD), b: Money.new(-4, :EUR), c: Money.new(-5, :USD)},
507
567
  ]
508
568
  ts.each do |t|
509
569
  expect(t[:b]).to receive(:exchange_to).once.with(t[:a].currency).and_return(Money.new(t[:b].cents * 2, :USD))
@@ -513,17 +573,19 @@ describe Money do
513
573
  end
514
574
 
515
575
  describe "#remainder" do
516
- it "calculates remainder with Fixnum" do
576
+ it "calculates remainder with Integer" do
517
577
  ts = [
518
- {:a => Money.new( 13, :USD), :b => 4, :c => Money.new( 1, :USD)},
519
- {:a => Money.new( 13, :USD), :b => -4, :c => Money.new( 1, :USD)},
520
- {:a => Money.new(-13, :USD), :b => 4, :c => Money.new(-1, :USD)},
521
- {:a => Money.new(-13, :USD), :b => -4, :c => Money.new(-1, :USD)},
578
+ {a: Money.new( 13, :USD), b: 4, c: Money.new( 1, :USD)},
579
+ {a: Money.new( 13, :USD), b: -4, c: Money.new( 1, :USD)},
580
+ {a: Money.new(-13, :USD), b: 4, c: Money.new(-1, :USD)},
581
+ {a: Money.new(-13, :USD), b: -4, c: Money.new(-1, :USD)},
522
582
  ]
523
583
  ts.each do |t|
524
584
  expect(t[:a].remainder(t[:b])).to eq t[:c]
525
585
  end
526
586
  end
587
+
588
+ it_behaves_like 'instance with custom bank', :remainder, -1
527
589
  end
528
590
 
529
591
  describe "#abs" do
@@ -537,6 +599,8 @@ describe Money do
537
599
  special_money_class = Class.new(Money)
538
600
  expect(special_money_class.new(-1).abs).to be_a special_money_class
539
601
  end
602
+
603
+ it_behaves_like 'instance with custom bank', :abs
540
604
  end
541
605
 
542
606
  describe "#zero?" do
@@ -567,6 +631,11 @@ describe Money do
567
631
  end
568
632
 
569
633
  describe "#coerce" do
634
+ it 'allows non-default currency money objects to be summed' do
635
+ result = 0 + Money.new(4, 'EUR') + Money.new(5, 'EUR')
636
+ expect(result).to eq Money.new(9, 'EUR')
637
+ end
638
+
570
639
  it "allows mathematical operations by coercing arguments" do
571
640
  result = 2 * Money.new(4, 'USD')
572
641
  expect(result).to eq Money.new(8, 'USD')
@@ -590,6 +659,16 @@ describe Money do
590
659
  }.to raise_exception(TypeError)
591
660
  end
592
661
 
662
+ it "allows subtraction from numeric zero" do
663
+ result = 0 - Money.new(4, 'USD')
664
+ expect(result).to eq Money.new(-4, 'USD')
665
+ end
666
+
667
+ it "allows addition from numeric zero" do
668
+ result = 0 + Money.new(4, 'USD')
669
+ expect(result).to eq Money.new(4, 'USD')
670
+ end
671
+
593
672
  it "treats multiplication as commutative" do
594
673
  expect {
595
674
  2 * Money.new(2, 'USD')
@@ -607,23 +686,27 @@ describe Money do
607
686
  it "correctly handles <=>" do
608
687
  expect {
609
688
  2 < Money.new(2, 'USD')
610
- }.to raise_exception(TypeError)
689
+ }.to raise_exception(ArgumentError)
611
690
 
612
691
  expect {
613
692
  2 > Money.new(2, 'USD')
614
- }.to raise_exception(TypeError)
693
+ }.to raise_exception(ArgumentError)
615
694
 
616
695
  expect {
617
696
  2 <= Money.new(2, 'USD')
618
- }.to raise_exception(TypeError)
697
+ }.to raise_exception(ArgumentError)
619
698
 
620
699
  expect {
621
700
  2 >= Money.new(2, 'USD')
622
- }.to raise_exception(TypeError)
701
+ }.to raise_exception(ArgumentError)
623
702
 
624
- expect {
625
- 2 <=> Money.new(2, 'USD')
626
- }.to raise_exception(TypeError)
703
+ expect(2 <=> Money.new(2, 'USD')).to be_nil
704
+ end
705
+
706
+ it 'compares with numeric 0' do
707
+ expect(0 < Money.usd(1)).to eq true
708
+ expect(0.0 > Money.usd(1)).to eq false
709
+ expect(0.0 >= Money.usd(0)).to eq true
627
710
  end
628
711
 
629
712
  it "raises exceptions for all numeric types, not just Integer" do
@@ -640,4 +723,34 @@ describe Money do
640
723
  }.to raise_exception(TypeError)
641
724
  end
642
725
  end
726
+
727
+ %w(+ - / divmod remainder).each do |op|
728
+ describe "##{op}" do
729
+ subject { ->(other = self.other) { instance.send(op, other) } }
730
+ let(:instance) { Money.usd(1) }
731
+
732
+ context 'when conversions disallowed' do
733
+ around do |ex|
734
+ begin
735
+ old = Money.default_bank
736
+ Money.disallow_currency_conversion!
737
+ ex.run
738
+ ensure
739
+ Money.default_bank = old
740
+ end
741
+ end
742
+
743
+ context 'and other is money with different currency' do
744
+ let(:other) { Money.gbp(1) }
745
+ it { should raise_error Money::Bank::DifferentCurrencyError }
746
+
747
+ context 'even for zero' do
748
+ let(:instance) { Money.usd(0) }
749
+ let(:other) { Money.gbp(0) }
750
+ it { should raise_error Money::Bank::DifferentCurrencyError }
751
+ end
752
+ end
753
+ end
754
+ end
755
+ end
643
756
  end