core_ext 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 65bef674a3f30a7d453c6daf9c001da0ad8ce670
4
- data.tar.gz: 4091487a2288aeeb53d9a65f16b64bd91e71962a
3
+ metadata.gz: 1bdf3f20c2a4605b931d22569286e4d4a2bc5b89
4
+ data.tar.gz: c27a153f427d418addb719755493eab242b85d95
5
5
  SHA512:
6
- metadata.gz: c4eedaeea00537d6013ce8a4e4176b219bc20894776a27241c6781c611382f92753923d75604ca6d2d7bcb6748dce6d2580993aeceb763b209601d4e846bd95e
7
- data.tar.gz: 8c7e8c31d381fcfa7511f98a5764fed0fe449bfc1b524cd3968c3766ff05f59751d5686b51f016ff79f76f9475fc56b10f9a12bcf4fd8e98c15c97e430854aad
6
+ metadata.gz: fe9e06e452543c0d39defe62ca3117d022987aedb45c7ee2c373a14a59413c20fa30104b31ad3c528e8c3b1056bccda89624c5bddf686dadd9ea45879bd919ab
7
+ data.tar.gz: f2f93d74095ddb305b276d5027fb18fd52361cff76ff1f806a66ecb78f990137be868aaa8e9625f6bb6f2e7535bd62090eaea17a31bc3f654827a53fae42126f
data/lib/core_ext.rb CHANGED
@@ -1,4 +1,7 @@
1
+ require "core_ext/version"
2
+ require "core_ext/module/attribute_accessors"
3
+
1
4
  module CoreExt
5
+ cattr_accessor :test_order # :nodoc :
2
6
  end
3
7
 
4
- require "core_ext/version"
@@ -1,4 +1,5 @@
1
1
  require 'core_ext/concern'
2
+ require 'core_ext/descendants_tracker'
2
3
  require 'core_ext/array/extract_options'
3
4
  require 'core_ext/class/attribute'
4
5
  require 'core_ext/kernel/reporting'
@@ -60,6 +61,10 @@ module CoreExt
60
61
  module Callbacks
61
62
  extend Concern
62
63
 
64
+ included do
65
+ extend CoreExt::DescendantsTracker
66
+ end
67
+
63
68
  CALLBACK_FILTER_TYPES = [:before, :after, :around]
64
69
 
65
70
  # If true, Active Record and Active Model callbacks returning +false+ will
@@ -551,8 +556,10 @@ module CoreExt
551
556
  # This is used internally to append, prepend and skip callbacks to the
552
557
  # CallbackChain.
553
558
  def __update_callbacks(name) #:nodoc:
554
- chain = get_callbacks name
555
- yield self, chain.dup
559
+ ([self] + CoreExt::DescendantsTracker.descendants(self)).reverse_each do |target|
560
+ chain = target.get_callbacks name
561
+ yield target, chain.dup
562
+ end
556
563
  end
557
564
 
558
565
  # Install a callback for the given event.
@@ -641,6 +648,12 @@ module CoreExt
641
648
  # Remove all set callbacks for the given event.
642
649
  def reset_callbacks(name)
643
650
  callbacks = get_callbacks name
651
+ CoreExt::DescendantsTracker.descendants(self).each do |target|
652
+ chain = target.get_callbacks(name).dup
653
+ callbacks.each { |c| chain.delete(c) }
654
+ target.set_callbacks name, chain
655
+ end
656
+
644
657
  set_callbacks name, callbacks.dup.clear
645
658
  end
646
659
 
