Module: Useful::RubyExtensions::Numeric

Included in:
Numeric
Defined in:
lib/useful/ruby_extensions/numeric.rb

Defined Under Namespace

Modules: ClassMethods

Constant Summary collapse

LOCALES =
{
  :en => {
    :currency => {:format => "%u%n", :unit=> '$'},
    :storage => {:format => "%n %u", :delimiter => ''},
    :format => {:delimiter => ',', :separator => '.'},
    :defaults => {:precision => 2}
  }
}.freeze
STORAGE_UNITS =
['Bytes', 'KB', 'MB', 'GB', 'TB'].freeze

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(klass) ⇒ Object



21
22
23
# File 'lib/useful/ruby_extensions/numeric.rb', line 21

def self.included(klass)
  klass.extend(ClassMethods) if klass.kind_of?(Class)
end

Instance Method Details

#to_currency(opts = {}) ⇒ Object

Formats a number into a currency string (e.g., $13.65). You can customize the format in the options hash.

> taken and inspired from ActionView::Helpers::NumberHelper (api.rubyonrails.org/)

Options

  • :precision - Sets the level of precision (defaults to 2).

  • :unit - Sets the denomination of the currency (defaults to “$”).

  • :separator - Sets the separator between the units (defaults to “.”).

  • :delimiter - Sets the thousands delimiter (defaults to “,”).

  • :format - Sets the format of the output string (defaults to “%u%n”). The field types are:

    %u  The currency unit
    %n  The number
    

Examples (:locale => :en)

1234567890.50.to_currency                    # => $1,234,567,890.50
1234567890.506.to_currency                   # => $1,234,567,890.51
1234567890.506.to_currency(:precision => 3)  # => $1,234,567,890.506

1234567890.50.to_currency(:unit => "£", :separator => ",", :delimiter => "")
# => £1234567890,50
1234567890.50.to_currency(:unit => "£", :separator => ",", :delimiter => "", :format => "%n %u")
# => 1234567890,50 £


148
149
150
151
152
153
154
155
156
# File 'lib/useful/ruby_extensions/numeric.rb', line 148

def to_currency(opts = {})
  return opts[:zero_display] if opts[:zero_display] && self.to_f == 0.to_f
  opts.symbolize_keys!
  opts[:locale] ||= :en
  locale = LOCALES[opts.delete(:locale)]
  opts = locale[:defaults].merge(locale[:format]).merge(locale[:currency]).merge(opts) unless locale.nil?

  opts[:format].gsub(/%n/, self.with_precision(opts.only(:precision, :delimiter, :separator)).to_s).gsub(/%u/, opts[:unit].to_s) #rescue self
end

#to_parityObject

Returns the string representation of the number’s parity.

Examples

1.to_parity                                          # => "odd"
2.to_parity                                          # => "even"


204
205
206
# File 'lib/useful/ruby_extensions/numeric.rb', line 204

def to_parity
  self.to_i.even? ? 'even' : 'odd'
end

#to_percentage(opts = {}) ⇒ Object

Formats a number as a percentage string (e.g., 65%). You can customize the format in the options hash.

Options

  • :precision - Sets the level of precision (defaults to 2).

  • :separator - Sets the separator between the units (defaults to “.”).

  • :delimiter - Sets the thousands delimiter (defaults to “”).

Examples

100.to_percentage                                        # => 100.00%
100.to_percentage(:precision => 0)                       # => 100%
1000.to_percentage(:delimiter => '.', :separator => ',') # => 1.000,00%
302.24398923423.to_percentage(:precision => 5)           # => 302.24399%


117
118
119
120
121
122
123
124
# File 'lib/useful/ruby_extensions/numeric.rb', line 117

def to_percentage(opts = {})
  opts.symbolize_keys!
  opts[:locale] ||= :en
  locale = LOCALES[opts.delete(:locale)]
  opts = locale[:defaults].merge(locale[:format]).merge(opts) unless locale.nil?

  "#{self.with_precision(opts.only(:precision, :separator, :delimiter))}%" rescue self
end

#to_phone(opts = {}) ⇒ Object

Formats a number into a US phone number (e.g., (555) 123-9876). You can customize the format in the options hash.

Options

  • :area_code - Adds parentheses around the area code.

  • :delimiter - Specifies the delimiter to use (defaults to “-”).

  • :extension - Specifies an extension to add to the end of the generated number.

  • :country_code - Sets the country code for the phone number.

Examples

5551234.to_phone                                           # => 555-1234
1235551234.to_phone                                        # => 123-555-1234
1235551234.to_phone(:area_code => true)                    # => (123) 555-1234
1235551234.to_phone(:delimiter => " ")                     # => 123 555 1234
1235551234.to_phone(:area_code => true, :extension => 555) # => (123) 555-1234 x 555
1235551234.to_phone(:country_code => 1)                    # => +1-123-555-1234
1235551234.to_phone({ :country_code => 1,
  :extension => 1343, :delimiter => "." })                 # => +1.123.555.1234 x 1343


232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# File 'lib/useful/ruby_extensions/numeric.rb', line 232

def to_phone(opts={})
  number = self.to_s.strip
  opts.symbolize_keys!
  opts[:delimiter] ||= '-'
  opts[:extension] = opts[:extension].to_s.strip unless opts[:extension].nil?

  begin
    str = ""
    str << "+#{opts[:country_code]}#{opts[:delimiter]}" unless opts[:country_code].blank?
    str << if opts[:area_code]
      number.gsub!(/([0-9]{1,3})([0-9]{3})([0-9]{4}$)/,"(\\1) \\2#{opts[:delimiter]}\\3")
    else
      number.gsub!(/([0-9]{0,3})([0-9]{3})([0-9]{4})$/,"\\1#{opts[:delimiter]}\\2#{opts[:delimiter]}\\3")
      number.starts_with?('-') ? number.slice!(1..-1) : number
    end
    str << " x #{opts[:extension]}" unless opts[:extension].blank?
    str
  rescue
    number
  end
