Skip to content

Commit a3b3643

Browse files
committed
Merge pull request rails#4667 from carlosantoniodasilva/av-number-helper
Action View number helpers improvements
2 parents a6aea14 + 74fabdf commit a3b3643

File tree

2 files changed

+55
-44
lines changed

2 files changed

+55
-44
lines changed

actionpack/lib/action_view/helpers/number_helper.rb

Lines changed: 30 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,11 @@ def initialize(number)
5757
# # => +1.123.555.1234 x 1343
5858
def number_to_phone(number, options = {})
5959
return unless number
60+
options = options.symbolize_keys
6061

61-
begin
62-
Float(number)
63-
rescue ArgumentError, TypeError
64-
raise InvalidNumberError, number
65-
end if options[:raise]
62+
parse_float(number, true) if options[:raise]
6663

6764
number = number.to_s.strip
68-
options = options.symbolize_keys
6965
area_code = options[:area_code]
7066
delimiter = options[:delimiter] || "-"
7167
extension = options[:extension]
@@ -75,7 +71,7 @@ def number_to_phone(number, options = {})
7571
number.gsub!(/(\d{1,3})(\d{3})(\d{4}$)/,"(\\1) \\2#{delimiter}\\3")
7672
else
7773
number.gsub!(/(\d{0,3})(\d{3})(\d{4})$/,"\\1#{delimiter}\\2#{delimiter}\\3")
78-
number.slice!(0, 1) if number.starts_with?(delimiter) && !delimiter.blank?
74+
number.slice!(0, 1) if number.start_with?(delimiter) && !delimiter.blank?
7975
end
8076

8177
str = []
@@ -122,8 +118,7 @@ def number_to_phone(number, options = {})
122118
# # => 1234567890,50 £
123119
def number_to_currency(number, options = {})
124120
return unless number
125-
126-
options.symbolize_keys!
121+
options = options.symbolize_keys
127122

128123
currency = translations_for('currency', options[:locale])
129124
currency[:negative_format] ||= "-" + currency[:format] if currency[:format]
@@ -185,12 +180,10 @@ def number_to_currency(number, options = {})
185180
# number_to_percentage("98a", :raise => true) # => InvalidNumberError
186181
def number_to_percentage(number, options = {})
187182
return unless number
183+
options = options.symbolize_keys
188184

189-
options.symbolize_keys!
190-
191-
defaults = defaults_translations(options[:locale]).merge(translations_for('percentage', options[:locale]))
192-
193-
options = options.reverse_merge(defaults)
185+
defaults = format_translations('percentage', options[:locale])
186+
options = defaults.merge!(options)
194187

195188
format = options[:format] || "%n%"
196189

@@ -201,7 +194,8 @@ def number_to_percentage(number, options = {})
201194
if options[:raise]
202195
raise
203196
else
204-
e.number.to_s.html_safe? ? format.gsub(/%n/, e.number).html_safe : format.gsub(/%n/, e.number)
197+
formatted_number = format.gsub(/%n/, e.number)
198+
e.number.to_s.html_safe? ? formatted_number.html_safe : formatted_number
205199
end
206200
end
207201
end
@@ -231,13 +225,11 @@ def number_to_percentage(number, options = {})
231225
#
232226
# number_with_delimiter("112a", :raise => true) # => raise InvalidNumberError
233227
def number_with_delimiter(number, options = {})
234-
options.symbolize_keys!
228+
options = options.symbolize_keys
235229

236-
parse_float_number(number, options[:raise]) do
237-
return number
238-
end
230+
parse_float(number, options[:raise]) or return number
239231

240-
options = options.reverse_merge(defaults_translations(options[:locale]))
232+
options = defaults_translations(options[:locale]).merge(options)
241233

242234
parts = number.to_s.to_str.split('.')
243235
parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{options[:delimiter]}")
@@ -277,15 +269,13 @@ def number_with_delimiter(number, options = {})
277269
# number_with_precision(1111.2345, :precision => 2, :separator => ',', :delimiter => '.')
278270
# # => 1.111,23
279271
def number_with_precision(number, options = {})
280-
options.symbolize_keys!
272+
options = options.symbolize_keys
281273

282-
number = parse_float_number(number, options[:raise]) do
283-
return number
284-
end
274+
number = (parse_float(number, options[:raise]) or return number)
285275

