Class Numeric
In: lib/extensions/numeric.rb
Parent: Object

Methods

format_s  

Constants

FORMAT_STYLES = { :us => { :sep => ',', :dec => '.', :id => :us }, :usd => { :style => :us, :currency => { :id => "$", :pos => :before }, :id => :usd }, :eu => { :sep => ' ', :dec => ',', :id => :us }, :euro => { :style => :eu, :currency => { :id => "€", :pos => :before }, :id => :euro }, :percent => { :style => :us, :currency => { :id => "%%", :pos => :after }, :id => :percent }   Provides the base formatting styles for format_s. See format_s for more details. Two keys provided that are not supported in the format_s arguments are:
:style:Allows a style to inherit from other styles. Styles will be applied in oldest-first order in the event of multiple inheritance layers.
:id:This must be provided on any default style created or provided so as to provide a stop marker so that recursive styles do not result in an infinite loop.

This is an implementation detail, not important for users of the class.

Public Instance methods

Format a number as a string, using US or European conventions, and allowing for the accounting format of representing negative numbers. Optionally, currency formatting options can be provided.

For example:

  x = -10259.8937
  x.format_s                         # => "-10,259.8937"
  x.format_s(:us)                    # => "-10,259.8937"
  x.format_s(:usd)                   # => "$-10,259.8937"
  x.format_s(:eu)                    # => "-10 259,8937"
  x.format_s(:euro)                  # => "€-10 259,8937"
  x.format_s(:us, :acct => true)     # => "(10,259.8937)"
  x.format_s(:eu, :acct => true)     # => "(10 259,8937)"
  x.format_s(:usd, :acct => true)    # => "$(10,259.8937)"
  x.format_s(:euro, :acct => true)   # => "€(10 259,8937)"
  x.format_s(:percent)               # => "-10,259.8937%"

You may configure several aspects of the formatting by providing keyword arguments after the country and accounting arguments. One example of that is the :acct keyword. A more insane example is:

  x = -10259.8937
  x.format_s(:us,
             :sep => ' ', :dec => ',',
             :neg => '<%s>', :size => 2,
             :fd => true)                    # -> "<1 02 59,89 37>"

The keyword parameters are as follows:

:acct:If true, then use accounting style for negative numbers. This overrides any value for :neg.
:sep:Default "," for US, " " for Euro. Separate the number groups from each other with this string.
:dec:Default "." for US, "," for Euro. Separate the number‘s integer part from the fractional part with this string.
:neg:Default "-%s". The format string used to represent negative numbers. If :acct is true, this is set to "(%s)".
:size:The number of digits per group. Defaults to thousands (3).
:fd:Indicates whether the decimal portion of the number should be formatted the same way as the integer portion of the number. ("fd" == "format decimal".) Defaults to false.
:currency:This is an optional hash with two keys, :id and :pos. :id is the string value of the currency (e.g., "$", "€", "USD&nbsp;"); :pos is either :before or :after, referring to the position of the currency indicator. The default :pos is :before.

[Source]

# File lib/extensions/numeric.rb, line 171
    def format_s(style = :us, configs={})
      style = FORMAT_STYLES[style].dup # Adopt US style by default.

        # Deal with recursive styles.
      if style[:style]
        styles = []
        s = style
        while s[:style]
          s = FORMAT_STYLES[s[:style]].dup
          styles << s
          break if s[:style] = s[:id]
        end
        styles.reverse_each { |s| style.merge!(s)  }
      end
        # Merge the configured style.
      style.merge!(configs)

      sm = style[:sep] || ','
      dp = style[:dec] || '.'
      if style[:acct]
        fmt = '(%s)'
      else
        fmt = style[:neg] || '-%s'
      end
      sz = style[:size] || 3
      format_decimal = style[:fd]
      ng = (self < 0)
      fmt = "%s" if not ng

      dec, frac = self.abs.to_s.split(/\./)

      dec.reverse!
      dec.gsub!(/\d{#{sz}}/) { |m| "#{m}#{sm}" }
      dec.gsub!(/#{sm}$/, '')
      dec.reverse!

      if format_decimal and not frac.nil?
        frac.gsub!(/\d{#{sz}}/) { |m| "#{m}#{sm}" }
        frac.gsub!(/#{sm}$/, '')
      end

      if frac.nil?
        val = dec
      else
        val = "#{dec}#{dp}#{frac}"
      end

      if style[:currency]
        if style[:currency][:pos].nil? or style[:currency][:pos] == :before
          fmt = "#{style[:currency][:id]}#{fmt}"
        elsif style[:currency][:pos] == :after
          fmt = "#{fmt}#{style[:currency][:id]}"
        end
      end

      fmt % val
    end

[Validate]