Skip to content

Commit 28eaceb

Browse files
committed
Add methods to register, unregister, and reset currency symbols
1 parent f365762 commit 28eaceb

File tree

3 files changed

+103
-11
lines changed

3 files changed

+103
-11
lines changed

lib/monetize.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,5 +68,17 @@ def from_numeric(value, currency = Money.default_currency)
6868
fail ArgumentError, "'value' should be a type of Numeric" unless value.is_a?(Numeric)
6969
Money.from_amount(value, currency)
7070
end
71+
72+
def register_currency_symbol(symbol, iso_code)
73+
Monetize::Parser.register_currency_symbol(symbol, iso_code)
74+
end
75+
76+
def unregister_currency_symbol(symbol)
77+
Monetize::Parser.unregister_currency_symbol(symbol)
78+
end
79+
80+
def reset_currency_symbols!
81+
Monetize::Parser.reset_currency_symbols!
82+
end
7183
end
7284
end

lib/monetize/parser.rb

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
module Monetize
22
class Parser
3-
CURRENCY_SYMBOLS = {
3+
MULTIPLIER_SUFFIXES = { 'K' => 3, 'M' => 6, 'B' => 9, 'T' => 12 }
4+
MULTIPLIER_SUFFIXES.default = 0
5+
MULTIPLIER_REGEXP = /^(.*?\d)(#{MULTIPLIER_SUFFIXES.keys.join('|')})\b([^\d]*)$/i
6+
7+
DEFAULT_DECIMAL_MARK = '.'.freeze
8+
9+
@@original_currency_symbols = {
410
'$' => 'USD',
511
'€' => 'EUR',
612
'£' => 'GBP',
@@ -26,15 +32,38 @@ class Parser
2632
'S$' => 'SGD',
2733
'HK$'=> 'HKD',
2834
'NT$'=> 'TWD',
29-
'₱' => 'PHP',
30-
}
35+
'₱' => 'PHP'
36+
}.freeze
3137

32-
CURRENCY_SYMBOL_REGEX = /(?<![A-Z])(#{CURRENCY_SYMBOLS.keys.map { |key| Regexp.escape(key) }.join('|')})(?![A-Z])/i
33-
MULTIPLIER_SUFFIXES = { 'K' => 3, 'M' => 6, 'B' => 9, 'T' => 12 }
34-
MULTIPLIER_SUFFIXES.default = 0
35-
MULTIPLIER_REGEXP = Regexp.new(format('^(.*?\d)(%s)\b([^\d]*)$', MULTIPLIER_SUFFIXES.keys.join('|')), 'i')
38+
class << self
39+
def currency_symbols
40+
@@currency_symbols ||= @@original_currency_symbols.dup
41+
end
3642

37-
DEFAULT_DECIMAL_MARK = '.'.freeze
43+
def register_currency_symbol(symbol, iso_code)
44+
@@currency_symbols[symbol] = iso_code
45+
46+
reset_currency_symbol_regex
47+
end
48+
49+
def unregister_currency_symbol(symbol)
50+
@@currency_symbols.delete(symbol)
51+
reset_currency_symbol_regex
52+
end
53+
54+
def reset_currency_symbols!
55+
@@currency_symbols = @@original_currency_symbols.dup
56+
reset_currency_symbol_regex
57+
end
58+
59+
def currency_symbol_regex
60+
@@currency_symbol_regex ||= /(?<![A-Z])(#{currency_symbols.keys.map { |key| Regexp.escape(key) }.join('|')})(?![A-Z])/i
61+
end
62+
63+
def reset_currency_symbol_regex
64+
@@currency_symbol_regex = nil
65+
end
66+
end
3867

3968
def initialize(input, fallback_currency = Money.default_currency, options = {})
4069
@input = input.to_s.strip
@@ -91,9 +120,9 @@ def compute_currency_from_iso_code
91120
end
92121

93122
def compute_currency_from_symbol
94-
match = input.match(CURRENCY_SYMBOL_REGEX)
123+
match = input.match(self.class.currency_symbol_regex)
95124

96-
CURRENCY_SYMBOLS[match.to_s] if match
125+
self.class.currency_symbols[match.to_s] if match
97126
end
98127

99128
def assume_from_symbol?

spec/monetize_spec.rb

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
Monetize.assume_from_symbol = false
5555
end
5656

57-
Monetize::Parser::CURRENCY_SYMBOLS.each_pair do |symbol, iso_code|
57+
Monetize::Parser.currency_symbols.each_pair do |symbol, iso_code|
5858
context iso_code do
5959
let(:currency) { Money::Currency.find(iso_code) }
6060
let(:amount) { 5_95 }
@@ -132,6 +132,57 @@
132132
expect(Monetize.parse('kr9.99')).to eq Money.new(999, 'USD')
133133
end
134134
end
135+
136+
context "registered custom symbols and unregistering" do
137+
after { Monetize.reset_currency_symbols! }
138+
139+
it "parses registered custom currency symbol" do
140+
Monetize.register_currency_symbol("S/", "PEN")
141+
142+
expect(Monetize.parse("S/19.90")).to eq Money.new(1990, "PEN")
143+
end
144+
145+
it "overrides existing currency symbol when registering" do
146+
Monetize.register_currency_symbol("€", "USD")
147+
148+
expect(Monetize.parse("€19.90")).to eq Money.new(1990, "USD")
149+
end
150+
151+
it "unregisters custom currency symbol" do
152+
Monetize.register_currency_symbol("S/", "PEN")
153+
154+
expect(Monetize.parse("S/19.90")).to eq Money.new(1990, "PEN")
155+
156+
Monetize.unregister_currency_symbol("S/")
157+
158+
expect(Monetize.parse("S/19.90")).to eq Money.new(1990, "USD")
159+
end
160+
161+
it "unregisters existing currency symbol" do
162+
Monetize.unregister_currency_symbol("€")
163+
164+
expect(Monetize.parse("€19.90")).to eq Money.new(1990, "USD")
165+
end
166+
167+
it "unregisters non-registered currency symbol without errors" do
168+
expect {
169+
Monetize.unregister_currency_symbol("XYZ")
170+
}.not_to raise_error
171+
end
172+
173+
it "resets currency symbols to original set" do
174+
Monetize.register_currency_symbol("S/", "PEN")
175+
Monetize.unregister_currency_symbol("€")
176+
177+
expect(Monetize.parse("S/19.90")).to eq Money.new(1990, "PEN")
178+
expect(Monetize.parse("€19.90")).to eq Money.new(1990, "USD")
179+
180+
Monetize.reset_currency_symbols!
181+
182+
expect(Monetize.parse("€19.90")).to eq Money.new(1990, "EUR")
183+
expect(Monetize.parse("S/19.90")).to eq Money.new(1990, "USD")
184+
end
185+
end
135186
end
136187

137188
context 'opted out' do

0 commit comments

Comments
 (0)