Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 504 lines (449 sloc) 25.458 kb
31319b4 Joshua Peek NumberHelper depends on big decimal extensions
josh authored
1 require 'active_support/core_ext/big_decimal/conversions'
b2d6fda Jeremy Kemper Fix tests on 1.9
jeremy authored
2 require 'active_support/core_ext/float/rounding'
3
aa09c77 David Heinemeier Hansson Added NumberHelper for common string representations like phone number, ...
dhh authored
4 module ActionView
1c71a5d David Heinemeier Hansson Upgraded NumberHelper with number_to_phone support international formats...
dhh authored
5 module Helpers #:nodoc:
a4090bc Bernardo de Pádua NumberHelper methods should now return html_safe strings (when the input...
bernardo authored
6
9ffb632 Enhance documentation coverage for fragment caching. Closes #7315 [bscof...
Marcel Molina authored
7 # Provides methods for converting numbers into formatted strings.
1c71a5d David Heinemeier Hansson Upgraded NumberHelper with number_to_phone support international formats...
dhh authored
8 # Methods are provided for phone numbers, currency, percentage,
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
9 # precision, positional notation, file size and pretty printing.
10 #
11 # Most methods expect a +number+ argument, and will return it
12 # unchanged if can't be converted into a valid number.
aa09c77 David Heinemeier Hansson Added NumberHelper for common string representations like phone number, ...
dhh authored
13 module NumberHelper
a4090bc Bernardo de Pádua NumberHelper methods should now return html_safe strings (when the input...
bernardo authored
14
15 # Raised when argument +number+ param given to the helpers is invalid and
16 # the option :raise is set to +true+.
17 class InvalidNumberError < StandardError
18 attr_accessor :number
19 def initialize(number)
20 @number = number
21 end
22 end
23
b00e6a9 David Heinemeier Hansson Massive documentation update for all helpers (closes #8223, #8177, #8175...
dhh authored
24 # Formats a +number+ into a US phone number (e.g., (555) 123-9876). You can customize the format
1c71a5d David Heinemeier Hansson Upgraded NumberHelper with number_to_phone support international formats...
dhh authored
25 # in the +options+ hash.
b00e6a9 David Heinemeier Hansson Massive documentation update for all helpers (closes #8223, #8177, #8175...
dhh authored
26 #
27 # ==== Options
1c71a5d David Heinemeier Hansson Upgraded NumberHelper with number_to_phone support international formats...
dhh authored
28 # * <tt>:area_code</tt> - Adds parentheses around the area code.
b00e6a9 David Heinemeier Hansson Massive documentation update for all helpers (closes #8223, #8177, #8175...
dhh authored
29 # * <tt>:delimiter</tt> - Specifies the delimiter to use (defaults to "-").
1c71a5d David Heinemeier Hansson Upgraded NumberHelper with number_to_phone support international formats...
dhh authored
30 # * <tt>:extension</tt> - Specifies an extension to add to the end of the
b00e6a9 David Heinemeier Hansson Massive documentation update for all helpers (closes #8223, #8177, #8175...
dhh authored
31 # generated number.
1c71a5d David Heinemeier Hansson Upgraded NumberHelper with number_to_phone support international formats...
dhh authored
32 # * <tt>:country_code</tt> - Sets the country code for the phone number.
33 #
b00e6a9 David Heinemeier Hansson Massive documentation update for all helpers (closes #8223, #8177, #8175...
dhh authored
34 # ==== Examples
1ab2ff5 Ryan Heath Fixed number_to_phone to work with 7 digit numbers [#2176 state:resolved...
rpheath authored
35 # number_to_phone(5551234) # => 555-1234
b00e6a9 David Heinemeier Hansson Massive documentation update for all helpers (closes #8223, #8177, #8175...
dhh authored
36 # number_to_phone(1235551234) # => 123-555-1234
37 # number_to_phone(1235551234, :area_code => true) # => (123) 555-1234
38 # number_to_phone(1235551234, :delimiter => " ") # => 123 555 1234
39 # number_to_phone(1235551234, :area_code => true, :extension => 555) # => (123) 555-1234 x 555
40 # number_to_phone(1235551234, :country_code => 1) # => +1-123-555-1234
41 #
2af36bb David Heinemeier Hansson Fix typos (closes #10378)
dhh authored
42 # number_to_phone(1235551234, :country_code => 1, :extension => 1343, :delimiter => ".")
0f43de6 Clemens Kofler Refactored NumberHelper API to accept arguments as an options hash [#666...
clemens authored
43 # => +1.123.555.1234 x 1343
aa09c77 David Heinemeier Hansson Added NumberHelper for common string representations like phone number, ...
dhh authored
44 def number_to_phone(number, options = {})
8da026c Xavier Shay Remove some of the blank rescues from number helper. This makes the code...
xaviershay authored
45 return nil if number.nil?
46
a4090bc Bernardo de Pádua NumberHelper methods should now return html_safe strings (when the input...
bernardo authored
47 begin
48 Float(number)
49 is_number_html_safe = true
50 rescue ArgumentError, TypeError
51 if options[:raise]
52 raise InvalidNumberError, number
53 else
54 is_number_html_safe = number.to_s.html_safe?
55 end
56 end
57
8da026c Xavier Shay Remove some of the blank rescues from number helper. This makes the code...
xaviershay authored
58 number = number.to_s.strip
fea7771 Clemens Kofler Updated NumberHelper: Full i18n support (except number_to_phone), consol...
clemens authored
59 options = options.symbolize_keys
60 area_code = options[:area_code] || nil
61 delimiter = options[:delimiter] || "-"
62 extension = options[:extension].to_s.strip || nil
63 country_code = options[:country_code] || nil
1c71a5d David Heinemeier Hansson Upgraded NumberHelper with number_to_phone support international formats...
dhh authored
64
8da026c Xavier Shay Remove some of the blank rescues from number helper. This makes the code...
xaviershay authored
65 str = ""
66 str << "+#{country_code}#{delimiter}" unless country_code.blank?
67 str << if area_code
68 number.gsub!(/([0-9]{1,3})([0-9]{3})([0-9]{4}$)/,"(\\1) \\2#{delimiter}\\3")
69 else
70 number.gsub!(/([0-9]{0,3})([0-9]{3})([0-9]{4})$/,"\\1#{delimiter}\\2#{delimiter}\\3")
71 number.starts_with?('-') ? number.slice!(1..-1) : number
aa09c77 David Heinemeier Hansson Added NumberHelper for common string representations like phone number, ...
dhh authored
72 end
8da026c Xavier Shay Remove some of the blank rescues from number helper. This makes the code...
xaviershay authored
73 str << " x #{extension}" unless extension.blank?
a4090bc Bernardo de Pádua NumberHelper methods should now return html_safe strings (when the input...
bernardo authored
74 is_number_html_safe ? str.html_safe : str
aa09c77 David Heinemeier Hansson Added NumberHelper for common string representations like phone number, ...
dhh authored
75 end
76
b00e6a9 David Heinemeier Hansson Massive documentation update for all helpers (closes #8223, #8177, #8175...
dhh authored
77 # Formats a +number+ into a currency string (e.g., $13.65). You can customize the format
1c71a5d David Heinemeier Hansson Upgraded NumberHelper with number_to_phone support international formats...
dhh authored
78 # in the +options+ hash.
79 #
b00e6a9 David Heinemeier Hansson Massive documentation update for all helpers (closes #8223, #8177, #8175...
dhh authored
80 # ==== Options
81 # * <tt>:precision</tt> - Sets the level of precision (defaults to 2).
fea7771 Clemens Kofler Updated NumberHelper: Full i18n support (except number_to_phone), consol...
clemens authored
82 # * <tt>:unit</tt> - Sets the denomination of the currency (defaults to "$").
b00e6a9 David Heinemeier Hansson Massive documentation update for all helpers (closes #8223, #8177, #8175...
dhh authored
83 # * <tt>:separator</tt> - Sets the separator between the units (defaults to ".").
84 # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to ",").
fea7771 Clemens Kofler Updated NumberHelper: Full i18n support (except number_to_phone), consol...
clemens authored
85 # * <tt>:format</tt> - Sets the format of the output string (defaults to "%u%n"). The field types are:
3c0fd44 David Heinemeier Hansson Added :format option to NumberHelper#number_to_currency to enable better...
dhh authored
86 #
87 # %u The currency unit
88 # %n The number
b00e6a9 David Heinemeier Hansson Massive documentation update for all helpers (closes #8223, #8177, #8175...
dhh authored
89 #
90 # ==== Examples
91 # number_to_currency(1234567890.50) # => $1,234,567,890.50
92 # number_to_currency(1234567890.506) # => $1,234,567,890.51
93 # number_to_currency(1234567890.506, :precision => 3) # => $1,234,567,890.506
94 #
2823a56 Jeremy Kemper Deprecation: remove deprecated human_size helper alias. Use number_to_hu...
jeremy authored
95 # number_to_currency(1234567890.50, :unit => "&pound;", :separator => ",", :delimiter => "")
b00e6a9 David Heinemeier Hansson Massive documentation update for all helpers (closes #8223, #8177, #8175...
dhh authored
96 # # => &pound;1234567890,50
3c0fd44 David Heinemeier Hansson Added :format option to NumberHelper#number_to_currency to enable better...
dhh authored
97 # number_to_currency(1234567890.50, :unit => "&pound;", :separator => ",", :delimiter => "", :format => "%n %u")
98 # # => 1234567890,50 &pound;
aa09c77 David Heinemeier Hansson Added NumberHelper for common string representations like phone number, ...
dhh authored
99 def number_to_currency(number, options = {})
a4090bc Bernardo de Pádua NumberHelper methods should now return html_safe strings (when the input...
bernardo authored
100 return nil if number.nil?
101
fea7771 Clemens Kofler Updated NumberHelper: Full i18n support (except number_to_phone), consol...
clemens authored
102 options.symbolize_keys!
103
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
104 defaults = I18n.translate(:'number.format', :locale => options[:locale], :default => {})
105 currency = I18n.translate(:'number.currency.format', :locale => options[:locale], :default => {})
dc66469 Clemens Kofler Fixed i18n bulk translate issues in NumberHelper
clemens authored
106 defaults = defaults.merge(currency)
0f43de6 Clemens Kofler Refactored NumberHelper API to accept arguments as an options hash [#666...
clemens authored
107
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
108 options = options.reverse_merge(defaults)
0f43de6 Clemens Kofler Refactored NumberHelper API to accept arguments as an options hash [#666...
clemens authored
109
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
110 unit = options.delete(:unit)
111 format = options.delete(:format)
112
a4090bc Bernardo de Pádua NumberHelper methods should now return html_safe strings (when the input...
bernardo authored
113 begin
114 value = number_with_precision(number, options.merge(:raise => true))
8da026c Xavier Shay Remove some of the blank rescues from number helper. This makes the code...
xaviershay authored
115 format.gsub(/%n/, value).gsub(/%u/, unit).html_safe
a4090bc Bernardo de Pádua NumberHelper methods should now return html_safe strings (when the input...
bernardo authored
116 rescue InvalidNumberError => e
117 if options[:raise]
118 raise
119 else
120 formatted_number = format.gsub(/%n/, e.number).gsub(/%u/, unit)
121 e.number.to_s.html_safe? ? formatted_number.html_safe : formatted_number
122 end
aa09c77 David Heinemeier Hansson Added NumberHelper for common string representations like phone number, ...
dhh authored
123 end
a4090bc Bernardo de Pádua NumberHelper methods should now return html_safe strings (when the input...
bernardo authored
124
aa09c77 David Heinemeier Hansson Added NumberHelper for common string representations like phone number, ...
dhh authored
125 end
126
b00e6a9 David Heinemeier Hansson Massive documentation update for all helpers (closes #8223, #8177, #8175...
dhh authored
127 # Formats a +number+ as a percentage string (e.g., 65%). You can customize the
1c71a5d David Heinemeier Hansson Upgraded NumberHelper with number_to_phone support international formats...
dhh authored
128 # format in the +options+ hash.
129 #
b00e6a9 David Heinemeier Hansson Massive documentation update for all helpers (closes #8223, #8177, #8175...
dhh authored
130 # ==== Options
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
131 # * <tt>:precision</tt> - Sets the precision of the number (defaults to 3).
132 # * <tt>:significant</tt> - If +true+, precision will be the # of significant_digits. If +false+, the # of fractional digits (defaults to +false+)
133 # * <tt>:separator</tt> - Sets the separator between the fractional and integer digits (defaults to ".").
fea7771 Clemens Kofler Updated NumberHelper: Full i18n support (except number_to_phone), consol...
clemens authored
134 # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to "").
c53f77f José Valim Rename unsignificant to insignificant.
josevalim authored
135 # * <tt>:strip_insignificant_zeros</tt> - If +true+ removes insignificant zeros after the decimal separator (defaults to +false+)
b00e6a9 David Heinemeier Hansson Massive documentation update for all helpers (closes #8223, #8177, #8175...
dhh authored
136 #
137 # ==== Examples
fea7771 Clemens Kofler Updated NumberHelper: Full i18n support (except number_to_phone), consol...
clemens authored
138 # number_to_percentage(100) # => 100.000%
139 # number_to_percentage(100, :precision => 0) # => 100%
140 # number_to_percentage(1000, :delimiter => '.', :separator => ',') # => 1.000,000%
141 # number_to_percentage(302.24398923423, :precision => 5) # => 302.24399%
aa09c77 David Heinemeier Hansson Added NumberHelper for common string representations like phone number, ...
dhh authored
142 def number_to_percentage(number, options = {})
a4090bc Bernardo de Pádua NumberHelper methods should now return html_safe strings (when the input...
bernardo authored
143 return nil if number.nil?
144
fea7771 Clemens Kofler Updated NumberHelper: Full i18n support (except number_to_phone), consol...
clemens authored
145 options.symbolize_keys!
146
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
147 defaults = I18n.translate(:'number.format', :locale => options[:locale], :default => {})
148 percentage = I18n.translate(:'number.percentage.format', :locale => options[:locale], :default => {})
dc66469 Clemens Kofler Fixed i18n bulk translate issues in NumberHelper
clemens authored
149 defaults = defaults.merge(percentage)
fea7771 Clemens Kofler Updated NumberHelper: Full i18n support (except number_to_phone), consol...
clemens authored
150
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
151 options = options.reverse_merge(defaults)
2823a56 Jeremy Kemper Deprecation: remove deprecated human_size helper alias. Use number_to_hu...
jeremy authored
152
a4090bc Bernardo de Pádua NumberHelper methods should now return html_safe strings (when the input...
bernardo authored
153 begin
154 "#{number_with_precision(number, options.merge(:raise => true))}%".html_safe
155 rescue InvalidNumberError => e
156 if options[:raise]
157 raise
158 else
159 e.number.to_s.html_safe? ? "#{e.number}%".html_safe : "#{e.number}%"
160 end
161 end
aa09c77 David Heinemeier Hansson Added NumberHelper for common string representations like phone number, ...
dhh authored
162 end
163
0f43de6 Clemens Kofler Refactored NumberHelper API to accept arguments as an options hash [#666...
clemens authored
164 # Formats a +number+ with grouped thousands using +delimiter+ (e.g., 12,324). You can
165 # customize the format in the +options+ hash.
1c71a5d David Heinemeier Hansson Upgraded NumberHelper with number_to_phone support international formats...
dhh authored
166 #
b00e6a9 David Heinemeier Hansson Massive documentation update for all helpers (closes #8223, #8177, #8175...
dhh authored
167 # ==== Options
0f43de6 Clemens Kofler Refactored NumberHelper API to accept arguments as an options hash [#666...
clemens authored
168 # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to ",").
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
169 # * <tt>:separator</tt> - Sets the separator between the fractional and integer digits (defaults to ".").
b00e6a9 David Heinemeier Hansson Massive documentation update for all helpers (closes #8223, #8177, #8175...
dhh authored
170 #
171 # ==== Examples
0f43de6 Clemens Kofler Refactored NumberHelper API to accept arguments as an options hash [#666...
clemens authored
172 # number_with_delimiter(12345678) # => 12,345,678
173 # number_with_delimiter(12345678.05) # => 12,345,678.05
174 # number_with_delimiter(12345678, :delimiter => ".") # => 12.345.678
18eb80c Pratik Merge docrails
lifo authored
175 # number_with_delimiter(12345678, :separator => ",") # => 12,345,678
0f43de6 Clemens Kofler Refactored NumberHelper API to accept arguments as an options hash [#666...
clemens authored
176 # number_with_delimiter(98765432.98, :delimiter => " ", :separator => ",")
b00e6a9 David Heinemeier Hansson Massive documentation update for all helpers (closes #8223, #8177, #8175...
dhh authored
177 # # => 98 765 432,98
0f43de6 Clemens Kofler Refactored NumberHelper API to accept arguments as an options hash [#666...
clemens authored
178 #
179 # You can still use <tt>number_with_delimiter</tt> with the old API that accepts the
180 # +delimiter+ as its optional second and the +separator+ as its
181 # optional third parameter:
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
182 # number_with_delimiter(12345678, " ") # => 12 345 678
fea7771 Clemens Kofler Updated NumberHelper: Full i18n support (except number_to_phone), consol...
clemens authored
183 # number_with_delimiter(12345678.05, ".", ",") # => 12.345.678,05
0f43de6 Clemens Kofler Refactored NumberHelper API to accept arguments as an options hash [#666...
clemens authored
184 def number_with_delimiter(number, *args)
185 options = args.extract_options!
fea7771 Clemens Kofler Updated NumberHelper: Full i18n support (except number_to_phone), consol...
clemens authored
186 options.symbolize_keys!
187
a4090bc Bernardo de Pádua NumberHelper methods should now return html_safe strings (when the input...
bernardo authored
188 begin
189 Float(number)
190 rescue ArgumentError, TypeError
191 if options[:raise]
192 raise InvalidNumberError, number
193 else
194 return number
195 end
196 end
197
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
198 defaults = I18n.translate(:'number.format', :locale => options[:locale], :default => {})
fea7771 Clemens Kofler Updated NumberHelper: Full i18n support (except number_to_phone), consol...
clemens authored
199
0f43de6 Clemens Kofler Refactored NumberHelper API to accept arguments as an options hash [#666...
clemens authored
200 unless args.empty?
fea7771 Clemens Kofler Updated NumberHelper: Full i18n support (except number_to_phone), consol...
clemens authored
201 ActiveSupport::Deprecation.warn('number_with_delimiter takes an option hash ' +
202 'instead of separate delimiter and precision arguments.', caller)
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
203 options[:delimiter] ||= args[0] if args[0]
204 options[:separator] ||= args[1] if args[1]
0f43de6 Clemens Kofler Refactored NumberHelper API to accept arguments as an options hash [#666...
clemens authored
205 end
fea7771 Clemens Kofler Updated NumberHelper: Full i18n support (except number_to_phone), consol...
clemens authored
206
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
207 options = options.reverse_merge(defaults)
0f43de6 Clemens Kofler Refactored NumberHelper API to accept arguments as an options hash [#666...
clemens authored
208
8da026c Xavier Shay Remove some of the blank rescues from number helper. This makes the code...
xaviershay authored
209 parts = number.to_s.split('.')
a4090bc Bernardo de Pádua NumberHelper methods should now return html_safe strings (when the input...
bernardo authored
210 parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{options[:delimiter]}")
211 parts.join(options[:separator]).html_safe
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
212
4bdb25d David Heinemeier Hansson Update to the helper to abstract delimeting a number #1015
dhh authored
213 end
2823a56 Jeremy Kemper Deprecation: remove deprecated human_size helper alias. Use number_to_hu...
jeremy authored
214
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
215 # Formats a +number+ with the specified level of <tt>:precision</tt> (e.g., 112.32 has a precision
216 # of 2 if +:significant+ is +false+, and 5 if +:significant+ is +true+).
fea7771 Clemens Kofler Updated NumberHelper: Full i18n support (except number_to_phone), consol...
clemens authored
217 # You can customize the format in the +options+ hash.
218 #
219 # ==== Options
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
220 # * <tt>:precision</tt> - Sets the precision of the number (defaults to 3).
221 # * <tt>:significant</tt> - If +true+, precision will be the # of significant_digits. If +false+, the # of fractional digits (defaults to +false+)
222 # * <tt>:separator</tt> - Sets the separator between the fractional and integer digits (defaults to ".").
fea7771 Clemens Kofler Updated NumberHelper: Full i18n support (except number_to_phone), consol...
clemens authored
223 # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to "").
c53f77f José Valim Rename unsignificant to insignificant.
josevalim authored
224 # * <tt>:strip_insignificant_zeros</tt> - If +true+ removes insignificant zeros after the decimal separator (defaults to +false+)
1c71a5d David Heinemeier Hansson Upgraded NumberHelper with number_to_phone support international formats...
dhh authored
225 #
b00e6a9 David Heinemeier Hansson Massive documentation update for all helpers (closes #8223, #8177, #8175...
dhh authored
226 # ==== Examples
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
227 # number_with_precision(111.2345) # => 111.235
228 # number_with_precision(111.2345, :precision => 2) # => 111.23
229 # number_with_precision(13, :precision => 5) # => 13.00000
230 # number_with_precision(389.32314, :precision => 0) # => 389
231 # number_with_precision(111.2345, :significant => true) # => 111
232 # number_with_precision(111.2345, :precision => 1, :significant => true) # => 100
233 # number_with_precision(13, :precision => 5, :significant => true) # => 13.000
c53f77f José Valim Rename unsignificant to insignificant.
josevalim authored
234 # number_with_precision(13, :precision => 5, :significant => true, strip_insignificant_zeros => true)
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
235 # # => 13
236 # number_with_precision(389.32314, :precision => 4, :significant => true) # => 389.3
fea7771 Clemens Kofler Updated NumberHelper: Full i18n support (except number_to_phone), consol...
clemens authored
237 # number_with_precision(1111.2345, :precision => 2, :separator => ',', :delimiter => '.')
238 # # => 1.111,23
0f43de6 Clemens Kofler Refactored NumberHelper API to accept arguments as an options hash [#666...
clemens authored
239 #
240 # You can still use <tt>number_with_precision</tt> with the old API that accepts the
241 # +precision+ as its optional second parameter:
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
242 # number_with_precision(111.2345, 2) # => 111.23
0f43de6 Clemens Kofler Refactored NumberHelper API to accept arguments as an options hash [#666...
clemens authored
243 def number_with_precision(number, *args)
a4090bc Bernardo de Pádua NumberHelper methods should now return html_safe strings (when the input...
bernardo authored
244
245 options = args.extract_options!
246 options.symbolize_keys!
247
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
248 number = begin
249 Float(number)
250 rescue ArgumentError, TypeError
a4090bc Bernardo de Pádua NumberHelper methods should now return html_safe strings (when the input...
bernardo authored
251 if options[:raise]
252 raise InvalidNumberError, number
253 else
254 return number
255 end
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
256 end
257
258 defaults = I18n.translate(:'number.format', :locale => options[:locale], :default => {})
259 precision_defaults = I18n.translate(:'number.precision.format', :locale => options[:locale], :default => {})
dc66469 Clemens Kofler Fixed i18n bulk translate issues in NumberHelper
clemens authored
260 defaults = defaults.merge(precision_defaults)
fea7771 Clemens Kofler Updated NumberHelper: Full i18n support (except number_to_phone), consol...
clemens authored
261
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
262 #Backwards compatibility
0f43de6 Clemens Kofler Refactored NumberHelper API to accept arguments as an options hash [#666...
clemens authored
263 unless args.empty?
fea7771 Clemens Kofler Updated NumberHelper: Full i18n support (except number_to_phone), consol...
clemens authored
264 ActiveSupport::Deprecation.warn('number_with_precision takes an option hash ' +
265 'instead of a separate precision argument.', caller)
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
266 options[:precision] ||= args[0] if args[0]
0f43de6 Clemens Kofler Refactored NumberHelper API to accept arguments as an options hash [#666...
clemens authored
267 end
fea7771 Clemens Kofler Updated NumberHelper: Full i18n support (except number_to_phone), consol...
clemens authored
268
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
269 options = options.reverse_merge(defaults) # Allow the user to unset default values: Eg.: :significant => false
270 precision = options.delete :precision
271 significant = options.delete :significant
c53f77f José Valim Rename unsignificant to insignificant.
josevalim authored
272 strip_insignificant_zeros = options.delete :strip_insignificant_zeros
fea7771 Clemens Kofler Updated NumberHelper: Full i18n support (except number_to_phone), consol...
clemens authored
273
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
274 if significant and precision > 0
275 digits = (Math.log10(number) + 1).floor
276 rounded_number = BigDecimal.new((number / 10 ** (digits - precision)).to_s).round.to_f * 10 ** (digits - precision)
277 precision = precision - digits
278 precision = precision > 0 ? precision : 0 #don't let it be negative
279 else
280 rounded_number = BigDecimal.new((number * (10 ** precision)).to_s).round.to_f / 10 ** precision
8da026c Xavier Shay Remove some of the blank rescues from number helper. This makes the code...
xaviershay authored
281 end
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
282 formatted_number = number_with_delimiter("%01.#{precision}f" % rounded_number, options)
c53f77f José Valim Rename unsignificant to insignificant.
josevalim authored
283 if strip_insignificant_zeros
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
284 escaped_separator = Regexp.escape(options[:separator])
a4090bc Bernardo de Pádua NumberHelper methods should now return html_safe strings (when the input...
bernardo authored
285 formatted_number.sub(/(#{escaped_separator})(\d*[1-9])?0+\z/, '\1\2').sub(/#{escaped_separator}\z/, '').html_safe
8da026c Xavier Shay Remove some of the blank rescues from number helper. This makes the code...
xaviershay authored
286 else
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
287 formatted_number
dc66469 Clemens Kofler Fixed i18n bulk translate issues in NumberHelper
clemens authored
288 end
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
289
1c71a5d David Heinemeier Hansson Upgraded NumberHelper with number_to_phone support international formats...
dhh authored
290 end
2823a56 Jeremy Kemper Deprecation: remove deprecated human_size helper alias. Use number_to_hu...
jeremy authored
291
17db28f Yaroslav Markin Improve i18n support for number_to_human_size helper:
yaroslav authored
292 STORAGE_UNITS = [:byte, :kb, :mb, :gb, :tb].freeze
293
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
294 # Formats the bytes in +number+ into a more understandable representation
0f43de6 Clemens Kofler Refactored NumberHelper API to accept arguments as an options hash [#666...
clemens authored
295 # (e.g., giving it 1500 yields 1.5 KB). This method is useful for
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
296 # reporting file sizes to users. You can customize the
fea7771 Clemens Kofler Updated NumberHelper: Full i18n support (except number_to_phone), consol...
clemens authored
297 # format in the +options+ hash.
298 #
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
299 # See <tt>number_to_human</tt> if you want to pretty-print a generic number.
300 #
fea7771 Clemens Kofler Updated NumberHelper: Full i18n support (except number_to_phone), consol...
clemens authored
301 # ==== Options
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
302 # * <tt>:precision</tt> - Sets the precision of the number (defaults to 3).
303 # * <tt>:significant</tt> - If +true+, precision will be the # of significant_digits. If +false+, the # of fractional digits (defaults to +true+)
304 # * <tt>:separator</tt> - Sets the separator between the fractional and integer digits (defaults to ".").
fea7771 Clemens Kofler Updated NumberHelper: Full i18n support (except number_to_phone), consol...
clemens authored
305 # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to "").
c53f77f José Valim Rename unsignificant to insignificant.
josevalim authored
306 # * <tt>:strip_insignificant_zeros</tt> - If +true+ removes insignificant zeros after the decimal separator (defaults to +true+)
b00e6a9 David Heinemeier Hansson Massive documentation update for all helpers (closes #8223, #8177, #8175...
dhh authored
307 # ==== Examples
fea7771 Clemens Kofler Updated NumberHelper: Full i18n support (except number_to_phone), consol...
clemens authored
308 # number_to_human_size(123) # => 123 Bytes
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
309 # number_to_human_size(1234) # => 1.21 KB
fea7771 Clemens Kofler Updated NumberHelper: Full i18n support (except number_to_phone), consol...
clemens authored
310 # number_to_human_size(12345) # => 12.1 KB
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
311 # number_to_human_size(1234567) # => 1.18 MB
312 # number_to_human_size(1234567890) # => 1.15 GB
313 # number_to_human_size(1234567890123) # => 1.12 TB
314 # number_to_human_size(1234567, :precision => 2) # => 1.2 MB
315 # number_to_human_size(483989, :precision => 2) # => 470 KB
316 # number_to_human_size(1234567, :precision => 2, :separator => ',') # => 1,2 MB
0f43de6 Clemens Kofler Refactored NumberHelper API to accept arguments as an options hash [#666...
clemens authored
317 #
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
318 # Unsignificant zeros after the fractional separator are stripped out by default (set
c53f77f José Valim Rename unsignificant to insignificant.
josevalim authored
319 # <tt>:strip_insignificant_zeros</tt> to +false+ to change that):
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
320 # number_to_human_size(1234567890123, :precision => 5) # => "1.1229 TB"
321 # number_to_human_size(524288000, :precision=>5) # => "500 MB"
98eaa2c Travis Briggs Ensure number_to_human_size does not strip zeros from the end [#1763 sta...
audiodude authored
322 #
0f43de6 Clemens Kofler Refactored NumberHelper API to accept arguments as an options hash [#666...
clemens authored
323 # You can still use <tt>number_to_human_size</tt> with the old API that accepts the
324 # +precision+ as its optional second parameter:
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
325 # number_to_human_size(1234567, 1) # => 1 MB
326 # number_to_human_size(483989, 2) # => 470 KB
fea7771 Clemens Kofler Updated NumberHelper: Full i18n support (except number_to_phone), consol...
clemens authored
327 def number_to_human_size(number, *args)
a4090bc Bernardo de Pádua NumberHelper methods should now return html_safe strings (when the input...
bernardo authored
328 options = args.extract_options!
329 options.symbolize_keys!
330
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
331 number = begin
332 Float(number)
333 rescue ArgumentError, TypeError
a4090bc Bernardo de Pádua NumberHelper methods should now return html_safe strings (when the input...
bernardo authored
334 if options[:raise]
335 raise InvalidNumberError, number
336 else
337 return number
338 end
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
339 end
fea7771 Clemens Kofler Updated NumberHelper: Full i18n support (except number_to_phone), consol...
clemens authored
340
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
341 defaults = I18n.translate(:'number.format', :locale => options[:locale], :default => {})
342 human = I18n.translate(:'number.human.format', :locale => options[:locale], :default => {})
fea7771 Clemens Kofler Updated NumberHelper: Full i18n support (except number_to_phone), consol...
clemens authored
343 defaults = defaults.merge(human)
344
0f43de6 Clemens Kofler Refactored NumberHelper API to accept arguments as an options hash [#666...
clemens authored
345 unless args.empty?
fea7771 Clemens Kofler Updated NumberHelper: Full i18n support (except number_to_phone), consol...
clemens authored
346 ActiveSupport::Deprecation.warn('number_to_human_size takes an option hash ' +
347 'instead of a separate precision argument.', caller)
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
348 options[:precision] ||= args[0] if args[0]
0f43de6 Clemens Kofler Refactored NumberHelper API to accept arguments as an options hash [#666...
clemens authored
349 end
fea7771 Clemens Kofler Updated NumberHelper: Full i18n support (except number_to_phone), consol...
clemens authored
350
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
351 options = options.reverse_merge(defaults)
c53f77f José Valim Rename unsignificant to insignificant.
josevalim authored
352 #for backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files
353 options[:strip_insignificant_zeros] = true if not options.key?(:strip_insignificant_zeros)
fea7771 Clemens Kofler Updated NumberHelper: Full i18n support (except number_to_phone), consol...
clemens authored
354
17db28f Yaroslav Markin Improve i18n support for number_to_human_size helper:
yaroslav authored
355 storage_units_format = I18n.translate(:'number.human.storage_units.format', :locale => options[:locale], :raise => true)
fea7771 Clemens Kofler Updated NumberHelper: Full i18n support (except number_to_phone), consol...
clemens authored
356
17db28f Yaroslav Markin Improve i18n support for number_to_human_size helper:
yaroslav authored
357 if number.to_i < 1024
358 unit = I18n.translate(:'number.human.storage_units.units.byte', :locale => options[:locale], :count => number.to_i, :raise => true)
a4090bc Bernardo de Pádua NumberHelper methods should now return html_safe strings (when the input...
bernardo authored
359 storage_units_format.gsub(/%n/, number.to_i.to_s).gsub(/%u/, unit).html_safe
17db28f Yaroslav Markin Improve i18n support for number_to_human_size helper:
yaroslav authored
360 else
361 max_exp = STORAGE_UNITS.size - 1
362 exponent = (Math.log(number) / Math.log(1024)).to_i # Convert to base 1024
363 exponent = max_exp if exponent > max_exp # we need this to avoid overflow for the highest unit
364 number /= 1024 ** exponent
365
366 unit_key = STORAGE_UNITS[exponent]
367 unit = I18n.translate(:"number.human.storage_units.units.#{unit_key}", :locale => options[:locale], :count => number, :raise => true)
368
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
369 formatted_number = number_with_precision(number, options)
a4090bc Bernardo de Pádua NumberHelper methods should now return html_safe strings (when the input...
bernardo authored
370 storage_units_format.gsub(/%n/, formatted_number).gsub(/%u/, unit).html_safe
dc66469 Clemens Kofler Fixed i18n bulk translate issues in NumberHelper
clemens authored
371 end
7140f65 David Heinemeier Hansson Moved TextHelper#human_size to NumberHelper#number_to_human_size, but ke...
dhh authored
372 end
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
373
374 DECIMAL_UNITS = {0 => :unit, 1 => :ten, 2 => :hundred, 3 => :thousand, 6 => :million, 9 => :billion, 12 => :trillion, 15 => :quadrillion,
375 -1 => :deci, -2 => :centi, -3 => :mili, -6 => :micro, -9 => :nano, -12 => :pico, -15 => :femto}.freeze
376
377 # Pretty prints (formats and approximates) a number in a way it is more readable by humans
378 # (eg.: 1200000000 becomes "1.2 Billion"). This is useful for numbers that
379 # can get very large (and too hard to read).
380 #
381 # See <tt>number_to_human_size</tt> if you want to print a file size.
382 #
383 # You can also define you own unit-quantifier names if you want to use other decimal units
384 # (eg.: 1500 becomes "1.5 kilometers", 0.150 becomes "150 mililiters", etc). You may define
385 # a wide range of unit quantifiers, even fractional ones (centi, deci, mili, etc).
386 #
387 # ==== Options
388 # * <tt>:precision</tt> - Sets the precision of the number (defaults to 3).
389 # * <tt>:significant</tt> - If +true+, precision will be the # of significant_digits. If +false+, the # of fractional digits (defaults to +true+)
390 # * <tt>:separator</tt> - Sets the separator between the fractional and integer digits (defaults to ".").
391 # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to "").
c53f77f José Valim Rename unsignificant to insignificant.
josevalim authored
392 # * <tt>:strip_insignificant_zeros</tt> - If +true+ removes insignificant zeros after the decimal separator (defaults to +true+)
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
393 # * <tt>:units</tt> - A Hash of unit quantifier names. Or a string containing an i18n scope where to find this hash. It might have the following keys:
394 # * *integers*: <tt>:unit</tt>, <tt>:ten</tt>, <tt>:hundred</tt>, <tt>:thousand</tt>, <tt>:million</tt>, <tt>:billion</tt>, <tt>:trillion</tt>, <tt>:quadrillion</tt>
395 # * *fractionals*: <tt>:deci</tt>, <tt>:centi</tt>, <tt>:mili</tt>, <tt>:micro</tt>, <tt>:nano</tt>, <tt>:pico</tt>, <tt>:femto</tt>
396 # * <tt>:format</tt> - Sets the format of the output string (defaults to "%n %u"). The field types are:
397 #
398 # %u The quantifier (ex.: 'thousand')
399 # %n The number
400 #
401 # ==== Examples
402 # number_to_human(123) # => "123"
403 # number_to_human(1234) # => "1.23 Thousand"
404 # number_to_human(12345) # => "12.3 Thousand"
405 # number_to_human(1234567) # => "1.23 Million"
406 # number_to_human(1234567890) # => "1.23 Billion"
407 # number_to_human(1234567890123) # => "1.23 Trillion"
408 # number_to_human(1234567890123456) # => "1.23 Quadrillion"
409 # number_to_human(1234567890123456789) # => "1230 Quadrillion"
410 # number_to_human(489939, :precision => 2) # => "490 Thousand"
411 # number_to_human(489939, :precision => 4) # => "489.9 Thousand"
412 # number_to_human(1234567, :precision => 4,
413 # :significant => false) # => "1.2346 Million"
414 # number_to_human(1234567, :precision => 1,
415 # :separator => ',',
416 # :significant => false) # => "1,2 Million"
417 #
418 # Unsignificant zeros after the decimal separator are stripped out by default (set
c53f77f José Valim Rename unsignificant to insignificant.
josevalim authored
419 # <tt>:strip_insignificant_zeros</tt> to +false+ to change that):
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
420 # number_to_human(12345012345, :significant_digits => 6) # => "12.345 Billion"
421 # number_to_human(500000000, :precision=>5) # => "500 Million"
422 #
423 # ==== Custom Unit Quantifiers
424 #
425 # You can also use your own custom unit quantifiers:
426 # number_to_human(500000, :units => {:unit => "ml", :thousand => "lt"}) # => "500 lt"
427 #
428 # If in your I18n locale you have:
429 # distance:
430 # centi:
431 # one: "centimeter"
432 # other: "centimeters"
433 # unit:
434 # one: "meter"
435 # other: "meters"
436 # thousand:
437 # one: "kilometer"
438 # other: "kilometers"
439 # billion: "gazilion-distance"
440 #
441 # Then you could do:
442 #
443 # number_to_human(543934, :units => :distance) # => "544 kilometers"
444 # number_to_human(54393498, :units => :distance) # => "54400 kilometers"
445 # number_to_human(54393498000, :units => :distance) # => "54.4 gazilion-distance"
446 # number_to_human(343, :units => :distance, :precision => 1) # => "300 meters"
447 # number_to_human(1, :units => :distance) # => "1 meter"
448 # number_to_human(0.34, :units => :distance) # => "34 centimeters"
449 #
450 def number_to_human(number, options = {})
a4090bc Bernardo de Pádua NumberHelper methods should now return html_safe strings (when the input...
bernardo authored
451 options.symbolize_keys!
452
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
453 number = begin
454 Float(number)
455 rescue ArgumentError, TypeError
a4090bc Bernardo de Pádua NumberHelper methods should now return html_safe strings (when the input...
bernardo authored
456 if options[:raise]
457 raise InvalidNumberError, number
458 else
459 return number
460 end
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
461 end
462
463 defaults = I18n.translate(:'number.format', :locale => options[:locale], :default => {})
464 human = I18n.translate(:'number.human.format', :locale => options[:locale], :default => {})
465 defaults = defaults.merge(human)
466
467 options = options.reverse_merge(defaults)
c53f77f José Valim Rename unsignificant to insignificant.
josevalim authored
468 #for backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files
469 options[:strip_insignificant_zeros] = true if not options.key?(:strip_insignificant_zeros)
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
470
471 units = options.delete :units
472 unit_exponents = case units
473 when Hash
474 units
475 when String, Symbol
476 I18n.translate(:"#{units}", :locale => options[:locale], :raise => true)
477 when nil
478 I18n.translate(:"number.human.decimal_units.units", :locale => options[:locale], :raise => true)
479 else
480 raise ArgumentError, ":units must be a Hash or String translation scope."
481 end.keys.map{|e_name| DECIMAL_UNITS.invert[e_name] }.sort_by{|e| -e}
482
483 number_exponent = Math.log10(number).floor
484 display_exponent = unit_exponents.find{|e| number_exponent >= e }
485 number /= 10 ** display_exponent
486
487 unit = case units
488 when Hash
489 units[DECIMAL_UNITS[display_exponent]]
490 when String, Symbol
491 I18n.translate(:"#{units}.#{DECIMAL_UNITS[display_exponent]}", :locale => options[:locale], :count => number.to_i)
492 else
493 I18n.translate(:"number.human.decimal_units.units.#{DECIMAL_UNITS[display_exponent]}", :locale => options[:locale], :count => number.to_i)
494 end
495
496 decimal_format = options[:format] || I18n.translate(:'number.human.decimal_units.format', :locale => options[:locale], :default => "%n %u")
497 formatted_number = number_with_precision(number, options)
a4090bc Bernardo de Pádua NumberHelper methods should now return html_safe strings (when the input...
bernardo authored
498 decimal_format.gsub(/%n/, formatted_number).gsub(/%u/, unit).strip.html_safe
75904c5 Bernardo de Pádua Adds number_to_human and several improvements in NumberHelper. [#4239 st...
bernardo authored
499 end
500
aa09c77 David Heinemeier Hansson Added NumberHelper for common string representations like phone number, ...
dhh authored
501 end
502 end
5cd815a David Heinemeier Hansson Fixed spelling of delimiter #1058
dhh authored
503 end
Something went wrong with that request. Please try again.