From f3657624ab13f811ebe186c9aa1d7ce6b3e91ce8 Mon Sep 17 00:00:00 2001 From: Ruben Ignacio Guzman Zamora Date: Sat, 17 Jan 2026 15:43:50 -0500 Subject: [PATCH 1/4] Add separate methods for compute currency from iso code and symbol --- lib/monetize/parser.rb | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/lib/monetize/parser.rb b/lib/monetize/parser.rb index 02a6b328f..6bd0d7061 100644 --- a/lib/monetize/parser.rb +++ b/lib/monetize/parser.rb @@ -73,14 +73,27 @@ def to_big_decimal(value) attr_reader :input, :fallback_currency, :options def parse_currency - computed_currency = nil + computed_currency = compute_currency_from_iso_code + computed_currency ||= compute_currency_from_symbol if assume_from_symbol? + computed_currency ||= fallback_currency || Money.default_currency + + raise Money::Currency::UnknownCurrency unless computed_currency + + computed_currency + end + + def compute_currency_from_iso_code computed_currency = input[/[A-Z]{2,3}/] - computed_currency = nil unless Money::Currency.find(computed_currency) - computed_currency ||= compute_currency if assume_from_symbol? - found = computed_currency || fallback_currency || Money.default_currency - raise Money::Currency::UnknownCurrency unless found - found + return unless Money::Currency.find(computed_currency) + + computed_currency + end + + def compute_currency_from_symbol + match = input.match(CURRENCY_SYMBOL_REGEX) + + CURRENCY_SYMBOLS[match.to_s] if match end def assume_from_symbol? @@ -99,11 +112,6 @@ def apply_sign(negative, amount) negative ? amount * -1 : amount end - def compute_currency - match = input.match(CURRENCY_SYMBOL_REGEX) - CURRENCY_SYMBOLS[match.to_s] if match - end - def extract_major_minor(num, currency) used_delimiters = num.scan(/[^\d]/).uniq From 96ac50c8c2e16ecb89e4df858144d5bd5eda890a Mon Sep 17 00:00:00 2001 From: Ruben Ignacio Guzman Zamora Date: Sat, 17 Jan 2026 19:12:03 -0500 Subject: [PATCH 2/4] Add methods to register, unregister, and reset currency symbols --- lib/monetize.rb | 12 +++++++++ lib/monetize/parser.rb | 49 +++++++++++++++++++++++++++++-------- spec/monetize_spec.rb | 55 ++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 104 insertions(+), 12 deletions(-) diff --git a/lib/monetize.rb b/lib/monetize.rb index 1ec63d360..ca5e3eec1 100644 --- a/lib/monetize.rb +++ b/lib/monetize.rb @@ -68,5 +68,17 @@ def from_numeric(value, currency = Money.default_currency) fail ArgumentError, "'value' should be a type of Numeric" unless value.is_a?(Numeric) Money.from_amount(value, currency) end + + def register_currency_symbol(symbol, iso_code) + Monetize::Parser.register_currency_symbol(symbol, iso_code) + end + + def unregister_currency_symbol(symbol) + Monetize::Parser.unregister_currency_symbol(symbol) + end + + def reset_currency_symbols! + Monetize::Parser.reset_currency_symbols! + end end end diff --git a/lib/monetize/parser.rb b/lib/monetize/parser.rb index 6bd0d7061..c842f227e 100644 --- a/lib/monetize/parser.rb +++ b/lib/monetize/parser.rb @@ -1,6 +1,12 @@ module Monetize class Parser - CURRENCY_SYMBOLS = { + MULTIPLIER_SUFFIXES = { 'K' => 3, 'M' => 6, 'B' => 9, 'T' => 12 } + MULTIPLIER_SUFFIXES.default = 0 + MULTIPLIER_REGEXP = /^(.*?\d)(#{MULTIPLIER_SUFFIXES.keys.join('|')})\b([^\d]*)$/i + + DEFAULT_DECIMAL_MARK = '.'.freeze + + @@original_currency_symbols = { '$' => 'USD', '€' => 'EUR', '£' => 'GBP', @@ -26,15 +32,38 @@ class Parser 'S$' => 'SGD', 'HK$'=> 'HKD', 'NT$'=> 'TWD', - '₱' => 'PHP', - } + '₱' => 'PHP' + }.freeze - CURRENCY_SYMBOL_REGEX = /(? 3, 'M' => 6, 'B' => 9, 'T' => 12 } - MULTIPLIER_SUFFIXES.default = 0 - MULTIPLIER_REGEXP = Regexp.new(format('^(.*?\d)(%s)\b([^\d]*)$', MULTIPLIER_SUFFIXES.keys.join('|')), 'i') + class << self + def currency_symbols + @@currency_symbols ||= @@original_currency_symbols.dup + end - DEFAULT_DECIMAL_MARK = '.'.freeze + def register_currency_symbol(symbol, iso_code) + @@currency_symbols[symbol] = iso_code + + reset_currency_symbol_regex + end + + def unregister_currency_symbol(symbol) + @@currency_symbols.delete(symbol) + reset_currency_symbol_regex + end + + def reset_currency_symbols! + @@currency_symbols = @@original_currency_symbols.dup + reset_currency_symbol_regex + end + + def currency_symbol_regex + @@currency_symbol_regex ||= /(? Date: Sat, 17 Jan 2026 21:05:38 -0500 Subject: [PATCH 3/4] Use the accessor method in currency symbol registration --- lib/monetize/parser.rb | 4 ++-- spec/monetize_spec.rb | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/monetize/parser.rb b/lib/monetize/parser.rb index c842f227e..7bf78050a 100644 --- a/lib/monetize/parser.rb +++ b/lib/monetize/parser.rb @@ -41,13 +41,13 @@ def currency_symbols end def register_currency_symbol(symbol, iso_code) - @@currency_symbols[symbol] = iso_code + currency_symbols[symbol] = iso_code reset_currency_symbol_regex end def unregister_currency_symbol(symbol) - @@currency_symbols.delete(symbol) + currency_symbols.delete(symbol) reset_currency_symbol_regex end diff --git a/spec/monetize_spec.rb b/spec/monetize_spec.rb index 7b31df562..a1a3ff470 100644 --- a/spec/monetize_spec.rb +++ b/spec/monetize_spec.rb @@ -148,6 +148,16 @@ expect(Monetize.parse("€19.90")).to eq Money.new(1990, "USD") end + it "registers currency symbol before currency_symbols is accessed" do + Monetize::Parser.class_variable_set(:@@currency_symbols, nil) + + expect { + Monetize.register_currency_symbol("S/", "PEN") + }.not_to raise_error + + expect(Monetize.parse("S/19.90")).to eq Money.new(1990, "PEN") + end + it "unregisters custom currency symbol" do Monetize.register_currency_symbol("S/", "PEN") From 84db6dfd4e662a86028b176e874d0ff99d77d1c2 Mon Sep 17 00:00:00 2001 From: Ruben Ignacio Guzman Zamora Date: Sun, 18 Jan 2026 17:52:47 -0500 Subject: [PATCH 4/4] Simplify currency computation from ISO code by directly returning the Money::Currency.find result --- lib/monetize/parser.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/monetize/parser.rb b/lib/monetize/parser.rb index 7bf78050a..c1d3d96eb 100644 --- a/lib/monetize/parser.rb +++ b/lib/monetize/parser.rb @@ -112,11 +112,7 @@ def parse_currency end def compute_currency_from_iso_code - computed_currency = input[/[A-Z]{2,3}/] - - return unless Money::Currency.find(computed_currency) - - computed_currency + Money::Currency.find(input[/[A-Z]{2,3}/]) end def compute_currency_from_symbol