@@ -0,0 +1,50 @@
1
+ module CoreExt
2
+ # This module provides an internal implementation to track descendants
3
+ # which is faster than iterating through ObjectSpace.
4
+ module DescendantsTracker
5
+ @@direct_descendants = {}
6
+
7
+ class << self
8
+ def direct_descendants(klass)
9
+ @@direct_descendants[klass] || []
10
+ end
11
+
12
+ def descendants(klass)
13
+ arr = []
14
+ accumulate_descendants(klass, arr)
15
+ arr
16
+ end
17
+
18
+ def clear
19
+ @@direct_descendants.clear
20
+ end
21
+
22
+ # This is the only method that is not thread safe, but is only ever called
23
+ # during the eager loading phase.
24
+ def store_inherited(klass, descendant)
25
+ (@@direct_descendants[klass] ||= []) << descendant
26
+ end
27
+
28
+ private
29
+ def accumulate_descendants(klass, acc)
30
+ if direct_descendants = @@direct_descendants[klass]
31
+ acc.concat(direct_descendants)
32
+ direct_descendants.each { |direct_descendant| accumulate_descendants(direct_descendant, acc) }
33
+ end
34
+ end
35
+ end
36
+
37
+ def inherited(base)
38
+ DescendantsTracker.store_inherited(self, base)
39
+ super
40
+ end
41
+
42
+ def direct_descendants
43
+ DescendantsTracker.direct_descendants(self)
44
+ end
45
+
46
+ def descendants
47
+ DescendantsTracker.descendants(self)
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,36 @@
1
+ require 'zlib'
2
+ require 'stringio'
3
+
4
+ module CoreExt
5
+ # A convenient wrapper for the zlib standard library that allows
6
+ # compression/decompression of strings with gzip.
7
+ #
8
+ # gzip = CoreExt::Gzip.compress('compress me!')
9
+ # # => "\x1F\x8B\b\x00o\x8D\xCDO\x00\x03K\xCE\xCF-(J-.V\xC8MU\x04\x00R>n\x83\f\x00\x00\x00"
10
+ #
11
+ # CoreExt::Gzip.decompress(gzip)
12
+ # # => "compress me!"
13
+ module Gzip
14
+ class Stream < StringIO
15
+ def initialize(*)
16
+ super
17
+ set_encoding "BINARY"
18
+ end
19
+ def close; rewind; end
20
+ end
21
+
22
+ # Decompresses a gzipped string.
23
+ def self.decompress(source)
24
+ Zlib::GzipReader.new(StringIO.new(source)).read
25
+ end
26
+
27
+ # Compresses a string using gzip.
28
+ def self.compress(source, level=Zlib::DEFAULT_COMPRESSION, strategy=Zlib::DEFAULT_STRATEGY)
29
+ output = Stream.new
30
+ gz = Zlib::GzipWriter.new(output, level, strategy)
31
+ gz.write(source)
32
+ gz.close
33
+ output.string
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,11 @@
1
+ require 'core_ext/hash/deep_merge'
2
+ require 'core_ext/hash/except'
3
+ require 'core_ext/hash/slice'
4
+ begin
5
+ require 'i18n'
6
+ rescue LoadError => e
7
+ $stderr.puts "The i18n gem is not available. Please add it to your Gemfile and run bundle install"
8
+ raise e
9
+ end
10
+
11
+ I18n.load_path << "#{File.dirname(__FILE__)}/locale/en.yml"
@@ -0,0 +1,135 @@
1
+ en:
2
+ date:
3
+ formats:
4
+ # Use the strftime parameters for formats.
5
+ # When no format has been given, it uses default.
6
+ # You can provide other formats here if you like!
7
+ default: "%Y-%m-%d"
8
+ short: "%b %d"
9
+ long: "%B %d, %Y"
10
+
11
+ day_names: [Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday]
12
+ abbr_day_names: [Sun, Mon, Tue, Wed, Thu, Fri, Sat]
13
+
14
+ # Don't forget the nil at the beginning; there's no such thing as a 0th month
15
+ month_names: [~, January, February, March, April, May, June, July, August, September, October, November, December]
16
+ abbr_month_names: [~, Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec]
17
+ # Used in date_select and datetime_select.
18
+ order:
19
+ - year
20
+ - month
21
+ - day
22
+
23
+ time:
24
+ formats:
25
+ default: "%a, %d %b %Y %H:%M:%S %z"
26
+ short: "%d %b %H:%M"
27
+ long: "%B %d, %Y %H:%M"
28
+ am: "am"
29
+ pm: "pm"
30
+
31
+ # Used in array.to_sentence.
32
+ support:
33
+ array:
34
+ words_connector: ", "
35
+ two_words_connector: " and "
36
+ last_word_connector: ", and "
37
+ number:
38
+ # Used in NumberHelper.number_to_delimited()
39
+ # These are also the defaults for 'currency', 'percentage', 'precision', and 'human'
40
+ format:
41
+ # Sets the separator between the units, for more precision (e.g. 1.0 / 2.0 == 0.5)
42
+ separator: "."
43
+ # Delimits thousands (e.g. 1,000,000 is a million) (always in groups of three)
44
+ delimiter: ","
45
+ # Number of decimals, behind the separator (the number 1 with a precision of 2 gives: 1.00)
46
+ precision: 3
47
+ # If set to true, precision will mean the number of significant digits instead
48
+ # of the number of decimal digits (1234 with precision 2 becomes 1200, 1.23543 becomes 1.2)
49
+ significant: false
50
+ # If set, the zeros after the decimal separator will always be stripped (eg.: 1.200 will be 1.2)
51
+ strip_insignificant_zeros: false
52
+
53
+ # Used in NumberHelper.number_to_currency()
54
+ currency:
55
+ format:
56
+ # Where is the currency sign? %u is the currency unit, %n the number (default: $5.00)
57
+ format: "%u%n"
58
+ unit: "$"
59
+ # These five are to override number.format and are optional
60
+ separator: "."
61
+ delimiter: ","
62
+ precision: 2
63
+ significant: false
64
+ strip_insignificant_zeros: false
65
+
66
+ # Used in NumberHelper.number_to_percentage()
67
+ percentage:
68
+ format:
69
+ # These five are to override number.format and are optional
70
+ # separator:
71
+ delimiter: ""
72
+ # precision:
73
+ # significant: false
74
+ # strip_insignificant_zeros: false
75
+ format: "%n%"
76
+
77
+ # Used in NumberHelper.number_to_rounded()
78
+ precision:
79
+ format:
80
+ # These five are to override number.format and are optional
81
+ # separator:
82
+ delimiter: ""
83
+ # precision:
84
+ # significant: false
85
+ # strip_insignificant_zeros: false
86
+
87
+ # Used in NumberHelper.number_to_human_size() and NumberHelper.number_to_human()
88
+ human:
89
+ format:
90
+ # These five are to override number.format and are optional
91
+ # separator:
92
+ delimiter: ""
93
+ precision: 3
94
+ significant: true
95
+ strip_insignificant_zeros: true
96
+ # Used in number_to_human_size()
97
+ storage_units:
98
+ # Storage units output formatting.
99
+ # %u is the storage unit, %n is the number (default: 2 MB)
100
+ format: "%n %u"
101
+ units:
102
+ byte:
103
+ one: "Byte"
104
+ other: "Bytes"
105
+ kb: "KB"
106
+ mb: "MB"
107
+ gb: "GB"
108
+ tb: "TB"
109
+ pb: "PB"
110
+ eb: "EB"
111
+ # Used in NumberHelper.number_to_human()
112
+ decimal_units:
113
+ format: "%n %u"
114
+ # Decimal units output formatting
115
+ # By default we will only quantify some of the exponents
116
+ # but the commented ones might be defined or overridden
117
+ # by the user.
118
+ units:
119
+ # femto: Quadrillionth
120
+ # pico: Trillionth
121
+ # nano: Billionth
122
+ # micro: Millionth
123
+ # mili: Thousandth
124
+ # centi: Hundredth
125
+ # deci: Tenth
126
+ unit: ""
127
+ # ten:
128
+ # one: Ten
129
+ # other: Tens
130
+ # hundred: Hundred
131
+ thousand: Thousand
132
+ million: Million
133
+ billion: Billion
134
+ trillion: Trillion
135
+ quadrillion: Quadrillion
@@ -0,0 +1,358 @@
1
+ module CoreExt
2
+ module NumberHelper
3
+
4
+ require "core_ext/number_helper/number_converter"
5
+ require "core_ext/number_helper/number_to_rounded_converter"
6
+ require "core_ext/number_helper/number_to_delimited_converter"
7
+ require "core_ext/number_helper/number_to_human_converter"
8
+ require "core_ext/number_helper/number_to_human_size_converter"
9
+ require "core_ext/number_helper/number_to_phone_converter"
10
+ require "core_ext/number_helper/number_to_currency_converter"
11
+ require "core_ext/number_helper/number_to_percentage_converter"
12
+
13
+ extend self
14
+
15
+ # Formats a +number+ into a US phone number (e.g., (555)
16
+ # 123-9876). You can customize the format in the +options+ hash.
17
+ #
18
+ # ==== Options
19
+ #
20
+ # * <tt>:area_code</tt> - Adds parentheses around the area code.
21
+ # * <tt>:delimiter</tt> - Specifies the delimiter to use
22
+ # (defaults to "-").
23
+ # * <tt>:extension</tt> - Specifies an extension to add to the
24
+ # end of the generated number.
25
+ # * <tt>:country_code</tt> - Sets the country code for the phone
26
+ # number.
27
+ # ==== Examples
28
+ #
29
+ # number_to_phone(5551234) # => 555-1234
30
+ # number_to_phone('5551234') # => 555-1234
31
+ # number_to_phone(1235551234) # => 123-555-1234
32
+ # number_to_phone(1235551234, area_code: true) # => (123) 555-1234
33
+ # number_to_phone(1235551234, delimiter: ' ') # => 123 555 1234
34
+ # number_to_phone(1235551234, area_code: true, extension: 555) # => (123) 555-1234 x 555
35
+ # number_to_phone(1235551234, country_code: 1) # => +1-123-555-1234
36
+ # number_to_phone('123a456') # => 123a456
37
+ #
38
+ # number_to_phone(1235551234, country_code: 1, extension: 1343, delimiter: '.')
39
+ # # => +1.123.555.1234 x 1343
40
+ def number_to_phone(number, options = {})
41
+ NumberToPhoneConverter.convert(number, options)
42
+ end
43
+
44
+ # Formats a +number+ into a currency string (e.g., $13.65). You
45
+ # can customize the format in the +options+ hash.
46
+ #
47
+ # The currency unit and number formatting of the current locale will be used
48
+ # unless otherwise specified in the provided options. No currency conversion
49
+ # is performed. If the user is given a way to change their locale, they will
50
+ # also be able to change the relative value of the currency displayed with
51
+ # this helper. If your application will ever support multiple locales, you
52
+ # may want to specify a constant <tt>:locale</tt> option or consider
53
+ # using a library capable of currency conversion.
54
+ #
55
+ # ==== Options
56
+ #
57
+ # * <tt>:locale</tt> - Sets the locale to be used for formatting
58
+ # (defaults to current locale).
59
+ # * <tt>:precision</tt> - Sets the level of precision (defaults
60
+ # to 2).
61
+ # * <tt>:unit</tt> - Sets the denomination of the currency
62
+ # (defaults to "$").
63
+ # * <tt>:separator</tt> - Sets the separator between the units
64
+ # (defaults to ".").
65
+ # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults
66
+ # to ",").
67
+ # * <tt>:format</tt> - Sets the format for non-negative numbers
68
+ # (defaults to "%u%n"). Fields are <tt>%u</tt> for the
69
+ # currency, and <tt>%n</tt> for the number.
70
+ # * <tt>:negative_format</tt> - Sets the format for negative
71
+ # numbers (defaults to prepending an hyphen to the formatted
72
+ # number given by <tt>:format</tt>). Accepts the same fields
73
+ # than <tt>:format</tt>, except <tt>%n</tt> is here the
74
+ # absolute value of the number.
75
+ #
76
+ # ==== Examples
77
+ #
78
+ # number_to_currency(1234567890.50) # => $1,234,567,890.50
79
+ # number_to_currency(1234567890.506) # => $1,234,567,890.51
80
+ # number_to_currency(1234567890.506, precision: 3) # => $1,234,567,890.506
81
+ # number_to_currency(1234567890.506, locale: :fr) # => 1 234 567 890,51 €
82
+ # number_to_currency('123a456') # => $123a456
83
+ #
84
+ # number_to_currency(-1234567890.50, negative_format: '(%u%n)')
85
+ # # => ($1,234,567,890.50)
86
+ # number_to_currency(1234567890.50, unit: '&pound;', separator: ',', delimiter: '')
87
+ # # => &pound;1234567890,50
88
+ # number_to_currency(1234567890.50, unit: '&pound;', separator: ',', delimiter: '', format: '%n %u')
89
+ # # => 1234567890,50 &pound;
90
+ def number_to_currency(number, options = {})
91
+ NumberToCurrencyConverter.convert(number, options)
92
+ end
93
+
94
+ # Formats a +number+ as a percentage string (e.g., 65%). You can
95
+ # customize the format in the +options+ hash.
96
+ #
97
+ # ==== Options
98
+ #
99
+ # * <tt>:locale</tt> - Sets the locale to be used for formatting
100
+ # (defaults to current locale).
101
+ # * <tt>:precision</tt> - Sets the precision of the number
102
+ # (defaults to 3). Keeps the number's precision if nil.
103
+ # * <tt>:significant</tt> - If +true+, precision will be the number
104
+ # of significant_digits. If +false+, the number of fractional
105
+ # digits (defaults to +false+).
106
+ # * <tt>:separator</tt> - Sets the separator between the
107
+ # fractional and integer digits (defaults to ".").
108
+ # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults
109
+ # to "").
110
+ # * <tt>:strip_insignificant_zeros</tt> - If +true+ removes
111
+ # insignificant zeros after the decimal separator (defaults to
112
+ # +false+).
113
+ # * <tt>:format</tt> - Specifies the format of the percentage
114
+ # string The number field is <tt>%n</tt> (defaults to "%n%").
115
+ #
116
+ # ==== Examples
117
+ #
118
+ # number_to_percentage(100) # => 100.000%
119
+ # number_to_percentage('98') # => 98.000%
120
+ # number_to_percentage(100, precision: 0) # => 100%
121
+ # number_to_percentage(1000, delimiter: '.', separator: ',') # => 1.000,000%
122
+ # number_to_percentage(302.24398923423, precision: 5) # => 302.24399%
123
+ # number_to_percentage(1000, locale: :fr) # => 1000,000%
124
+ # number_to_percentage(1000, precision: nil) # => 1000%
125
+ # number_to_percentage('98a') # => 98a%
126
+ # number_to_percentage(100, format: '%n %') # => 100.000 %
127
+ def number_to_percentage(number, options = {})
128
+ NumberToPercentageConverter.convert(number, options)
129
+ end
130
+
131
+ # Formats a +number+ with grouped thousands using +delimiter+
132
+ # (e.g., 12,324). You can customize the format in the +options+
133
+ # hash.
134
+ #
135
+ # ==== Options
136
+ #
137
+ # * <tt>:locale</tt> - Sets the locale to be used for formatting
138
+ # (defaults to current locale).
139
+ # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults
140
+ # to ",").
141
+ # * <tt>:separator</tt> - Sets the separator between the
142
+ # fractional and integer digits (defaults to ".").
143
+ # * <tt>:delimiter_pattern</tt> - Sets a custom regular expression used for
144
+ # deriving the placement of delimiter. Helpful when using currency formats
145
+ # like INR.
146
+ #
147
+ # ==== Examples
148
+ #
149
+ # number_to_delimited(12345678) # => 12,345,678
150
+ # number_to_delimited('123456') # => 123,456
151
+ # number_to_delimited(12345678.05) # => 12,345,678.05
152
+ # number_to_delimited(12345678, delimiter: '.') # => 12.345.678
153
+ # number_to_delimited(12345678, delimiter: ',') # => 12,345,678
154
+ # number_to_delimited(12345678.05, separator: ' ') # => 12,345,678 05
155
+ # number_to_delimited(12345678.05, locale: :fr) # => 12 345 678,05
156
+ # number_to_delimited('112a') # => 112a
157
+ # number_to_delimited(98765432.98, delimiter: ' ', separator: ',')
158
+ # # => 98 765 432,98
159
+ # number_to_delimited("123456.78",
160
+ # delimiter_pattern: /(\d+?)(?=(\d\d)+(\d)(?!\d))/)
161
+ # # => 1,23,456.78
162
+ def number_to_delimited(number, options = {})
163
+ NumberToDelimitedConverter.convert(number, options)
164
+ end
165
+
166
+ # Formats a +number+ with the specified level of
167
+ # <tt>:precision</tt> (e.g., 112.32 has a precision of 2 if
168
+ # +:significant+ is +false+, and 5 if +:significant+ is +true+).
169
+ # You can customize the format in the +options+ hash.
170
+ #
171
+ # ==== Options
172
+ #
173
+ # * <tt>:locale</tt> - Sets the locale to be used for formatting
174
+ # (defaults to current locale).
175
+ # * <tt>:precision</tt> - Sets the precision of the number
176
+ # (defaults to 3). Keeps the number's precision if nil.
177
+ # * <tt>:significant</tt> - If +true+, precision will be the number
178
+ # of significant_digits. If +false+, the number of fractional
179
+ # digits (defaults to +false+).
180
+ # * <tt>:separator</tt> - Sets the separator between the
181
+ # fractional and integer digits (defaults to ".").
182
+ # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults
183
+ # to "").
184
+ # * <tt>:strip_insignificant_zeros</tt> - If +true+ removes
185
+ # insignificant zeros after the decimal separator (defaults to
186
+ # +false+).
187
+ #
188
+ # ==== Examples
189
+ #
190
+ # number_to_rounded(111.2345) # => 111.235
191
+ # number_to_rounded(111.2345, precision: 2) # => 111.23
192
+ # number_to_rounded(13, precision: 5) # => 13.00000
193
+ # number_to_rounded(389.32314, precision: 0) # => 389
194
+ # number_to_rounded(111.2345, significant: true) # => 111
195
+ # number_to_rounded(111.2345, precision: 1, significant: true) # => 100
196
+ # number_to_rounded(13, precision: 5, significant: true) # => 13.000
197
+ # number_to_rounded(13, precision: nil) # => 13
198
+ # number_to_rounded(111.234, locale: :fr) # => 111,234
199
+ #
200
+ # number_to_rounded(13, precision: 5, significant: true, strip_insignificant_zeros: true)
201
+ # # => 13
202
+ #
203
+ # number_to_rounded(389.32314, precision: 4, significant: true) # => 389.3
204
+ # number_to_rounded(1111.2345, precision: 2, separator: ',', delimiter: '.')
205
+ # # => 1.111,23
206
+ def number_to_rounded(number, options = {})
207
+ NumberToRoundedConverter.convert(number, options)
208
+ end
209
+
210
+ # Formats the bytes in +number+ into a more understandable
211
+ # representation (e.g., giving it 1500 yields 1.5 KB). This
212
+ # method is useful for reporting file sizes to users. You can
213
+ # customize the format in the +options+ hash.
214
+ #
215
+ # See <tt>number_to_human</tt> if you want to pretty-print a
216
+ # generic number.
217
+ #
218
+ # ==== Options
219
+ #
220
+ # * <tt>:locale</tt> - Sets the locale to be used for formatting
221
+ # (defaults to current locale).
222
+ # * <tt>:precision</tt> - Sets the precision of the number
223
+ # (defaults to 3).
224
+ # * <tt>:significant</tt> - If +true+, precision will be the number
225
+ # of significant_digits. If +false+, the number of fractional
226
+ # digits (defaults to +true+)
227
+ # * <tt>:separator</tt> - Sets the separator between the
228
+ # fractional and integer digits (defaults to ".").
229
+ # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults
230
+ # to "").
231
+ # * <tt>:strip_insignificant_zeros</tt> - If +true+ removes
232
+ # insignificant zeros after the decimal separator (defaults to
233
+ # +true+)
234
+ #
235
+ # ==== Examples
236
+ #
237
+ # number_to_human_size(123) # => 123 Bytes
238
+ # number_to_human_size(1234) # => 1.21 KB
239
+ # number_to_human_size(12345) # => 12.1 KB
240
+ # number_to_human_size(1234567) # => 1.18 MB
241
+ # number_to_human_size(1234567890) # => 1.15 GB
242
+ # number_to_human_size(1234567890123) # => 1.12 TB
243
+ # number_to_human_size(1234567890123456) # => 1.1 PB
244
+ # number_to_human_size(1234567890123456789) # => 1.07 EB
245
+ # number_to_human_size(1234567, precision: 2) # => 1.2 MB
246
+ # number_to_human_size(483989, precision: 2) # => 470 KB
247
+ # number_to_human_size(1234567, precision: 2, separator: ',') # => 1,2 MB
248
+ # number_to_human_size(1234567890123, precision: 5) # => "1.1228 TB"
249
+ # number_to_human_size(524288000, precision: 5) # => "500 MB"
250
+ def number_to_human_size(number, options = {})
251
+ NumberToHumanSizeConverter.convert(number, options)
252
+ end
253
+
254
+ # Pretty prints (formats and approximates) a number in a way it
255
+ # is more readable by humans (eg.: 1200000000 becomes "1.2
256
+ # Billion"). This is useful for numbers that can get very large
257
+ # (and too hard to read).
258
+ #
259
+ # See <tt>number_to_human_size</tt> if you want to print a file
260
+ # size.
261
+ #
262
+ # You can also define your own unit-quantifier names if you want
263
+ # to use other decimal units (eg.: 1500 becomes "1.5
264
+ # kilometers", 0.150 becomes "150 milliliters", etc). You may
265
+ # define a wide range of unit quantifiers, even fractional ones
266
+ # (centi, deci, mili, etc).
267
+ #
268
+ # ==== Options
269
+ #
270
+ # * <tt>:locale</tt> - Sets the locale to be used for formatting
271
+ # (defaults to current locale).
272
+ # * <tt>:precision</tt> - Sets the precision of the number
273
+ # (defaults to 3).
274
+ # * <tt>:significant</tt> - If +true+, precision will be the number
275
+ # of significant_digits. If +false+, the number of fractional
276
+ # digits (defaults to +true+)
277
+ # * <tt>:separator</tt> - Sets the separator between the
278
+ # fractional and integer digits (defaults to ".").
279
+ # * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults
280
+ # to "").
281
+ # * <tt>:strip_insignificant_zeros</tt> - If +true+ removes
282
+ # insignificant zeros after the decimal separator (defaults to
283
+ # +true+)
284
+ # * <tt>:units</tt> - A Hash of unit quantifier names. Or a
285
+ # string containing an i18n scope where to find this hash. It
286
+ # might have the following keys:
287
+ # * *integers*: <tt>:unit</tt>, <tt>:ten</tt>,
288
+ # <tt>:hundred</tt>, <tt>:thousand</tt>, <tt>:million</tt>,
289
+ # <tt>:billion</tt>, <tt>:trillion</tt>,
290
+ # <tt>:quadrillion</tt>
291
+ # * *fractionals*: <tt>:deci</tt>, <tt>:centi</tt>,
292
+ # <tt>:mili</tt>, <tt>:micro</tt>, <tt>:nano</tt>,
293
+ # <tt>:pico</tt>, <tt>:femto</tt>
294
+ # * <tt>:format</tt> - Sets the format of the output string
295
+ # (defaults to "%n %u"). The field types are:
296
+ # * %u - The quantifier (ex.: 'thousand')
297
+ # * %n - The number
298
+ #
299
+ # ==== Examples
300
+ #
301
+ # number_to_human(123) # => "123"
302
+ # number_to_human(1234) # => "1.23 Thousand"
303
+ # number_to_human(12345) # => "12.3 Thousand"
304
+ # number_to_human(1234567) # => "1.23 Million"
305
+ # number_to_human(1234567890) # => "1.23 Billion"
306
+ # number_to_human(1234567890123) # => "1.23 Trillion"
307
+ # number_to_human(1234567890123456) # => "1.23 Quadrillion"
308
+ # number_to_human(1234567890123456789) # => "1230 Quadrillion"
309
+ # number_to_human(489939, precision: 2) # => "490 Thousand"
310
+ # number_to_human(489939, precision: 4) # => "489.9 Thousand"
311
+ # number_to_human(1234567, precision: 4,
312
+ # significant: false) # => "1.2346 Million"
313
+ # number_to_human(1234567, precision: 1,
314
+ # separator: ',',
315
+ # significant: false) # => "1,2 Million"
316
+ #
317
+ # number_to_human(500000000, precision: 5) # => "500 Million"
318
+ # number_to_human(12345012345, significant: false) # => "12.345 Billion"
319
+ #
320
+ # Non-significant zeros after the decimal separator are stripped
321
+ # out by default (set <tt>:strip_insignificant_zeros</tt> to
322
+ # +false+ to change that):
323
+ #
324
+ # number_to_human(12.00001) # => "12"
325
+ # number_to_human(12.00001, strip_insignificant_zeros: false) # => "12.0"
326
+ #
327
+ # ==== Custom Unit Quantifiers
328
+ #
329
+ # You can also use your own custom unit quantifiers:
330
+ # number_to_human(500000, units: { unit: 'ml', thousand: 'lt' }) # => "500 lt"
331
+ #
332
+ # If in your I18n locale you have:
333
+ #
334
+ # distance:
335
+ # centi:
336
+ # one: "centimeter"
337
+ # other: "centimeters"
338
+ # unit:
339
+ # one: "meter"
340
+ # other: "meters"
341
+ # thousand:
342
+ # one: "kilometer"
343
+ # other: "kilometers"
344
+ # billion: "gazillion-distance"
345
+ #
346
+ # Then you could do:
347
+ #
348
+ # number_to_human(543934, units: :distance) # => "544 kilometers"
349
+ # number_to_human(54393498, units: :distance) # => "54400 kilometers"
350
+ # number_to_human(54393498000, units: :distance) # => "54.4 gazillion-distance"
351
+ # number_to_human(343, units: :distance, precision: 1) # => "300 meters"
352
+ # number_to_human(1, units: :distance) # => "1 meter"
353
+ # number_to_human(0.34, units: :distance) # => "34 centimeters"
354
+ def number_to_human(number, options = {})
355
+ NumberToHumanConverter.convert(number, options)
356
+ end
357
+ end
358
+ end