module ActionView::Helpers::NumberHelper

def delegate_number_helper_method(method, number, options)

def delegate_number_helper_method(method, number, options)
  return unless number
  options = escape_unsafe_options(options.symbolize_keys)
  wrap_with_output_safety_handling(number, options.delete(:raise)) {
    ActiveSupport::NumberHelper.public_send(method, number, options)
  }
end

def escape_units(units)

def escape_units(units)
  units.transform_values do |v|
    ERB::Util.html_escape(v)
  end
end

def escape_unsafe_options(options)

def escape_unsafe_options(options)
  options[:format]          = ERB::Util.html_escape(options[:format]) if options[:format]
  options[:negative_format] = ERB::Util.html_escape(options[:negative_format]) if options[:negative_format]
  options[:separator]       = ERB::Util.html_escape(options[:separator]) if options[:separator]
  options[:delimiter]       = ERB::Util.html_escape(options[:delimiter]) if options[:delimiter]
  options[:unit]            = ERB::Util.html_escape(options[:unit]) if options[:unit] && !options[:unit].html_safe?
  options[:units]           = escape_units(options[:units]) if options[:units] && Hash === options[:units]
  options
end

def number_to_currency(number, options = {})


number_to_currency("12x34", raise: true) # => InvalidNumberError
number_to_currency("12x34") # => "$12x34"

InvalidNumberError to be raised if +number+ is not a valid number:
Additionally, supports a +:raise+ option that will cause

Delegates to ActiveSupport::NumberHelper#number_to_currency.
def number_to_currency(number, options = {})
  delegate_number_helper_method(:number_to_currency, number, options)
end

def number_to_human(number, options = {})


number_to_human("12x34", raise: true) # => InvalidNumberError
number_to_human("12x34") # => "12x34"

InvalidNumberError to be raised if +number+ is not a valid number:
Additionally, supports a +:raise+ option that will cause

Delegates to ActiveSupport::NumberHelper#number_to_human.
def number_to_human(number, options = {})
  delegate_number_helper_method(:number_to_human, number, options)
end

def number_to_human_size(number, options = {})


number_to_human_size("12x34", raise: true) # => InvalidNumberError
number_to_human_size("12x34") # => "12x34"

InvalidNumberError to be raised if +number+ is not a valid number:
Additionally, supports a +:raise+ option that will cause

Delegates to ActiveSupport::NumberHelper#number_to_human_size.
def number_to_human_size(number, options = {})
  delegate_number_helper_method(:number_to_human_size, number, options)
end

def number_to_percentage(number, options = {})


number_to_percentage("99x", raise: true) # => InvalidNumberError
number_to_percentage("99x") # => "99x%"

InvalidNumberError to be raised if +number+ is not a valid number:
Additionally, supports a +:raise+ option that will cause

Delegates to ActiveSupport::NumberHelper#number_to_percentage.
def number_to_percentage(number, options = {})
  delegate_number_helper_method(:number_to_percentage, number, options)
end

def number_to_phone(number, options = {})


number_to_phone("12x34", raise: true) # => InvalidNumberError
number_to_phone("12x34") # => "12x34"

InvalidNumberError to be raised if +number+ is not a valid number:
Additionally, supports a +:raise+ option that will cause

Delegates to ActiveSupport::NumberHelper#number_to_phone.
def number_to_phone(number, options = {})
  return unless number
  options = options.symbolize_keys
  parse_float(number, true) if options.delete(:raise)
  ERB::Util.html_escape(ActiveSupport::NumberHelper.number_to_phone(number, options))
end

def number_with_delimiter(number, options = {})


number_with_delimiter("12x34", raise: true) # => InvalidNumberError
number_with_delimiter("12x34") # => "12x34"

InvalidNumberError to be raised if +number+ is not a valid number:
Additionally, supports a +:raise+ option that will cause

Delegates to ActiveSupport::NumberHelper#number_to_delimited.
def number_with_delimiter(number, options = {})
  delegate_number_helper_method(:number_to_delimited, number, options)
end

def number_with_precision(number, options = {})


number_with_precision("12x34", raise: true) # => InvalidNumberError
number_with_precision("12x34") # => "12x34"

InvalidNumberError to be raised if +number+ is not a valid number:
Additionally, supports a +:raise+ option that will cause

Delegates to ActiveSupport::NumberHelper#number_to_rounded.
def number_with_precision(number, options = {})
  delegate_number_helper_method(:number_to_rounded, number, options)
end

def parse_float(number, raise_error)

def parse_float(number, raise_error)
  result = Float(number, exception: false)
  raise InvalidNumberError, number if result.nil? && raise_error
  result
end

def valid_float?(number)

def valid_float?(number)
  !parse_float(number, false).nil?
end

def wrap_with_output_safety_handling(number, raise_on_invalid, &block)

def wrap_with_output_safety_handling(number, raise_on_invalid, &block)
  valid_float = valid_float?(number)
  raise InvalidNumberError, number if raise_on_invalid && !valid_float
  formatted_number = yield
  if valid_float || number.html_safe?
    formatted_number.html_safe
  else
    formatted_number
  end
end