money 6.7.0 → 6.13.0

Sign up to get free protection for your applications and to get access to all the features.
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