diff --git a/CHANGELOG.md b/CHANGELOG.md index 2af9a0b8de..d045874cbb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ - **Potential breaking change**: Fix MGA (Malagasy Ariary) to be a zero-decimal currency (changing subunit_to_unit from 5 to 1) - **Potential breaking change**: Remove special handling for Japanese language only - **Potential breaking change**: Adjust formatting rules to use i18n translations for `:format` +- **Potential breaking change**: Not allow divide by zero - Updated Armenian Dram sign and HTML entity - Updated the Turkmen Manat symbol and HTML entity and added disambiguation symbol for TMM - Expose Money::VERSION diff --git a/lib/money/money/arithmetic.rb b/lib/money/money/arithmetic.rb index 37c4aa8079..95ddc8099f 100644 --- a/lib/money/money/arithmetic.rb +++ b/lib/money/money/arithmetic.rb @@ -200,10 +200,15 @@ def *(value) # def /(value) if value.is_a?(self.class) - fractional / as_d(value.exchange_to(currency).fractional).to_f + exchanged = value.exchange_to(currency) + raise ZeroDivisionError, "divided by Money(0)" if exchanged.zero? + fractional / as_d(exchanged.fractional).to_f else raise TypeError, 'Can not divide by Money' if value.is_a?(CoercedNumeric) - dup_with(fractional: fractional / as_d(value)) + + value = as_d(value) + raise ZeroDivisionError, "divided by zero" if value.zero? + dup_with(fractional: fractional / value) end end @@ -240,13 +245,16 @@ def divmod(val) def divmod_money(val) cents = val.exchange_to(currency).cents + raise ZeroDivisionError, "divided by Money(0)" if cents == 0 quotient, remainder = fractional.divmod(cents) [quotient, dup_with(fractional: remainder)] end private :divmod_money def divmod_other(val) - quotient, remainder = fractional.divmod(as_d(val)) + val = as_d(val) + raise ZeroDivisionError, "divided by zero" if val.zero? + quotient, remainder = fractional.divmod(val) [dup_with(fractional: quotient), dup_with(fractional: remainder)] end private :divmod_other diff --git a/spec/money/arithmetic_spec.rb b/spec/money/arithmetic_spec.rb index 0ad1b503e3..710366333c 100644 --- a/spec/money/arithmetic_spec.rb +++ b/spec/money/arithmetic_spec.rb @@ -437,6 +437,28 @@ end end + it "raises ZeroDivisionError when dividing by Money with zero value" do + money = Money.new(100, "USD") + zero_money = Money.new(0, "USD") + + expect { money / zero_money }.to raise_error(ZeroDivisionError, "divided by Money(0)") + end + + it "raises ZeroDivisionError when dividing by Money with zero value in same currency" do + money = Money.new(100, "USD") + zero_usd = Money.new(0, "USD") + + expect { money / zero_usd }.to raise_error(ZeroDivisionError, "divided by Money(0)") + end + + it "raises ZeroDivisionError when dividing by numeric zero" do + money = Money.new(100, "USD") + + expect { money / 0 }.to raise_error(ZeroDivisionError, "divided by zero") + expect { money / 0.0 }.to raise_error(ZeroDivisionError, "divided by zero") + expect { money / BigDecimal("0") }.to raise_error(ZeroDivisionError, "divided by zero") + end + it_behaves_like 'instance with custom bank', :/, 1 end @@ -555,6 +577,28 @@ expect(special_money_class.new(10_00, "USD").divmod(special_money_class.new(4_00)).last).to be_a special_money_class end + it "raises ZeroDivisionError when dividing by Money with zero value" do + money = Money.new(100, "USD") + zero_money = Money.new(0, "USD") + + expect { money.divmod(zero_money) }.to raise_error(ZeroDivisionError, "divided by Money(0)") + end + + it "raises ZeroDivisionError when dividing by Money with zero value in same currency" do + money = Money.new(100, "USD") + zero_usd = Money.new(0, "USD") + + expect { money.divmod(zero_usd) }.to raise_error(ZeroDivisionError, "divided by Money(0)") + end + + it "raises ZeroDivisionError when dividing by numeric zero" do + money = Money.new(100, "USD") + + expect { money.divmod(0) }.to raise_error(ZeroDivisionError, "divided by zero") + expect { money.divmod(0.0) }.to raise_error(ZeroDivisionError, "divided by zero") + expect { money.divmod(BigDecimal("0")) }.to raise_error(ZeroDivisionError, "divided by zero") + end + it_behaves_like 'instance with custom bank', :divmod, -> { Money.new(1) } it_behaves_like 'instance with custom bank', :divmod, 1 end