Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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