diff --git a/CHANGELOG.md b/CHANGELOG.md index 519ff8fabe..fef91dedf4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased +- Fix `Money::Currency.unregister` raising `NoMethodError` when called before the currency table was loaded, for example in an initializer right after `require "money"` - Fix `Money::Allocation.generate` converting a Rational with unlimited `to_d` precision. It now uses `Money.conversion_precision` - Fix `Money::Currency.reset!` keeping the cached key set, so a currency registered before the reset was still accepted by `Money::Currency.new` and raised `NoMethodError` instead of `UnknownCurrency` - Fix `Money::Bank::VariableExchange#import_rates` parsing `:json` with `JSON.load`, which instantiates any class named by a `json_class` key; it now uses `JSON.parse` diff --git a/lib/money/currency.rb b/lib/money/currency.rb index d4e96be88e..3517a20436 100644 --- a/lib/money/currency.rb +++ b/lib/money/currency.rb @@ -204,8 +204,12 @@ def unregister(curr) else curr.downcase.to_sym end - existed = @table.delete(key) - @stringified_keys = nil if existed + existed = table.delete(key) + if existed + @@mutex.synchronize { _instances.delete(key.to_s) } + @stringified_keys = nil + clear_iso_numeric_cache + end existed ? true : false end # rubocop:enable Naming/PredicateMethod diff --git a/spec/money/currency_spec.rb b/spec/money/currency_spec.rb index 1b809d7f22..2823e6a0ef 100644 --- a/spec/money/currency_spec.rb +++ b/spec/money/currency_spec.rb @@ -241,6 +241,32 @@ def to_s described_class.unregister(:yyz) expect(described_class.find(:yyz)).to be_nil end + + context "when the currency table changes" do + after { described_class.reset! } + + it "works before the currency table has been loaded" do + described_class.instance_variable_set(:@table, nil) + + expect(described_class.unregister(:usd)).to be true + expect(described_class.find(:usd)).to be_nil + expect(described_class.find(:eur)).to eq described_class.new(:eur) + end + + it "returns false for an unknown currency before the table has been loaded" do + described_class.instance_variable_set(:@table, nil) + + expect(described_class.unregister(:abc)).to be false + end + + it "drops the currency from the iso_numeric lookup" do + expect(described_class.find_by_iso_numeric(978)).to eq described_class.new(:eur) + + described_class.unregister(:eur) + + expect(described_class.find_by_iso_numeric(978)).to be_nil + end + end end # rubocop:disable Style/MapIntoArray