activesupport 4.0.12 → 7.0.2.4
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.
Potentially problematic release.
This version of activesupport might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +249 -501
- data/MIT-LICENSE +2 -2
- data/README.rdoc +10 -5
- data/lib/active_support/actionable_error.rb +48 -0
- data/lib/active_support/all.rb +5 -3
- data/lib/active_support/array_inquirer.rb +48 -0
- data/lib/active_support/backtrace_cleaner.rb +41 -13
- data/lib/active_support/benchmarkable.rb +7 -15
- data/lib/active_support/builder.rb +3 -1
- data/lib/active_support/cache/file_store.rb +96 -74
- data/lib/active_support/cache/mem_cache_store.rb +211 -103
- data/lib/active_support/cache/memory_store.rb +90 -58
- data/lib/active_support/cache/null_store.rb +19 -7
- data/lib/active_support/cache/redis_cache_store.rb +468 -0
- data/lib/active_support/cache/strategy/local_cache.rb +86 -83
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +45 -0
- data/lib/active_support/cache.rb +580 -241
- data/lib/active_support/callbacks.rb +812 -425
- data/lib/active_support/code_generator.rb +65 -0
- data/lib/active_support/concern.rb +103 -14
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +33 -0
- data/lib/active_support/concurrency/share_lock.rb +226 -0
- data/lib/active_support/configurable.rb +21 -19
- data/lib/active_support/configuration_file.rb +51 -0
- data/lib/active_support/core_ext/array/access.rb +47 -1
- data/lib/active_support/core_ext/array/conversions.rb +35 -44
- data/lib/active_support/core_ext/array/deprecated_conversions.rb +25 -0
- data/lib/active_support/core_ext/array/extract.rb +21 -0
- data/lib/active_support/core_ext/array/extract_options.rb +2 -0
- data/lib/active_support/core_ext/array/grouping.rb +26 -16
- data/lib/active_support/core_ext/array/inquiry.rb +19 -0
- data/lib/active_support/core_ext/array/wrap.rb +7 -4
- data/lib/active_support/core_ext/array.rb +10 -7
- data/lib/active_support/core_ext/benchmark.rb +5 -3
- data/lib/active_support/core_ext/big_decimal/conversions.rb +9 -26
- data/lib/active_support/core_ext/big_decimal.rb +3 -1
- data/lib/active_support/core_ext/class/attribute.rb +52 -49
- data/lib/active_support/core_ext/class/attribute_accessors.rb +5 -169
- data/lib/active_support/core_ext/class/subclasses.rb +25 -26
- data/lib/active_support/core_ext/class.rb +4 -4
- data/lib/active_support/core_ext/date/acts_like.rb +3 -1
- data/lib/active_support/core_ext/date/blank.rb +14 -0
- data/lib/active_support/core_ext/date/calculations.rb +31 -18
- data/lib/active_support/core_ext/date/conversions.rb +43 -32
- data/lib/active_support/core_ext/date/deprecated_conversions.rb +26 -0
- data/lib/active_support/core_ext/date/zones.rb +5 -34
- data/lib/active_support/core_ext/date.rb +7 -4
- data/lib/active_support/core_ext/date_and_time/calculations.rb +198 -66
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +31 -0
- data/lib/active_support/core_ext/date_and_time/zones.rb +40 -0
- data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
- data/lib/active_support/core_ext/date_time/blank.rb +14 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +79 -38
- data/lib/active_support/core_ext/date_time/compatibility.rb +18 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +31 -26
- data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +22 -0
- data/lib/active_support/core_ext/date_time.rb +8 -4
- data/lib/active_support/core_ext/digest/uuid.rb +79 -0
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/enumerable.rb +249 -17
- data/lib/active_support/core_ext/file/atomic.rb +41 -32
- data/lib/active_support/core_ext/file.rb +3 -1
- data/lib/active_support/core_ext/hash/conversions.rb +71 -49
- data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
- data/lib/active_support/core_ext/hash/except.rb +14 -5
- data/lib/active_support/core_ext/hash/indifferent_access.rb +5 -3
- data/lib/active_support/core_ext/hash/keys.rb +39 -56
- data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
- data/lib/active_support/core_ext/hash/slice.rb +8 -23
- data/lib/active_support/core_ext/hash.rb +10 -8
- data/lib/active_support/core_ext/integer/inflections.rb +3 -1
- data/lib/active_support/core_ext/integer/multiple.rb +3 -1
- data/lib/active_support/core_ext/integer/time.rb +11 -33
- data/lib/active_support/core_ext/integer.rb +5 -3
- data/lib/active_support/core_ext/kernel/concern.rb +14 -0
- data/lib/active_support/core_ext/kernel/reporting.rb +9 -78
- data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
- data/lib/active_support/core_ext/kernel.rb +5 -4
- data/lib/active_support/core_ext/load_error.rb +5 -21
- data/lib/active_support/core_ext/module/aliasing.rb +6 -44
- data/lib/active_support/core_ext/module/anonymous.rb +12 -1
- data/lib/active_support/core_ext/module/attr_internal.rb +8 -8
- data/lib/active_support/core_ext/module/attribute_accessors.rb +186 -44
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +157 -0
- data/lib/active_support/core_ext/module/concerning.rb +140 -0
- data/lib/active_support/core_ext/module/delegation.rb +172 -45
- data/lib/active_support/core_ext/module/deprecation.rb +3 -3
- data/lib/active_support/core_ext/module/introspection.rb +23 -38
- data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
- data/lib/active_support/core_ext/module/remove_method.rb +8 -3
- data/lib/active_support/core_ext/module.rb +13 -10
- data/lib/active_support/core_ext/name_error.rb +45 -4
- data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +135 -127
- data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +60 -0
- data/lib/active_support/core_ext/numeric/time.rb +37 -50
- data/lib/active_support/core_ext/numeric.rb +6 -3
- data/lib/active_support/core_ext/object/acts_like.rb +41 -6
- data/lib/active_support/core_ext/object/blank.rb +70 -20
- data/lib/active_support/core_ext/object/conversions.rb +6 -4
- data/lib/active_support/core_ext/object/deep_dup.rb +19 -10
- data/lib/active_support/core_ext/object/duplicable.rb +17 -47
- data/lib/active_support/core_ext/object/inclusion.rb +18 -15
- data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
- data/lib/active_support/core_ext/object/json.rb +244 -0
- data/lib/active_support/core_ext/object/to_param.rb +3 -1
- data/lib/active_support/core_ext/object/to_query.rb +21 -8
- data/lib/active_support/core_ext/object/try.rb +106 -26
- data/lib/active_support/core_ext/object/with_options.rb +64 -5
- data/lib/active_support/core_ext/object.rb +14 -12
- data/lib/active_support/core_ext/pathname/existence.rb +21 -0
- data/lib/active_support/core_ext/pathname.rb +3 -0
- data/lib/active_support/core_ext/range/compare_range.rb +57 -0
- data/lib/active_support/core_ext/range/conversions.rb +37 -15
- data/lib/active_support/core_ext/range/deprecated_conversions.rb +26 -0
- data/lib/active_support/core_ext/range/each.rb +18 -17
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +7 -0
- data/lib/active_support/core_ext/range/overlaps.rb +2 -0
- data/lib/active_support/core_ext/range.rb +7 -4
- data/lib/active_support/core_ext/regexp.rb +10 -1
- data/lib/active_support/core_ext/securerandom.rb +45 -0
- data/lib/active_support/core_ext/string/access.rb +42 -51
- data/lib/active_support/core_ext/string/behavior.rb +3 -1
- data/lib/active_support/core_ext/string/conversions.rb +18 -13
- data/lib/active_support/core_ext/string/exclude.rb +5 -3
- data/lib/active_support/core_ext/string/filters.rb +97 -7
- data/lib/active_support/core_ext/string/indent.rb +6 -4
- data/lib/active_support/core_ext/string/inflections.rb +106 -25
- data/lib/active_support/core_ext/string/inquiry.rb +4 -1
- data/lib/active_support/core_ext/string/multibyte.rb +18 -9
- data/lib/active_support/core_ext/string/output_safety.rb +227 -54
- data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
- data/lib/active_support/core_ext/string/strip.rb +6 -5
- data/lib/active_support/core_ext/string/zones.rb +4 -1
- data/lib/active_support/core_ext/string.rb +15 -13
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +6 -0
- data/lib/active_support/core_ext/symbol.rb +3 -0
- data/lib/active_support/core_ext/time/acts_like.rb +3 -1
- data/lib/active_support/core_ext/time/calculations.rb +178 -116
- data/lib/active_support/core_ext/time/compatibility.rb +16 -0
- data/lib/active_support/core_ext/time/conversions.rb +37 -25
- data/lib/active_support/core_ext/time/deprecated_conversions.rb +22 -0
- data/lib/active_support/core_ext/time/zones.rb +44 -42
- data/lib/active_support/core_ext/time.rb +8 -5
- data/lib/active_support/core_ext/uri.rb +4 -25
- data/lib/active_support/core_ext.rb +4 -2
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/current_attributes.rb +226 -0
- data/lib/active_support/dependencies/autoload.rb +3 -1
- data/lib/active_support/dependencies/interlock.rb +49 -0
- data/lib/active_support/dependencies/require_dependency.rb +28 -0
- data/lib/active_support/dependencies.rb +71 -696
- data/lib/active_support/deprecation/behaviors.rb +65 -16
- data/lib/active_support/deprecation/constant_accessor.rb +52 -0
- data/lib/active_support/deprecation/disallowed.rb +56 -0
- data/lib/active_support/deprecation/instance_delegator.rb +16 -2
- data/lib/active_support/deprecation/method_wrappers.rb +62 -21
- data/lib/active_support/deprecation/proxy_wrappers.rb +82 -31
- data/lib/active_support/deprecation/reporting.rb +81 -18
- data/lib/active_support/deprecation.rb +19 -11
- data/lib/active_support/descendants_tracker.rb +192 -34
- data/lib/active_support/digest.rb +22 -0
- data/lib/active_support/duration/iso8601_parser.rb +123 -0
- data/lib/active_support/duration/iso8601_serializer.rb +67 -0
- data/lib/active_support/duration.rb +437 -39
- data/lib/active_support/encrypted_configuration.rb +56 -0
- data/lib/active_support/encrypted_file.rb +117 -0
- data/lib/active_support/environment_inquirer.rb +20 -0
- data/lib/active_support/error_reporter.rb +117 -0
- data/lib/active_support/evented_file_update_checker.rb +170 -0
- data/lib/active_support/execution_context/test_helper.rb +13 -0
- data/lib/active_support/execution_context.rb +53 -0
- data/lib/active_support/execution_wrapper.rb +151 -0
- data/lib/active_support/executor/test_helper.rb +7 -0
- data/lib/active_support/executor.rb +8 -0
- data/lib/active_support/file_update_checker.rb +62 -37
- data/lib/active_support/fork_tracker.rb +71 -0
- data/lib/active_support/gem_version.rb +17 -0
- data/lib/active_support/gzip.rb +7 -5
- data/lib/active_support/hash_with_indifferent_access.rb +207 -54
- data/lib/active_support/html_safe_translation.rb +43 -0
- data/lib/active_support/i18n.rb +10 -6
- data/lib/active_support/i18n_railtie.rb +48 -19
- data/lib/active_support/inflections.rb +19 -12
- data/lib/active_support/inflector/inflections.rb +97 -37
- data/lib/active_support/inflector/methods.rb +192 -157
- data/lib/active_support/inflector/transliterate.rb +83 -33
- data/lib/active_support/inflector.rb +7 -5
- data/lib/active_support/isolated_execution_state.rb +64 -0
- data/lib/active_support/json/decoding.rb +37 -42
- data/lib/active_support/json/encoding.rb +93 -293
- data/lib/active_support/json.rb +4 -2
- data/lib/active_support/key_generator.rb +30 -47
- data/lib/active_support/lazy_load_hooks.rb +54 -21
- data/lib/active_support/locale/en.rb +33 -0
- data/lib/active_support/locale/en.yml +10 -4
- data/lib/active_support/log_subscriber/test_helper.rb +14 -12
- data/lib/active_support/log_subscriber.rb +61 -18
- data/lib/active_support/logger.rb +40 -4
- data/lib/active_support/logger_silence.rb +17 -20
- data/lib/active_support/logger_thread_safe_level.rb +69 -0
- data/lib/active_support/message_encryptor.rb +178 -55
- data/lib/active_support/message_verifier.rb +195 -26
- data/lib/active_support/messages/metadata.rb +80 -0
- data/lib/active_support/messages/rotation_configuration.rb +23 -0
- data/lib/active_support/messages/rotator.rb +57 -0
- data/lib/active_support/multibyte/chars.rb +45 -92
- data/lib/active_support/multibyte/unicode.rb +44 -377
- data/lib/active_support/multibyte.rb +5 -3
- data/lib/active_support/notifications/fanout.rb +177 -44
- data/lib/active_support/notifications/instrumenter.rb +117 -17
- data/lib/active_support/notifications.rb +106 -39
- data/lib/active_support/number_helper/number_converter.rb +181 -0
- data/lib/active_support/number_helper/number_to_currency_converter.rb +46 -0
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +30 -0
- data/lib/active_support/number_helper/number_to_human_converter.rb +69 -0
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +60 -0
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +16 -0
- data/lib/active_support/number_helper/number_to_phone_converter.rb +59 -0
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +59 -0
- data/lib/active_support/number_helper/rounding_helper.rb +46 -0
- data/lib/active_support/number_helper.rb +152 -394
- data/lib/active_support/option_merger.rb +18 -5
- data/lib/active_support/ordered_hash.rb +8 -6
- data/lib/active_support/ordered_options.rb +43 -7
- data/lib/active_support/parameter_filter.rb +138 -0
- data/lib/active_support/per_thread_registry.rb +24 -11
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/rails.rb +10 -11
- data/lib/active_support/railtie.rb +118 -12
- data/lib/active_support/reloader.rb +130 -0
- data/lib/active_support/rescuable.rb +112 -57
- data/lib/active_support/ruby_features.rb +7 -0
- data/lib/active_support/secure_compare_rotator.rb +51 -0
- data/lib/active_support/security_utils.rb +38 -0
- data/lib/active_support/string_inquirer.rb +11 -4
- data/lib/active_support/subscriber.rb +109 -39
- data/lib/active_support/tagged_logging.rb +54 -17
- data/lib/active_support/test_case.rb +121 -37
- data/lib/active_support/testing/assertions.rb +177 -39
- data/lib/active_support/testing/autorun.rb +5 -3
- data/lib/active_support/testing/constant_lookup.rb +3 -6
- data/lib/active_support/testing/declarative.rb +10 -22
- data/lib/active_support/testing/deprecation.rb +65 -11
- data/lib/active_support/testing/file_fixtures.rb +38 -0
- data/lib/active_support/testing/isolation.rb +56 -87
- data/lib/active_support/testing/method_call_assertions.rb +70 -0
- data/lib/active_support/testing/parallelization/server.rb +82 -0
- data/lib/active_support/testing/parallelization/worker.rb +103 -0
- data/lib/active_support/testing/parallelization.rb +55 -0
- data/lib/active_support/testing/parallelize_executor.rb +76 -0
- data/lib/active_support/testing/setup_and_teardown.rb +30 -10
- data/lib/active_support/testing/stream.rb +41 -0
- data/lib/active_support/testing/tagged_logging.rb +6 -4
- data/lib/active_support/testing/time_helpers.rb +246 -0
- data/lib/active_support/time.rb +13 -13
- data/lib/active_support/time_with_zone.rb +315 -90
- data/lib/active_support/values/time_zone.rb +306 -135
- data/lib/active_support/version.rb +6 -7
- data/lib/active_support/xml_mini/jdom.rb +117 -115
- data/lib/active_support/xml_mini/libxml.rb +22 -21
- data/lib/active_support/xml_mini/libxmlsax.rb +17 -19
- data/lib/active_support/xml_mini/nokogiri.rb +19 -19
- data/lib/active_support/xml_mini/nokogirisax.rb +16 -17
- data/lib/active_support/xml_mini/rexml.rb +25 -17
- data/lib/active_support/xml_mini.rb +67 -56
- data/lib/active_support.rb +58 -3
- metadata +125 -66
- data/lib/active_support/basic_object.rb +0 -11
- data/lib/active_support/buffered_logger.rb +0 -21
- data/lib/active_support/concurrency/latch.rb +0 -27
- data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
- data/lib/active_support/core_ext/array/uniq_by.rb +0 -19
- data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -40
- data/lib/active_support/core_ext/date_time/zones.rb +0 -24
- data/lib/active_support/core_ext/hash/diff.rb +0 -14
- data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
- data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
- data/lib/active_support/core_ext/logger.rb +0 -67
- data/lib/active_support/core_ext/marshal.rb +0 -21
- data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
- data/lib/active_support/core_ext/module/reachable.rb +0 -8
- data/lib/active_support/core_ext/object/to_json.rb +0 -27
- data/lib/active_support/core_ext/proc.rb +0 -17
- data/lib/active_support/core_ext/range/include_range.rb +0 -23
- data/lib/active_support/core_ext/string/encoding.rb +0 -8
- data/lib/active_support/core_ext/struct.rb +0 -6
- data/lib/active_support/core_ext/thread.rb +0 -79
- data/lib/active_support/core_ext/time/marshal.rb +0 -30
- data/lib/active_support/file_watcher.rb +0 -36
- data/lib/active_support/json/variable.rb +0 -18
- data/lib/active_support/testing/pending.rb +0 -14
- data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,117 +1,24 @@
|
|
1
|
-
|
2
|
-
require 'active_support/core_ext/object/blank'
|
3
|
-
require 'active_support/core_ext/hash/keys'
|
4
|
-
require 'active_support/i18n'
|
1
|
+
# frozen_string_literal: true
|
5
2
|
|
6
3
|
module ActiveSupport
|
7
4
|
module NumberHelper
|
8
|
-
extend
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
# of the number of decimal digits (1234 with precision 2 becomes 1200, 1.23543 becomes 1.2)
|
22
|
-
significant: false,
|
23
|
-
# If set, the zeros after the decimal separator will always be stripped (eg.: 1.200 will be 1.2)
|
24
|
-
strip_insignificant_zeros: false
|
25
|
-
},
|
26
|
-
|
27
|
-
# Used in number_to_currency
|
28
|
-
currency: {
|
29
|
-
format: {
|
30
|
-
format: "%u%n",
|
31
|
-
negative_format: "-%u%n",
|
32
|
-
unit: "$",
|
33
|
-
# These five are to override number.format and are optional
|
34
|
-
separator: ".",
|
35
|
-
delimiter: ",",
|
36
|
-
precision: 2,
|
37
|
-
significant: false,
|
38
|
-
strip_insignificant_zeros: false
|
39
|
-
}
|
40
|
-
},
|
41
|
-
|
42
|
-
# Used in number_to_percentage
|
43
|
-
percentage: {
|
44
|
-
format: {
|
45
|
-
delimiter: "",
|
46
|
-
format: "%n%"
|
47
|
-
}
|
48
|
-
},
|
49
|
-
|
50
|
-
# Used in number_to_rounded
|
51
|
-
precision: {
|
52
|
-
format: {
|
53
|
-
delimiter: ""
|
54
|
-
}
|
55
|
-
},
|
56
|
-
|
57
|
-
# Used in number_to_human_size and number_to_human
|
58
|
-
human: {
|
59
|
-
format: {
|
60
|
-
# These five are to override number.format and are optional
|
61
|
-
delimiter: "",
|
62
|
-
precision: 3,
|
63
|
-
significant: true,
|
64
|
-
strip_insignificant_zeros: true
|
65
|
-
},
|
66
|
-
# Used in number_to_human_size
|
67
|
-
storage_units: {
|
68
|
-
# Storage units output formatting.
|
69
|
-
# %u is the storage unit, %n is the number (default: 2 MB)
|
70
|
-
format: "%n %u",
|
71
|
-
units: {
|
72
|
-
byte: "Bytes",
|
73
|
-
kb: "KB",
|
74
|
-
mb: "MB",
|
75
|
-
gb: "GB",
|
76
|
-
tb: "TB"
|
77
|
-
}
|
78
|
-
},
|
79
|
-
# Used in number_to_human
|
80
|
-
decimal_units: {
|
81
|
-
format: "%n %u",
|
82
|
-
# Decimal units output formatting
|
83
|
-
# By default we will only quantify some of the exponents
|
84
|
-
# but the commented ones might be defined or overridden
|
85
|
-
# by the user.
|
86
|
-
units: {
|
87
|
-
# femto: Quadrillionth
|
88
|
-
# pico: Trillionth
|
89
|
-
# nano: Billionth
|
90
|
-
# micro: Millionth
|
91
|
-
# mili: Thousandth
|
92
|
-
# centi: Hundredth
|
93
|
-
# deci: Tenth
|
94
|
-
unit: "",
|
95
|
-
# ten:
|
96
|
-
# one: Ten
|
97
|
-
# other: Tens
|
98
|
-
# hundred: Hundred
|
99
|
-
thousand: "Thousand",
|
100
|
-
million: "Million",
|
101
|
-
billion: "Billion",
|
102
|
-
trillion: "Trillion",
|
103
|
-
quadrillion: "Quadrillion"
|
104
|
-
}
|
105
|
-
}
|
106
|
-
}
|
107
|
-
}
|
108
|
-
|
109
|
-
DECIMAL_UNITS = { 0 => :unit, 1 => :ten, 2 => :hundred, 3 => :thousand, 6 => :million, 9 => :billion, 12 => :trillion, 15 => :quadrillion,
|
110
|
-
-1 => :deci, -2 => :centi, -3 => :mili, -6 => :micro, -9 => :nano, -12 => :pico, -15 => :femto }
|
5
|
+
extend ActiveSupport::Autoload
|
6
|
+
|
7
|
+
eager_autoload do
|
8
|
+
autoload :NumberConverter
|
9
|
+
autoload :RoundingHelper
|
10
|
+
autoload :NumberToRoundedConverter
|
11
|
+
autoload :NumberToDelimitedConverter
|
12
|
+
autoload :NumberToHumanConverter
|
13
|
+
autoload :NumberToHumanSizeConverter
|
14
|
+
autoload :NumberToPhoneConverter
|
15
|
+
autoload :NumberToCurrencyConverter
|
16
|
+
autoload :NumberToPercentageConverter
|
17
|
+
end
|
111
18
|
|
112
|
-
|
19
|
+
extend self
|
113
20
|
|
114
|
-
# Formats a +number+ into a
|
21
|
+
# Formats a +number+ into a phone number (US by default e.g., (555)
|
115
22
|
# 123-9876). You can customize the format in the +options+ hash.
|
116
23
|
#
|
117
24
|
# ==== Options
|
@@ -123,52 +30,49 @@ module ActiveSupport
|
|
123
30
|
# end of the generated number.
|
124
31
|
# * <tt>:country_code</tt> - Sets the country code for the phone
|
125
32
|
# number.
|
33
|
+
# * <tt>:pattern</tt> - Specifies how the number is divided into three
|
34
|
+
# groups with the custom regexp to override the default format.
|
126
35
|
# ==== Examples
|
127
36
|
#
|
128
|
-
# number_to_phone(5551234) # => 555-1234
|
129
|
-
# number_to_phone('5551234') # => 555-1234
|
130
|
-
# number_to_phone(1235551234) # => 123-555-1234
|
131
|
-
# number_to_phone(1235551234, area_code: true) # => (123) 555-1234
|
132
|
-
# number_to_phone(1235551234, delimiter: ' ') # => 123 555 1234
|
133
|
-
# number_to_phone(1235551234, area_code: true, extension: 555) # => (123) 555-1234 x 555
|
134
|
-
# number_to_phone(1235551234, country_code: 1) # => +1-123-555-1234
|
135
|
-
# number_to_phone('123a456') # => 123a456
|
37
|
+
# number_to_phone(5551234) # => "555-1234"
|
38
|
+
# number_to_phone('5551234') # => "555-1234"
|
39
|
+
# number_to_phone(1235551234) # => "123-555-1234"
|
40
|
+
# number_to_phone(1235551234, area_code: true) # => "(123) 555-1234"
|
41
|
+
# number_to_phone(1235551234, delimiter: ' ') # => "123 555 1234"
|
42
|
+
# number_to_phone(1235551234, area_code: true, extension: 555) # => "(123) 555-1234 x 555"
|
43
|
+
# number_to_phone(1235551234, country_code: 1) # => "+1-123-555-1234"
|
44
|
+
# number_to_phone('123a456') # => "123a456"
|
136
45
|
#
|
137
46
|
# number_to_phone(1235551234, country_code: 1, extension: 1343, delimiter: '.')
|
138
|
-
# # => +1.123.555.1234 x 1343
|
47
|
+
# # => "+1.123.555.1234 x 1343"
|
48
|
+
#
|
49
|
+
# number_to_phone(75561234567, pattern: /(\d{1,4})(\d{4})(\d{4})$/, area_code: true)
|
50
|
+
# # => "(755) 6123-4567"
|
51
|
+
# number_to_phone(13312345678, pattern: /(\d{3})(\d{4})(\d{4})$/)
|
52
|
+
# # => "133-1234-5678"
|
139
53
|
def number_to_phone(number, options = {})
|
140
|
-
|
141
|
-
options = options.symbolize_keys
|
142
|
-
|
143
|
-
number = number.to_s.strip
|
144
|
-
area_code = options[:area_code]
|
145
|
-
delimiter = options[:delimiter] || "-"
|
146
|
-
extension = options[:extension]
|
147
|
-
country_code = options[:country_code]
|
148
|
-
|
149
|
-
if area_code
|
150
|
-
number.gsub!(/(\d{1,3})(\d{3})(\d{4}$)/,"(\\1) \\2#{delimiter}\\3")
|
151
|
-
else
|
152
|
-
number.gsub!(/(\d{0,3})(\d{3})(\d{4})$/,"\\1#{delimiter}\\2#{delimiter}\\3")
|
153
|
-
number.slice!(0, 1) if number.start_with?(delimiter) && !delimiter.blank?
|
154
|
-
end
|
155
|
-
|
156
|
-
str = ''
|
157
|
-
str << "+#{country_code}#{delimiter}" unless country_code.blank?
|
158
|
-
str << number
|
159
|
-
str << " x #{extension}" unless extension.blank?
|
160
|
-
str
|
54
|
+
NumberToPhoneConverter.convert(number, options)
|
161
55
|
end
|
162
56
|
|
163
57
|
# Formats a +number+ into a currency string (e.g., $13.65). You
|
164
58
|
# can customize the format in the +options+ hash.
|
165
59
|
#
|
60
|
+
# The currency unit and number formatting of the current locale will be used
|
61
|
+
# unless otherwise specified in the provided options. No currency conversion
|
62
|
+
# is performed. If the user is given a way to change their locale, they will
|
63
|
+
# also be able to change the relative value of the currency displayed with
|
64
|
+
# this helper. If your application will ever support multiple locales, you
|
65
|
+
# may want to specify a constant <tt>:locale</tt> option or consider
|
66
|
+
# using a library capable of currency conversion.
|
67
|
+
#
|
166
68
|
# ==== Options
|
167
69
|
#
|
168
70
|
# * <tt>:locale</tt> - Sets the locale to be used for formatting
|
169
71
|
# (defaults to current locale).
|
170
72
|
# * <tt>:precision</tt> - Sets the level of precision (defaults
|
171
73
|
# to 2).
|
74
|
+
# * <tt>:round_mode</tt> - Determine how rounding is performed
|
75
|
+
# (defaults to :default. See BigDecimal::mode)
|
172
76
|
# * <tt>:unit</tt> - Sets the denomination of the currency
|
173
77
|
# (defaults to "$").
|
174
78
|
# * <tt>:separator</tt> - Sets the separator between the units
|
@@ -179,45 +83,36 @@ module ActiveSupport
|
|
179
83
|
# (defaults to "%u%n"). Fields are <tt>%u</tt> for the
|
180
84
|
# currency, and <tt>%n</tt> for the number.
|
181
85
|
# * <tt>:negative_format</tt> - Sets the format for negative
|
182
|
-
# numbers (defaults to prepending
|
86
|
+
# numbers (defaults to prepending a hyphen to the formatted
|
183
87
|
# number given by <tt>:format</tt>). Accepts the same fields
|
184
88
|
# than <tt>:format</tt>, except <tt>%n</tt> is here the
|
185
89
|
# absolute value of the number.
|
90
|
+
# * <tt>:strip_insignificant_zeros</tt> - If +true+ removes
|
91
|
+
# insignificant zeros after the decimal separator (defaults to
|
92
|
+
# +false+).
|
186
93
|
#
|
187
94
|
# ==== Examples
|
188
95
|
#
|
189
|
-
# number_to_currency(1234567890.50) # => $1,234,567,890.50
|
190
|
-
# number_to_currency(1234567890.506) # => $1,234,567,890.51
|
191
|
-
# number_to_currency(1234567890.506, precision: 3) # => $1,234,567,890.506
|
192
|
-
# number_to_currency(1234567890.506, locale: :fr) # => 1 234 567 890,51 €
|
193
|
-
# number_to_currency('123a456') # => $123a456
|
96
|
+
# number_to_currency(1234567890.50) # => "$1,234,567,890.50"
|
97
|
+
# number_to_currency(1234567890.506) # => "$1,234,567,890.51"
|
98
|
+
# number_to_currency(1234567890.506, precision: 3) # => "$1,234,567,890.506"
|
99
|
+
# number_to_currency(1234567890.506, locale: :fr) # => "1 234 567 890,51 €"
|
100
|
+
# number_to_currency('123a456') # => "$123a456"
|
194
101
|
#
|
102
|
+
# number_to_currency(-0.456789, precision: 0)
|
103
|
+
# # => "$0"
|
195
104
|
# number_to_currency(-1234567890.50, negative_format: '(%u%n)')
|
196
|
-
# # => ($1,234,567,890.50)
|
105
|
+
# # => "($1,234,567,890.50)"
|
197
106
|
# number_to_currency(1234567890.50, unit: '£', separator: ',', delimiter: '')
|
198
|
-
# # => £1234567890,50
|
107
|
+
# # => "£1234567890,50"
|
199
108
|
# number_to_currency(1234567890.50, unit: '£', separator: ',', delimiter: '', format: '%n %u')
|
200
|
-
# # => 1234567890,50 £
|
109
|
+
# # => "1234567890,50 £"
|
110
|
+
# number_to_currency(1234567890.50, strip_insignificant_zeros: true)
|
111
|
+
# # => "$1,234,567,890.5"
|
112
|
+
# number_to_currency(1234567890.50, precision: 0, round_mode: :up)
|
113
|
+
# # => "$1,234,567,891"
|
201
114
|
def number_to_currency(number, options = {})
|
202
|
-
|
203
|
-
options = options.symbolize_keys
|
204
|
-
|
205
|
-
currency = i18n_format_options(options[:locale], :currency)
|
206
|
-
currency[:negative_format] ||= "-" + currency[:format] if currency[:format]
|
207
|
-
|
208
|
-
defaults = default_format_options(:currency).merge!(currency)
|
209
|
-
defaults[:negative_format] = "-" + options[:format] if options[:format]
|
210
|
-
options = defaults.merge!(options)
|
211
|
-
|
212
|
-
unit = options.delete(:unit)
|
213
|
-
format = options.delete(:format)
|
214
|
-
|
215
|
-
if number.to_f.phase != 0
|
216
|
-
format = options.delete(:negative_format)
|
217
|
-
number = number.respond_to?("abs") ? number.abs : number.sub(/^-/, '')
|
218
|
-
end
|
219
|
-
|
220
|
-
format.gsub('%n', self.number_to_rounded(number, options)).gsub('%u', unit)
|
115
|
+
NumberToCurrencyConverter.convert(number, options)
|
221
116
|
end
|
222
117
|
|
223
118
|
# Formats a +number+ as a percentage string (e.g., 65%). You can
|
@@ -228,9 +123,11 @@ module ActiveSupport
|
|
228
123
|
# * <tt>:locale</tt> - Sets the locale to be used for formatting
|
229
124
|
# (defaults to current locale).
|
230
125
|
# * <tt>:precision</tt> - Sets the precision of the number
|
231
|
-
# (defaults to 3).
|
232
|
-
# * <tt>:
|
233
|
-
#
|
126
|
+
# (defaults to 3). Keeps the number's precision if +nil+.
|
127
|
+
# * <tt>:round_mode</tt> - Determine how rounding is performed
|
128
|
+
# (defaults to :default. See BigDecimal::mode)
|
129
|
+
# * <tt>:significant</tt> - If +true+, precision will be the number
|
130
|
+
# of significant_digits. If +false+, the number of fractional
|
234
131
|
# digits (defaults to +false+).
|
235
132
|
# * <tt>:separator</tt> - Sets the separator between the
|
236
133
|
# fractional and integer digits (defaults to ".").
|
@@ -244,23 +141,18 @@ module ActiveSupport
|
|
244
141
|
#
|
245
142
|
# ==== Examples
|
246
143
|
#
|
247
|
-
# number_to_percentage(100)
|
248
|
-
# number_to_percentage('98')
|
249
|
-
# number_to_percentage(100, precision: 0)
|
250
|
-
# number_to_percentage(1000, delimiter: '.', separator: ',')
|
251
|
-
# number_to_percentage(302.24398923423, precision: 5)
|
252
|
-
# number_to_percentage(1000, locale: :fr)
|
253
|
-
# number_to_percentage(
|
254
|
-
# number_to_percentage(
|
144
|
+
# number_to_percentage(100) # => "100.000%"
|
145
|
+
# number_to_percentage('98') # => "98.000%"
|
146
|
+
# number_to_percentage(100, precision: 0) # => "100%"
|
147
|
+
# number_to_percentage(1000, delimiter: '.', separator: ',') # => "1.000,000%"
|
148
|
+
# number_to_percentage(302.24398923423, precision: 5) # => "302.24399%"
|
149
|
+
# number_to_percentage(1000, locale: :fr) # => "1000,000%"
|
150
|
+
# number_to_percentage(1000, precision: nil) # => "1000%"
|
151
|
+
# number_to_percentage('98a') # => "98a%"
|
152
|
+
# number_to_percentage(100, format: '%n %') # => "100.000 %"
|
153
|
+
# number_to_percentage(302.24398923423, precision: 5, round_mode: :down) # => "302.24398%"
|
255
154
|
def number_to_percentage(number, options = {})
|
256
|
-
|
257
|
-
options = options.symbolize_keys
|
258
|
-
|
259
|
-
defaults = format_options(options[:locale], :percentage)
|
260
|
-
options = defaults.merge!(options)
|
261
|
-
|
262
|
-
format = options[:format] || "%n%"
|
263
|
-
format.gsub('%n', self.number_to_rounded(number, options))
|
155
|
+
NumberToPercentageConverter.convert(number, options)
|
264
156
|
end
|
265
157
|
|
266
158
|
# Formats a +number+ with grouped thousands using +delimiter+
|
@@ -275,29 +167,27 @@ module ActiveSupport
|
|
275
167
|
# to ",").
|
276
168
|
# * <tt>:separator</tt> - Sets the separator between the
|
277
169
|
# fractional and integer digits (defaults to ".").
|
170
|
+
# * <tt>:delimiter_pattern</tt> - Sets a custom regular expression used for
|
171
|
+
# deriving the placement of delimiter. Helpful when using currency formats
|
172
|
+
# like INR.
|
278
173
|
#
|
279
174
|
# ==== Examples
|
280
175
|
#
|
281
|
-
# number_to_delimited(12345678) # => 12,345,678
|
282
|
-
# number_to_delimited('123456') # => 123,456
|
283
|
-
# number_to_delimited(12345678.05) # => 12,345,678.05
|
284
|
-
# number_to_delimited(12345678, delimiter: '.') # => 12.345.678
|
285
|
-
# number_to_delimited(12345678, delimiter: ',') # => 12,345,678
|
286
|
-
# number_to_delimited(12345678.05, separator: ' ') # => 12,345,678 05
|
287
|
-
# number_to_delimited(12345678.05, locale: :fr) # => 12 345 678,05
|
288
|
-
# number_to_delimited('112a') # => 112a
|
176
|
+
# number_to_delimited(12345678) # => "12,345,678"
|
177
|
+
# number_to_delimited('123456') # => "123,456"
|
178
|
+
# number_to_delimited(12345678.05) # => "12,345,678.05"
|
179
|
+
# number_to_delimited(12345678, delimiter: '.') # => "12.345.678"
|
180
|
+
# number_to_delimited(12345678, delimiter: ',') # => "12,345,678"
|
181
|
+
# number_to_delimited(12345678.05, separator: ' ') # => "12,345,678 05"
|
182
|
+
# number_to_delimited(12345678.05, locale: :fr) # => "12 345 678,05"
|
183
|
+
# number_to_delimited('112a') # => "112a"
|
289
184
|
# number_to_delimited(98765432.98, delimiter: ' ', separator: ',')
|
290
|
-
#
|
185
|
+
# # => "98 765 432,98"
|
186
|
+
# number_to_delimited("123456.78",
|
187
|
+
# delimiter_pattern: /(\d+?)(?=(\d\d)+(\d)(?!\d))/)
|
188
|
+
# # => "1,23,456.78"
|
291
189
|
def number_to_delimited(number, options = {})
|
292
|
-
|
293
|
-
|
294
|
-
return number unless valid_float?(number)
|
295
|
-
|
296
|
-
options = format_options(options[:locale]).merge!(options)
|
297
|
-
|
298
|
-
parts = number.to_s.split('.')
|
299
|
-
parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{options[:delimiter]}")
|
300
|
-
parts.join(options[:separator])
|
190
|
+
NumberToDelimitedConverter.convert(number, options)
|
301
191
|
end
|
302
192
|
|
303
193
|
# Formats a +number+ with the specified level of
|
@@ -310,9 +200,11 @@ module ActiveSupport
|
|
310
200
|
# * <tt>:locale</tt> - Sets the locale to be used for formatting
|
311
201
|
# (defaults to current locale).
|
312
202
|
# * <tt>:precision</tt> - Sets the precision of the number
|
313
|
-
# (defaults to 3).
|
314
|
-
# * <tt>:
|
315
|
-
#
|
203
|
+
# (defaults to 3). Keeps the number's precision if +nil+.
|
204
|
+
# * <tt>:round_mode</tt> - Determine how rounding is performed
|
205
|
+
# (defaults to :default. See BigDecimal::mode)
|
206
|
+
# * <tt>:significant</tt> - If +true+, precision will be the number
|
207
|
+
# of significant_digits. If +false+, the number of fractional
|
316
208
|
# digits (defaults to +false+).
|
317
209
|
# * <tt>:separator</tt> - Sets the separator between the
|
318
210
|
# fractional and integer digits (defaults to ".").
|
@@ -324,59 +216,29 @@ module ActiveSupport
|
|
324
216
|
#
|
325
217
|
# ==== Examples
|
326
218
|
#
|
327
|
-
# number_to_rounded(111.2345) # => 111.235
|
328
|
-
# number_to_rounded(111.2345, precision: 2) # => 111.23
|
329
|
-
# number_to_rounded(13, precision: 5) # => 13.00000
|
330
|
-
# number_to_rounded(389.32314, precision: 0) # => 389
|
331
|
-
# number_to_rounded(111.2345, significant: true) # => 111
|
332
|
-
# number_to_rounded(111.2345, precision: 1, significant: true) # => 100
|
333
|
-
# number_to_rounded(13, precision: 5, significant: true) # => 13.000
|
334
|
-
# number_to_rounded(
|
219
|
+
# number_to_rounded(111.2345) # => "111.235"
|
220
|
+
# number_to_rounded(111.2345, precision: 2) # => "111.23"
|
221
|
+
# number_to_rounded(13, precision: 5) # => "13.00000"
|
222
|
+
# number_to_rounded(389.32314, precision: 0) # => "389"
|
223
|
+
# number_to_rounded(111.2345, significant: true) # => "111"
|
224
|
+
# number_to_rounded(111.2345, precision: 1, significant: true) # => "100"
|
225
|
+
# number_to_rounded(13, precision: 5, significant: true) # => "13.000"
|
226
|
+
# number_to_rounded(13, precision: nil) # => "13"
|
227
|
+
# number_to_rounded(389.32314, precision: 0, round_mode: :up) # => "390"
|
228
|
+
# number_to_rounded(111.234, locale: :fr) # => "111,234"
|
335
229
|
#
|
336
230
|
# number_to_rounded(13, precision: 5, significant: true, strip_insignificant_zeros: true)
|
337
|
-
# # => 13
|
231
|
+
# # => "13"
|
338
232
|
#
|
339
|
-
# number_to_rounded(389.32314, precision: 4, significant: true) # => 389.3
|
233
|
+
# number_to_rounded(389.32314, precision: 4, significant: true) # => "389.3"
|
340
234
|
# number_to_rounded(1111.2345, precision: 2, separator: ',', delimiter: '.')
|
341
|
-
# # => 1.111,23
|
235
|
+
# # => "1.111,23"
|
342
236
|
def number_to_rounded(number, options = {})
|
343
|
-
|
344
|
-
number = Float(number)
|
345
|
-
options = options.symbolize_keys
|
346
|
-
|
347
|
-
defaults = format_options(options[:locale], :precision)
|
348
|
-
options = defaults.merge!(options)
|
349
|
-
|
350
|
-
precision = options.delete :precision
|
351
|
-
significant = options.delete :significant
|
352
|
-
strip_insignificant_zeros = options.delete :strip_insignificant_zeros
|
353
|
-
|
354
|
-
if significant && precision > 0
|
355
|
-
if number == 0
|
356
|
-
digits, rounded_number = 1, 0
|
357
|
-
else
|
358
|
-
digits = (Math.log10(number.abs) + 1).floor
|
359
|
-
multiplier = 10 ** (digits - precision)
|
360
|
-
rounded_number = (BigDecimal.new(number.to_s) / BigDecimal.new(multiplier.to_f.to_s)).round.to_f * multiplier
|
361
|
-
digits = (Math.log10(rounded_number.abs) + 1).floor # After rounding, the number of digits may have changed
|
362
|
-
end
|
363
|
-
precision -= digits
|
364
|
-
precision = 0 if precision < 0 # don't let it be negative
|
365
|
-
else
|
366
|
-
rounded_number = BigDecimal.new(number.to_s).round(precision).to_f
|
367
|
-
rounded_number = rounded_number.abs if rounded_number.zero? # prevent showing negative zeros
|
368
|
-
end
|
369
|
-
formatted_number = self.number_to_delimited("%01.#{precision}f" % rounded_number, options)
|
370
|
-
if strip_insignificant_zeros
|
371
|
-
escaped_separator = Regexp.escape(options[:separator])
|
372
|
-
formatted_number.sub(/(#{escaped_separator})(\d*[1-9])?0+\z/, '\1\2').sub(/#{escaped_separator}\z/, '')
|
373
|
-
else
|
374
|
-
formatted_number
|
375
|
-
end
|
237
|
+
NumberToRoundedConverter.convert(number, options)
|
376
238
|
end
|
377
239
|
|
378
240
|
# Formats the bytes in +number+ into a more understandable
|
379
|
-
# representation (e.g., giving it 1500 yields 1.
|
241
|
+
# representation (e.g., giving it 1500 yields 1.46 KB). This
|
380
242
|
# method is useful for reporting file sizes to users. You can
|
381
243
|
# customize the format in the +options+ hash.
|
382
244
|
#
|
@@ -389,8 +251,10 @@ module ActiveSupport
|
|
389
251
|
# (defaults to current locale).
|
390
252
|
# * <tt>:precision</tt> - Sets the precision of the number
|
391
253
|
# (defaults to 3).
|
392
|
-
# * <tt>:
|
393
|
-
#
|
254
|
+
# * <tt>:round_mode</tt> - Determine how rounding is performed
|
255
|
+
# (defaults to :default. See BigDecimal::mode)
|
256
|
+
# * <tt>:significant</tt> - If +true+, precision will be the number
|
257
|
+
# of significant_digits. If +false+, the number of fractional
|
394
258
|
# digits (defaults to +true+)
|
395
259
|
# * <tt>:separator</tt> - Sets the separator between the
|
396
260
|
# fractional and integer digits (defaults to ".").
|
@@ -399,61 +263,29 @@ module ActiveSupport
|
|
399
263
|
# * <tt>:strip_insignificant_zeros</tt> - If +true+ removes
|
400
264
|
# insignificant zeros after the decimal separator (defaults to
|
401
265
|
# +true+)
|
402
|
-
# * <tt>:prefix</tt> - If +:si+ formats the number using the SI
|
403
|
-
# prefix (defaults to :binary)
|
404
266
|
#
|
405
267
|
# ==== Examples
|
406
268
|
#
|
407
|
-
# number_to_human_size(123) # => 123 Bytes
|
408
|
-
# number_to_human_size(1234) # => 1.21 KB
|
409
|
-
# number_to_human_size(12345) # => 12.1 KB
|
410
|
-
# number_to_human_size(1234567) # => 1.18 MB
|
411
|
-
# number_to_human_size(1234567890) # => 1.15 GB
|
412
|
-
# number_to_human_size(1234567890123) # => 1.12 TB
|
413
|
-
# number_to_human_size(
|
414
|
-
# number_to_human_size(
|
415
|
-
# number_to_human_size(1234567, precision: 2
|
416
|
-
#
|
417
|
-
#
|
418
|
-
#
|
419
|
-
#
|
420
|
-
# number_to_human_size(
|
421
|
-
# number_to_human_size(524288000, precision: 5) # => "500 MB"
|
269
|
+
# number_to_human_size(123) # => "123 Bytes"
|
270
|
+
# number_to_human_size(1234) # => "1.21 KB"
|
271
|
+
# number_to_human_size(12345) # => "12.1 KB"
|
272
|
+
# number_to_human_size(1234567) # => "1.18 MB"
|
273
|
+
# number_to_human_size(1234567890) # => "1.15 GB"
|
274
|
+
# number_to_human_size(1234567890123) # => "1.12 TB"
|
275
|
+
# number_to_human_size(1234567890123456) # => "1.1 PB"
|
276
|
+
# number_to_human_size(1234567890123456789) # => "1.07 EB"
|
277
|
+
# number_to_human_size(1234567, precision: 2) # => "1.2 MB"
|
278
|
+
# number_to_human_size(483989, precision: 2) # => "470 KB"
|
279
|
+
# number_to_human_size(483989, precision: 2, round_mode: :up) # => "480 KB"
|
280
|
+
# number_to_human_size(1234567, precision: 2, separator: ',') # => "1,2 MB"
|
281
|
+
# number_to_human_size(1234567890123, precision: 5) # => "1.1228 TB"
|
282
|
+
# number_to_human_size(524288000, precision: 5) # => "500 MB"
|
422
283
|
def number_to_human_size(number, options = {})
|
423
|
-
|
424
|
-
|
425
|
-
return number unless valid_float?(number)
|
426
|
-
number = Float(number)
|
427
|
-
|
428
|
-
defaults = format_options(options[:locale], :human)
|
429
|
-
options = defaults.merge!(options)
|
430
|
-
|
431
|
-
#for backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files
|
432
|
-
options[:strip_insignificant_zeros] = true if not options.key?(:strip_insignificant_zeros)
|
433
|
-
|
434
|
-
storage_units_format = translate_number_value_with_default('human.storage_units.format', :locale => options[:locale], :raise => true)
|
435
|
-
|
436
|
-
base = options[:prefix] == :si ? 1000 : 1024
|
437
|
-
|
438
|
-
if number.to_i < base
|
439
|
-
unit = translate_number_value_with_default('human.storage_units.units.byte', :locale => options[:locale], :count => number.to_i, :raise => true)
|
440
|
-
storage_units_format.gsub(/%n/, number.to_i.to_s).gsub(/%u/, unit)
|
441
|
-
else
|
442
|
-
max_exp = STORAGE_UNITS.size - 1
|
443
|
-
exponent = (Math.log(number) / Math.log(base)).to_i # Convert to base
|
444
|
-
exponent = max_exp if exponent > max_exp # we need this to avoid overflow for the highest unit
|
445
|
-
number /= base ** exponent
|
446
|
-
|
447
|
-
unit_key = STORAGE_UNITS[exponent]
|
448
|
-
unit = translate_number_value_with_default("human.storage_units.units.#{unit_key}", :locale => options[:locale], :count => number, :raise => true)
|
449
|
-
|
450
|
-
formatted_number = self.number_to_rounded(number, options)
|
451
|
-
storage_units_format.gsub(/%n/, formatted_number).gsub(/%u/, unit)
|
452
|
-
end
|
284
|
+
NumberToHumanSizeConverter.convert(number, options)
|
453
285
|
end
|
454
286
|
|
455
287
|
# Pretty prints (formats and approximates) a number in a way it
|
456
|
-
# is more readable by humans (
|
288
|
+
# is more readable by humans (e.g.: 1200000000 becomes "1.2
|
457
289
|
# Billion"). This is useful for numbers that can get very large
|
458
290
|
# (and too hard to read).
|
459
291
|
#
|
@@ -461,7 +293,7 @@ module ActiveSupport
|
|
461
293
|
# size.
|
462
294
|
#
|
463
295
|
# You can also define your own unit-quantifier names if you want
|
464
|
-
# to use other decimal units (
|
296
|
+
# to use other decimal units (e.g.: 1500 becomes "1.5
|
465
297
|
# kilometers", 0.150 becomes "150 milliliters", etc). You may
|
466
298
|
# define a wide range of unit quantifiers, even fractional ones
|
467
299
|
# (centi, deci, mili, etc).
|
@@ -472,8 +304,10 @@ module ActiveSupport
|
|
472
304
|
# (defaults to current locale).
|
473
305
|
# * <tt>:precision</tt> - Sets the precision of the number
|
474
306
|
# (defaults to 3).
|
475
|
-
# * <tt>:
|
476
|
-
#
|
307
|
+
# * <tt>:round_mode</tt> - Determine how rounding is performed
|
308
|
+
# (defaults to :default. See BigDecimal::mode)
|
309
|
+
# * <tt>:significant</tt> - If +true+, precision will be the number
|
310
|
+
# of significant_digits. If +false+, the number of fractional
|
477
311
|
# digits (defaults to +true+)
|
478
312
|
# * <tt>:separator</tt> - Sets the separator between the
|
479
313
|
# fractional and integer digits (defaults to ".").
|
@@ -486,12 +320,12 @@ module ActiveSupport
|
|
486
320
|
# string containing an i18n scope where to find this hash. It
|
487
321
|
# might have the following keys:
|
488
322
|
# * *integers*: <tt>:unit</tt>, <tt>:ten</tt>,
|
489
|
-
#
|
490
|
-
#
|
491
|
-
#
|
323
|
+
# <tt>:hundred</tt>, <tt>:thousand</tt>, <tt>:million</tt>,
|
324
|
+
# <tt>:billion</tt>, <tt>:trillion</tt>,
|
325
|
+
# <tt>:quadrillion</tt>
|
492
326
|
# * *fractionals*: <tt>:deci</tt>, <tt>:centi</tt>,
|
493
|
-
#
|
494
|
-
#
|
327
|
+
# <tt>:mili</tt>, <tt>:micro</tt>, <tt>:nano</tt>,
|
328
|
+
# <tt>:pico</tt>, <tt>:femto</tt>
|
495
329
|
# * <tt>:format</tt> - Sets the format of the output string
|
496
330
|
# (defaults to "%n %u"). The field types are:
|
497
331
|
# * %u - The quantifier (ex.: 'thousand')
|
@@ -509,18 +343,23 @@ module ActiveSupport
|
|
509
343
|
# number_to_human(1234567890123456789) # => "1230 Quadrillion"
|
510
344
|
# number_to_human(489939, precision: 2) # => "490 Thousand"
|
511
345
|
# number_to_human(489939, precision: 4) # => "489.9 Thousand"
|
346
|
+
# number_to_human(489939, precision: 2
|
347
|
+
# , round_mode: :down) # => "480 Thousand"
|
512
348
|
# number_to_human(1234567, precision: 4,
|
513
349
|
# significant: false) # => "1.2346 Million"
|
514
350
|
# number_to_human(1234567, precision: 1,
|
515
351
|
# separator: ',',
|
516
352
|
# significant: false) # => "1,2 Million"
|
517
353
|
#
|
354
|
+
# number_to_human(500000000, precision: 5) # => "500 Million"
|
355
|
+
# number_to_human(12345012345, significant: false) # => "12.345 Billion"
|
356
|
+
#
|
518
357
|
# Non-significant zeros after the decimal separator are stripped
|
519
358
|
# out by default (set <tt>:strip_insignificant_zeros</tt> to
|
520
359
|
# +false+ to change that):
|
521
360
|
#
|
522
|
-
#
|
523
|
-
#
|
361
|
+
# number_to_human(12.00001) # => "12"
|
362
|
+
# number_to_human(12.00001, strip_insignificant_zeros: false) # => "12.0"
|
524
363
|
#
|
525
364
|
# ==== Custom Unit Quantifiers
|
526
365
|
#
|
@@ -550,88 +389,7 @@ module ActiveSupport
|
|
550
389
|
# number_to_human(1, units: :distance) # => "1 meter"
|
551
390
|
# number_to_human(0.34, units: :distance) # => "34 centimeters"
|
552
391
|
def number_to_human(number, options = {})
|
553
|
-
|
554
|
-
|
555
|
-
return number unless valid_float?(number)
|
556
|
-
number = Float(number)
|
557
|
-
|
558
|
-
defaults = format_options(options[:locale], :human)
|
559
|
-
options = defaults.merge!(options)
|
560
|
-
|
561
|
-
#for backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files
|
562
|
-
options[:strip_insignificant_zeros] = true if not options.key?(:strip_insignificant_zeros)
|
563
|
-
|
564
|
-
inverted_du = DECIMAL_UNITS.invert
|
565
|
-
|
566
|
-
units = options.delete :units
|
567
|
-
unit_exponents = case units
|
568
|
-
when Hash
|
569
|
-
units
|
570
|
-
when String, Symbol
|
571
|
-
I18n.translate(:"#{units}", :locale => options[:locale], :raise => true)
|
572
|
-
when nil
|
573
|
-
translate_number_value_with_default("human.decimal_units.units", :locale => options[:locale], :raise => true)
|
574
|
-
else
|
575
|
-
raise ArgumentError, ":units must be a Hash or String translation scope."
|
576
|
-
end.keys.map{|e_name| inverted_du[e_name] }.sort_by{|e| -e}
|
577
|
-
|
578
|
-
number_exponent = number != 0 ? Math.log10(number.abs).floor : 0
|
579
|
-
display_exponent = unit_exponents.find{ |e| number_exponent >= e } || 0
|
580
|
-
number /= 10 ** display_exponent
|
581
|
-
|
582
|
-
unit = case units
|
583
|
-
when Hash
|
584
|
-
units[DECIMAL_UNITS[display_exponent]] || ''
|
585
|
-
when String, Symbol
|
586
|
-
I18n.translate(:"#{units}.#{DECIMAL_UNITS[display_exponent]}", :locale => options[:locale], :count => number.to_i)
|
587
|
-
else
|
588
|
-
translate_number_value_with_default("human.decimal_units.units.#{DECIMAL_UNITS[display_exponent]}", :locale => options[:locale], :count => number.to_i)
|
589
|
-
end
|
590
|
-
|
591
|
-
decimal_format = options[:format] || translate_number_value_with_default('human.decimal_units.format', :locale => options[:locale])
|
592
|
-
formatted_number = self.number_to_rounded(number, options)
|
593
|
-
decimal_format.gsub(/%n/, formatted_number).gsub(/%u/, unit).strip
|
594
|
-
end
|
595
|
-
|
596
|
-
def self.private_module_and_instance_method(method_name) #:nodoc:
|
597
|
-
private method_name
|
598
|
-
private_class_method method_name
|
599
|
-
end
|
600
|
-
private_class_method :private_module_and_instance_method
|
601
|
-
|
602
|
-
def format_options(locale, namespace = nil) #:nodoc:
|
603
|
-
default_format_options(namespace).merge!(i18n_format_options(locale, namespace))
|
604
|
-
end
|
605
|
-
private_module_and_instance_method :format_options
|
606
|
-
|
607
|
-
def default_format_options(namespace = nil) #:nodoc:
|
608
|
-
options = DEFAULTS[:format].dup
|
609
|
-
options.merge!(DEFAULTS[namespace][:format]) if namespace
|
610
|
-
options
|
611
|
-
end
|
612
|
-
private_module_and_instance_method :default_format_options
|
613
|
-
|
614
|
-
def i18n_format_options(locale, namespace = nil) #:nodoc:
|
615
|
-
options = I18n.translate(:'number.format', locale: locale, default: {}).dup
|
616
|
-
if namespace
|
617
|
-
options.merge!(I18n.translate(:"number.#{namespace}.format", locale: locale, default: {}))
|
618
|
-
end
|
619
|
-
options
|
620
|
-
end
|
621
|
-
private_module_and_instance_method :i18n_format_options
|
622
|
-
|
623
|
-
def translate_number_value_with_default(key, i18n_options = {}) #:nodoc:
|
624
|
-
default = key.split('.').reduce(DEFAULTS) { |defaults, k| defaults[k.to_sym] }
|
625
|
-
|
626
|
-
I18n.translate(key, { default: default, scope: :number }.merge!(i18n_options))
|
627
|
-
end
|
628
|
-
private_module_and_instance_method :translate_number_value_with_default
|
629
|
-
|
630
|
-
def valid_float?(number) #:nodoc:
|
631
|
-
Float(number)
|
632
|
-
rescue ArgumentError, TypeError
|
633
|
-
false
|
392
|
+
NumberToHumanConverter.convert(number, options)
|
634
393
|
end
|
635
|
-
private_module_and_instance_method :valid_float?
|
636
394
|
end
|
637
395
|
end
|