286-
defaults = defaults_translations(options[:locale]).merge(translations_for('precision', options[:locale]))
276+
defaults = format_translations('precision', options[:locale])
277+
options = defaults.merge!(options)
287278

288-
options = options.reverse_merge(defaults) # Allow the user to unset default values: Eg.: :significant => false
289279
precision = options.delete :precision
290280
significant = options.delete :significant
291281
strip_insignificant_zeros = options.delete :strip_insignificant_zeros
@@ -346,15 +336,13 @@ def number_with_precision(number, options = {})
346336
# number_to_human_size(1234567890123, :precision => 5) # => "1.1229 TB"
347337
# number_to_human_size(524288000, :precision => 5) # => "500 MB"
348338
def number_to_human_size(number, options = {})
349-
options.symbolize_keys!
339+
options = options.symbolize_keys
350340

351-
number = parse_float_number(number, options[:raise]) do
352-
return number
353-
end
341+
number = (parse_float(number, options[:raise]) or return number)
354342

355-
defaults = defaults_translations(options[:locale]).merge(translations_for('human', options[:locale]))
343+
defaults = format_translations('human', options[:locale])
344+
options = defaults.merge!(options)
356345

357-
options = options.reverse_merge(defaults)
358346
#for backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files
359347
options[:strip_insignificant_zeros] = true if not options.key?(:strip_insignificant_zeros)
360348

@@ -458,15 +446,13 @@ def number_to_human_size(number, options = {})
458446
# number_to_human(0.34, :units => :distance) # => "34 centimeters"
459447
#
460448
def number_to_human(number, options = {})
461-
options.symbolize_keys!
449+
options = options.symbolize_keys
462450

463-
number = parse_float_number(number, options[:raise]) do
464-
return number
465-
end
451+
number = (parse_float(number, options[:raise]) or return number)
466452

467-
defaults = defaults_translations(options[:locale]).merge(translations_for('human', options[:locale]))
453+
defaults = format_translations('human', options[:locale])
454+
options = defaults.merge!(options)
468455

469-
options = options.reverse_merge(defaults)
470456
#for backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files
471457
options[:strip_insignificant_zeros] = true if not options.key?(:strip_insignificant_zeros)
472458

@@ -504,6 +490,10 @@ def number_to_human(number, options = {})
504490

505491
private
506492

493+
def format_translations(namespace, locale)
494+
defaults_translations(locale).merge(translations_for(namespace, locale))
495+
end
496+
507497
def defaults_translations(locale)
508498
I18n.translate(:'number.format', :locale => locale, :default => {})
509499
end
@@ -512,14 +502,10 @@ def translations_for(namespace, locale)
512502
I18n.translate(:"number.#{namespace}.format", :locale => locale, :default => {})
513503
end
514504

515-
def parse_float_number(number, raise_error)
505+
def parse_float(number, raise_error)
516506
Float(number)
517507
rescue ArgumentError, TypeError
518-
if raise_error
519-
raise InvalidNumberError, number
520-
else
521-
yield
522-
end
508+
raise InvalidNumberError, number if raise_error
523509
end
524510
end
525511
end

actionpack/test/template/number_helper_test.rb

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,31 @@ def test_number_helpers_should_return_nil_when_given_nil
268268
assert_nil number_to_human(nil)
269269
end
270270

271+
def test_number_helpers_do_not_mutate_options_hash
272+
options = { 'raise' => true }
273+
274+
number_to_phone(1, options)
275+
assert_equal({ 'raise' => true }, options)
276+
277+
number_to_currency(1, options)
278+
assert_equal({ 'raise' => true }, options)
279+
280+
number_to_percentage(1, options)
281+
assert_equal({ 'raise' => true }, options)
282+
283+
number_with_delimiter(1, options)
284+
assert_equal({ 'raise' => true }, options)
285+
286+
number_with_precision(1, options)
287+
assert_equal({ 'raise' => true }, options)
288+
289+
number_to_human_size(1, options)
290+
assert_equal({ 'raise' => true }, options)
291+
292+
number_to_human(1, options)
293+
assert_equal({ 'raise' => true }, options)
294+
end
295+
271296
def test_number_helpers_should_return_non_numeric_param_unchanged
272297
assert_equal("+1-x x 123", number_to_phone("x", :country_code => 1, :extension => 123))
273298
assert_equal("x", number_to_phone("x"))

0 commit comments

Comments
 (0)