end

#to_precision(precision = 2) ⇒ Object

Converts a number with the specified level of :precision (e.g., 112.32 has a precision of 2).

> taken and inspired from ActionView::Helpers::NumberHelper (api.rubyonrails.org/)



71
72
73
74
75
# File 'lib/useful/ruby_extensions/numeric.rb', line 71

def to_precision(precision = 2)
  rounded_number = (Float(self) * (10 ** precision)).round
  rounded_number = rounded_number.to_f if precision > 0
  (rounded_number / 10 ** precision) rescue self
end

#to_storage_size(opts = {}) ⇒ Object

Formats the bytes in size into a more understandable representation (e.g., giving it 1500 yields 1.5 KB). This method is useful for reporting file sizes to users. This method returns nil if size cannot be converted into a number. You can customize the format in the options hash.

Options

  • :precision - Sets the level of precision (defaults to 2).

  • :separator - Sets the separator between the units (defaults to “.”).

  • :delimiter - Sets the thousands delimiter (defaults to “”).

Examples

123.to_storage_size                                          # => 123 Bytes
1234.to_storage_size                                         # => 1.2 KB
12345.to_storage_size                                        # => 12.1 KB
1234567.to_storage_size                                      # => 1.2 MB
1234567890.to_storage_size                                   # => 1.1 GB
1234567890123.to_storage_size                                # => 1.1 TB
1234567.to_storage_size(:precision => 2)                     # => 1.18 MB
483989.to_storage_size(:precision => 0)                      # => 473 KB
1234567.to_storage_size(:precision => 2, :separator => ',')  # => 1,18 MB


179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/useful/ruby_extensions/numeric.rb', line 179

def to_storage_size(opts = {})
  return nil if self.nil?
  opts.symbolize_keys!
  opt_precision = opts[:precision]
  opts[:locale] ||= :en
  locale = LOCALES[opts.delete(:locale)]
  opts = locale[:defaults].merge(locale[:format]).merge(locale[:storage]).merge(opts) unless locale.nil?
  opts[:format] ||= "%n %u"
  opts[:precision] = 0 unless opt_precision

  value = self.to_f
  unit = ''
  STORAGE_UNITS.each do |storage_unit|
    unit = storage_unit.to_s
    return opts[:format].gsub(/%n/, value.with_precision(opts.only(:precision, :delimiter, :separator)).to_s).gsub(/%u/, unit.to_s) if value < 1024 || storage_unit == STORAGE_UNITS.last
    opts[:precision] = 2 unless opt_precision
    value /= 1024.0
  end
end

#with_delimiter(opts = {}) ⇒ Object

Formats a number with grouped thousands using delimiter (e.g., 12,324). You can customize the format in the options hash.

> taken and inspired from ActionView::Helpers::NumberHelper (api.rubyonrails.org/)

Options

  • :delimiter - Sets the thousands delimiter (defaults to “,”).

  • :separator - Sets the separator between the units (defaults to “.”).

Examples

12345678.with_delimiter                        # => 12,345,678
12345678.05.with_delimiter                     # => 12,345,678.05
12345678.with_delimiter(:delimiter => ".")     # => 12.345.678
12345678.with_delimiter(:seperator => ",")     # => 12,345,678
98765432.98.with_delimiter(:delimiter => " ", :separator => ",")
# => 98 765 432,98


51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/useful/ruby_extensions/numeric.rb', line 51

def with_delimiter(opts = {})
  number = self.to_s.strip
  opts.symbolize_keys!
  opts[:locale] ||= :en
  locale = LOCALES[opts.delete(:locale)]
  opts = locale[:format].merge(opts) unless locale.nil?
  opts[:delimiter] ||= ','
  opts[:separator] ||= '.'

  begin
    parts = number.to_s.split('.')
    parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{opts[:delimiter]}")
    parts.join(opts[:separator])
  rescue
    number
  end
end

#with_precision(opts = {}) ⇒ Object

Formats a number with the specified level of :precision (e.g., 112.32 has a precision of 2). You can customize the format in the options hash.

> taken and inspired from ActionView::Helpers::NumberHelper (api.rubyonrails.org/)

Options

  • :precision - Sets the level of precision (defaults to 3).

  • :separator - Sets the separator between the units (defaults to “.”).

  • :delimiter - Sets the thousands delimiter (defaults to “”).

Examples (:locale => :en)

111.2345.with_precision                    # => 111.235
111.2345.with_precision(:precision => 2)   # => 111.23
13.with_precision(:precision => 5)         # => 13.00000
389.32314.with_precision(:precision => 0)  # => 389
1111.2345.with_precision(:precision => 2, :separator => ',', :delimiter => '.')
# => 1,111.23


93
94
95
96
97
98
99
100
101
102
# File 'lib/useful/ruby_extensions/numeric.rb', line 93

def with_precision(opts = {})
  opts.symbolize_keys!
  opts[:locale] ||= :en
  opts[:delimiter] ||= ''
  locale = LOCALES[opts.delete(:locale)]
  opts = locale[:defaults].merge(locale[:format]).merge(opts) unless locale.nil?
  opts[:precision] ||= 2
  
  self.class.pad_precision(self.to_precision(opts[:precision]).with_delimiter(opts.only(:separator, :delimiter)), opts) rescue self
end