activesupport 6.1.7.2 → 7.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +866 -411
- data/MIT-LICENSE +1 -1
- data/README.rdoc +6 -6
- data/lib/active_support/actionable_error.rb +4 -2
- data/lib/active_support/array_inquirer.rb +2 -2
- data/lib/active_support/backtrace_cleaner.rb +27 -7
- data/lib/active_support/benchmarkable.rb +3 -2
- data/lib/active_support/broadcast_logger.rb +250 -0
- data/lib/active_support/builder.rb +1 -1
- data/lib/active_support/cache/coder.rb +153 -0
- data/lib/active_support/cache/entry.rb +134 -0
- data/lib/active_support/cache/file_store.rb +52 -19
- data/lib/active_support/cache/mem_cache_store.rb +195 -60
- data/lib/active_support/cache/memory_store.rb +86 -24
- data/lib/active_support/cache/null_store.rb +16 -2
- data/lib/active_support/cache/redis_cache_store.rb +186 -193
- data/lib/active_support/cache/serializer_with_fallback.rb +175 -0
- data/lib/active_support/cache/strategy/local_cache.rb +63 -71
- data/lib/active_support/cache.rb +478 -247
- data/lib/active_support/callbacks.rb +227 -105
- data/lib/active_support/code_generator.rb +65 -0
- data/lib/active_support/concern.rb +9 -7
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +44 -7
- data/lib/active_support/concurrency/null_lock.rb +13 -0
- data/lib/active_support/concurrency/share_lock.rb +2 -2
- data/lib/active_support/configurable.rb +18 -5
- data/lib/active_support/configuration_file.rb +1 -1
- data/lib/active_support/core_ext/array/access.rb +1 -5
- data/lib/active_support/core_ext/array/conversions.rb +15 -13
- data/lib/active_support/core_ext/array/grouping.rb +6 -6
- data/lib/active_support/core_ext/array/inquiry.rb +2 -2
- data/lib/active_support/core_ext/big_decimal/conversions.rb +1 -1
- data/lib/active_support/core_ext/class/subclasses.rb +37 -26
- data/lib/active_support/core_ext/date/blank.rb +1 -1
- data/lib/active_support/core_ext/date/calculations.rb +24 -9
- data/lib/active_support/core_ext/date/conversions.rb +16 -15
- data/lib/active_support/core_ext/date_and_time/calculations.rb +14 -4
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +1 -1
- data/lib/active_support/core_ext/date_time/blank.rb +1 -1
- data/lib/active_support/core_ext/date_time/calculations.rb +4 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +19 -15
- data/lib/active_support/core_ext/digest/uuid.rb +30 -14
- data/lib/active_support/core_ext/enumerable.rb +85 -83
- data/lib/active_support/core_ext/erb/util.rb +196 -0
- data/lib/active_support/core_ext/file/atomic.rb +3 -1
- data/lib/active_support/core_ext/hash/conversions.rb +1 -2
- data/lib/active_support/core_ext/hash/deep_merge.rb +22 -14
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +3 -3
- data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -3
- data/lib/active_support/core_ext/hash/keys.rb +4 -4
- data/lib/active_support/core_ext/integer/inflections.rb +12 -12
- data/lib/active_support/core_ext/kernel/reporting.rb +4 -4
- data/lib/active_support/core_ext/kernel/singleton_class.rb +1 -1
- data/lib/active_support/core_ext/module/attribute_accessors.rb +8 -0
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +49 -22
- data/lib/active_support/core_ext/module/concerning.rb +6 -6
- data/lib/active_support/core_ext/module/delegation.rb +41 -18
- data/lib/active_support/core_ext/module/deprecation.rb +15 -12
- data/lib/active_support/core_ext/module/introspection.rb +0 -1
- data/lib/active_support/core_ext/name_error.rb +2 -8
- data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +82 -77
- data/lib/active_support/core_ext/object/acts_like.rb +29 -5
- data/lib/active_support/core_ext/object/blank.rb +2 -2
- data/lib/active_support/core_ext/object/deep_dup.rb +17 -1
- data/lib/active_support/core_ext/object/duplicable.rb +15 -4
- data/lib/active_support/core_ext/object/inclusion.rb +13 -5
- data/lib/active_support/core_ext/object/instance_variables.rb +22 -12
- data/lib/active_support/core_ext/object/json.rb +40 -27
- data/lib/active_support/core_ext/object/to_query.rb +2 -4
- data/lib/active_support/core_ext/object/try.rb +20 -20
- data/lib/active_support/core_ext/object/with.rb +44 -0
- data/lib/active_support/core_ext/object/with_options.rb +25 -6
- data/lib/active_support/core_ext/object.rb +1 -0
- data/lib/active_support/core_ext/pathname/blank.rb +16 -0
- data/lib/active_support/core_ext/pathname/existence.rb +23 -0
- data/lib/active_support/core_ext/pathname.rb +4 -0
- data/lib/active_support/core_ext/range/compare_range.rb +0 -25
- data/lib/active_support/core_ext/range/conversions.rb +34 -13
- data/lib/active_support/core_ext/range/each.rb +1 -1
- data/lib/active_support/core_ext/range/overlap.rb +40 -0
- data/lib/active_support/core_ext/range.rb +1 -2
- data/lib/active_support/core_ext/securerandom.rb +25 -13
- data/lib/active_support/core_ext/string/conversions.rb +2 -2
- data/lib/active_support/core_ext/string/filters.rb +21 -15
- data/lib/active_support/core_ext/string/indent.rb +1 -1
- data/lib/active_support/core_ext/string/inflections.rb +17 -10
- data/lib/active_support/core_ext/string/inquiry.rb +1 -1
- data/lib/active_support/core_ext/string/output_safety.rb +85 -193
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +0 -8
- data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
- data/lib/active_support/core_ext/time/calculations.rb +29 -10
- data/lib/active_support/core_ext/time/conversions.rb +14 -13
- data/lib/active_support/core_ext/time/zones.rb +12 -28
- data/lib/active_support/core_ext.rb +1 -0
- data/lib/active_support/current_attributes.rb +46 -21
- data/lib/active_support/deep_mergeable.rb +53 -0
- data/lib/active_support/dependencies/autoload.rb +17 -12
- data/lib/active_support/dependencies/interlock.rb +10 -18
- data/lib/active_support/dependencies/require_dependency.rb +28 -0
- data/lib/active_support/dependencies.rb +58 -788
- data/lib/active_support/deprecation/behaviors.rb +66 -40
- data/lib/active_support/deprecation/constant_accessor.rb +5 -4
- data/lib/active_support/deprecation/deprecators.rb +104 -0
- data/lib/active_support/deprecation/disallowed.rb +6 -8
- data/lib/active_support/deprecation/instance_delegator.rb +31 -4
- data/lib/active_support/deprecation/method_wrappers.rb +9 -26
- data/lib/active_support/deprecation/proxy_wrappers.rb +38 -23
- data/lib/active_support/deprecation/reporting.rb +42 -25
- data/lib/active_support/deprecation.rb +32 -5
- data/lib/active_support/deprecator.rb +7 -0
- data/lib/active_support/descendants_tracker.rb +150 -72
- data/lib/active_support/digest.rb +4 -4
- data/lib/active_support/duration/iso8601_parser.rb +3 -3
- data/lib/active_support/duration/iso8601_serializer.rb +9 -3
- data/lib/active_support/duration.rb +79 -49
- data/lib/active_support/encrypted_configuration.rb +72 -9
- data/lib/active_support/encrypted_file.rb +29 -13
- data/lib/active_support/environment_inquirer.rb +23 -3
- data/lib/active_support/error_reporter/test_helper.rb +15 -0
- data/lib/active_support/error_reporter.rb +203 -0
- data/lib/active_support/evented_file_update_checker.rb +20 -7
- 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 +31 -12
- data/lib/active_support/executor/test_helper.rb +7 -0
- data/lib/active_support/file_update_checker.rb +4 -2
- data/lib/active_support/fork_tracker.rb +28 -13
- data/lib/active_support/gem_version.rb +4 -4
- data/lib/active_support/gzip.rb +2 -0
- data/lib/active_support/hash_with_indifferent_access.rb +38 -18
- data/lib/active_support/html_safe_translation.rb +43 -0
- data/lib/active_support/i18n.rb +2 -1
- data/lib/active_support/i18n_railtie.rb +21 -14
- data/lib/active_support/inflector/inflections.rb +25 -7
- data/lib/active_support/inflector/methods.rb +50 -63
- data/lib/active_support/inflector/transliterate.rb +4 -2
- data/lib/active_support/isolated_execution_state.rb +76 -0
- data/lib/active_support/json/decoding.rb +2 -1
- data/lib/active_support/json/encoding.rb +27 -45
- data/lib/active_support/key_generator.rb +31 -6
- data/lib/active_support/lazy_load_hooks.rb +33 -7
- data/lib/active_support/locale/en.yml +3 -1
- data/lib/active_support/log_subscriber/test_helper.rb +2 -2
- data/lib/active_support/log_subscriber.rb +96 -35
- data/lib/active_support/logger.rb +9 -60
- data/lib/active_support/logger_thread_safe_level.rb +11 -34
- data/lib/active_support/message_encryptor.rb +206 -56
- data/lib/active_support/message_encryptors.rb +141 -0
- data/lib/active_support/message_pack/cache_serializer.rb +23 -0
- data/lib/active_support/message_pack/extensions.rb +292 -0
- data/lib/active_support/message_pack/serializer.rb +63 -0
- data/lib/active_support/message_pack.rb +50 -0
- data/lib/active_support/message_verifier.rb +235 -84
- data/lib/active_support/message_verifiers.rb +135 -0
- data/lib/active_support/messages/codec.rb +65 -0
- data/lib/active_support/messages/metadata.rb +112 -46
- data/lib/active_support/messages/rotation_coordinator.rb +93 -0
- data/lib/active_support/messages/rotator.rb +34 -32
- data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
- data/lib/active_support/multibyte/chars.rb +12 -11
- data/lib/active_support/multibyte/unicode.rb +9 -49
- data/lib/active_support/multibyte.rb +1 -1
- data/lib/active_support/notifications/fanout.rb +304 -114
- data/lib/active_support/notifications/instrumenter.rb +109 -35
- data/lib/active_support/notifications.rb +24 -24
- data/lib/active_support/number_helper/number_converter.rb +14 -7
- data/lib/active_support/number_helper/number_to_currency_converter.rb +11 -6
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +4 -4
- data/lib/active_support/number_helper/number_to_phone_converter.rb +2 -1
- data/lib/active_support/number_helper/rounding_helper.rb +1 -5
- data/lib/active_support/number_helper.rb +379 -319
- data/lib/active_support/option_merger.rb +10 -18
- data/lib/active_support/ordered_hash.rb +4 -4
- data/lib/active_support/ordered_options.rb +15 -1
- data/lib/active_support/parameter_filter.rb +104 -80
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/railtie.rb +83 -21
- data/lib/active_support/reloader.rb +12 -4
- data/lib/active_support/rescuable.rb +14 -12
- data/lib/active_support/ruby_features.rb +7 -0
- data/lib/active_support/secure_compare_rotator.rb +18 -11
- data/lib/active_support/string_inquirer.rb +3 -3
- data/lib/active_support/subscriber.rb +11 -40
- data/lib/active_support/syntax_error_proxy.rb +70 -0
- data/lib/active_support/tagged_logging.rb +60 -24
- data/lib/active_support/test_case.rb +166 -27
- data/lib/active_support/testing/assertions.rb +60 -14
- data/lib/active_support/testing/autorun.rb +0 -2
- data/lib/active_support/testing/constant_stubbing.rb +32 -0
- data/lib/active_support/testing/deprecation.rb +53 -2
- data/lib/active_support/testing/error_reporter_assertions.rb +107 -0
- data/lib/active_support/testing/isolation.rb +30 -29
- data/lib/active_support/testing/method_call_assertions.rb +24 -11
- data/lib/active_support/testing/parallelization/server.rb +4 -0
- data/lib/active_support/testing/parallelization/worker.rb +3 -0
- data/lib/active_support/testing/parallelization.rb +4 -0
- data/lib/active_support/testing/parallelize_executor.rb +81 -0
- data/lib/active_support/testing/stream.rb +4 -6
- data/lib/active_support/testing/strict_warnings.rb +39 -0
- data/lib/active_support/testing/tagged_logging.rb +1 -1
- data/lib/active_support/testing/time_helpers.rb +49 -16
- data/lib/active_support/time_with_zone.rb +39 -28
- data/lib/active_support/values/time_zone.rb +38 -17
- data/lib/active_support/version.rb +1 -1
- data/lib/active_support/xml_mini/jdom.rb +4 -11
- data/lib/active_support/xml_mini/libxml.rb +5 -5
- data/lib/active_support/xml_mini/libxmlsax.rb +1 -1
- data/lib/active_support/xml_mini/nokogiri.rb +5 -5
- data/lib/active_support/xml_mini/nokogirisax.rb +2 -2
- data/lib/active_support/xml_mini/rexml.rb +2 -2
- data/lib/active_support/xml_mini.rb +7 -6
- data/lib/active_support.rb +28 -1
- metadata +107 -18
- data/lib/active_support/core_ext/marshal.rb +0 -26
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -28
- data/lib/active_support/core_ext/range/overlaps.rb +0 -10
- data/lib/active_support/core_ext/uri.rb +0 -29
- data/lib/active_support/dependencies/zeitwerk_integration.rb +0 -120
- data/lib/active_support/per_thread_registry.rb +0 -61
@@ -5,9 +5,13 @@ require "active_support/number_helper"
|
|
5
5
|
|
6
6
|
module ActiveSupport
|
7
7
|
module NumericWithFormat
|
8
|
+
# \Numeric With Format
|
9
|
+
#
|
8
10
|
# Provides options for converting numbers into formatted strings.
|
9
11
|
# Options are provided for phone numbers, currency, percentage,
|
10
|
-
# precision, positional notation, file size and pretty printing.
|
12
|
+
# precision, positional notation, file size, and pretty printing.
|
13
|
+
#
|
14
|
+
# This method is aliased to <tt>to_formatted_s</tt>.
|
11
15
|
#
|
12
16
|
# ==== Options
|
13
17
|
#
|
@@ -16,102 +20,102 @@ module ActiveSupport
|
|
16
20
|
# ==== Examples
|
17
21
|
#
|
18
22
|
# Phone Numbers:
|
19
|
-
# 5551234.
|
20
|
-
# 1235551234.
|
21
|
-
# 1235551234.
|
22
|
-
# 1235551234.
|
23
|
-
# 1235551234.
|
24
|
-
# 1235551234.
|
25
|
-
# 1235551234.
|
23
|
+
# 5551234.to_fs(:phone) # => "555-1234"
|
24
|
+
# 1235551234.to_fs(:phone) # => "123-555-1234"
|
25
|
+
# 1235551234.to_fs(:phone, area_code: true) # => "(123) 555-1234"
|
26
|
+
# 1235551234.to_fs(:phone, delimiter: ' ') # => "123 555 1234"
|
27
|
+
# 1235551234.to_fs(:phone, area_code: true, extension: 555) # => "(123) 555-1234 x 555"
|
28
|
+
# 1235551234.to_fs(:phone, country_code: 1) # => "+1-123-555-1234"
|
29
|
+
# 1235551234.to_fs(:phone, country_code: 1, extension: 1343, delimiter: '.')
|
26
30
|
# # => "+1.123.555.1234 x 1343"
|
27
31
|
#
|
28
32
|
# Currency:
|
29
|
-
# 1234567890.50.
|
30
|
-
# 1234567890.506.
|
31
|
-
# 1234567890.506.
|
32
|
-
# 1234567890.506.
|
33
|
-
# 1234567890.506.
|
34
|
-
# -1234567890.50.
|
33
|
+
# 1234567890.50.to_fs(:currency) # => "$1,234,567,890.50"
|
34
|
+
# 1234567890.506.to_fs(:currency) # => "$1,234,567,890.51"
|
35
|
+
# 1234567890.506.to_fs(:currency, precision: 3) # => "$1,234,567,890.506"
|
36
|
+
# 1234567890.506.to_fs(:currency, round_mode: :down) # => "$1,234,567,890.50"
|
37
|
+
# 1234567890.506.to_fs(:currency, locale: :fr) # => "1 234 567 890,51 €"
|
38
|
+
# -1234567890.50.to_fs(:currency, negative_format: '(%u%n)')
|
35
39
|
# # => "($1,234,567,890.50)"
|
36
|
-
# 1234567890.50.
|
40
|
+
# 1234567890.50.to_fs(:currency, unit: '£', separator: ',', delimiter: '')
|
37
41
|
# # => "£1234567890,50"
|
38
|
-
# 1234567890.50.
|
42
|
+
# 1234567890.50.to_fs(:currency, unit: '£', separator: ',', delimiter: '', format: '%n %u')
|
39
43
|
# # => "1234567890,50 £"
|
40
44
|
#
|
41
45
|
# Percentage:
|
42
|
-
# 100.
|
43
|
-
# 100.
|
44
|
-
# 1000.
|
45
|
-
# 302.24398923423.
|
46
|
-
# 302.24398923423.
|
47
|
-
# 1000.
|
48
|
-
# 100.
|
46
|
+
# 100.to_fs(:percentage) # => "100.000%"
|
47
|
+
# 100.to_fs(:percentage, precision: 0) # => "100%"
|
48
|
+
# 1000.to_fs(:percentage, delimiter: '.', separator: ',') # => "1.000,000%"
|
49
|
+
# 302.24398923423.to_fs(:percentage, precision: 5) # => "302.24399%"
|
50
|
+
# 302.24398923423.to_fs(:percentage, round_mode: :down) # => "302.243%"
|
51
|
+
# 1000.to_fs(:percentage, locale: :fr) # => "1 000,000%"
|
52
|
+
# 100.to_fs(:percentage, format: '%n %') # => "100.000 %"
|
49
53
|
#
|
50
54
|
# Delimited:
|
51
|
-
# 12345678.
|
52
|
-
# 12345678.05.
|
53
|
-
# 12345678.
|
54
|
-
# 12345678.
|
55
|
-
# 12345678.05.
|
56
|
-
# 12345678.05.
|
57
|
-
# 98765432.98.
|
55
|
+
# 12345678.to_fs(:delimited) # => "12,345,678"
|
56
|
+
# 12345678.05.to_fs(:delimited) # => "12,345,678.05"
|
57
|
+
# 12345678.to_fs(:delimited, delimiter: '.') # => "12.345.678"
|
58
|
+
# 12345678.to_fs(:delimited, delimiter: ',') # => "12,345,678"
|
59
|
+
# 12345678.05.to_fs(:delimited, separator: ' ') # => "12,345,678 05"
|
60
|
+
# 12345678.05.to_fs(:delimited, locale: :fr) # => "12 345 678,05"
|
61
|
+
# 98765432.98.to_fs(:delimited, delimiter: ' ', separator: ',')
|
58
62
|
# # => "98 765 432,98"
|
59
63
|
#
|
60
64
|
# Rounded:
|
61
|
-
# 111.2345.
|
62
|
-
# 111.2345.
|
63
|
-
# 111.2345.
|
64
|
-
# 13.
|
65
|
-
# 389.32314.
|
66
|
-
# 111.2345.
|
67
|
-
# 111.2345.
|
68
|
-
# 13.
|
69
|
-
# 111.234.
|
70
|
-
# 13.
|
65
|
+
# 111.2345.to_fs(:rounded) # => "111.235"
|
66
|
+
# 111.2345.to_fs(:rounded, precision: 2) # => "111.23"
|
67
|
+
# 111.2345.to_fs(:rounded, precision: 2, round_mode: :up) # => "111.24"
|
68
|
+
# 13.to_fs(:rounded, precision: 5) # => "13.00000"
|
69
|
+
# 389.32314.to_fs(:rounded, precision: 0) # => "389"
|
70
|
+
# 111.2345.to_fs(:rounded, significant: true) # => "111"
|
71
|
+
# 111.2345.to_fs(:rounded, precision: 1, significant: true) # => "100"
|
72
|
+
# 13.to_fs(:rounded, precision: 5, significant: true) # => "13.000"
|
73
|
+
# 111.234.to_fs(:rounded, locale: :fr) # => "111,234"
|
74
|
+
# 13.to_fs(:rounded, precision: 5, significant: true, strip_insignificant_zeros: true)
|
71
75
|
# # => "13"
|
72
|
-
# 389.32314.
|
73
|
-
# 1111.2345.
|
76
|
+
# 389.32314.to_fs(:rounded, precision: 4, significant: true) # => "389.3"
|
77
|
+
# 1111.2345.to_fs(:rounded, precision: 2, separator: ',', delimiter: '.')
|
74
78
|
# # => "1.111,23"
|
75
79
|
#
|
76
80
|
# Human-friendly size in Bytes:
|
77
|
-
# 123.
|
78
|
-
# 1234.
|
79
|
-
# 12345.
|
80
|
-
# 1234567.
|
81
|
-
# 1234567890.
|
82
|
-
# 1234567890123.
|
83
|
-
# 1234567890123456.
|
84
|
-
# 1234567890123456789.
|
85
|
-
# 1234567.
|
86
|
-
# 1234567.
|
87
|
-
# 483989.
|
88
|
-
# 1234567.
|
89
|
-
# 1234567890123.
|
90
|
-
# 524288000.
|
81
|
+
# 123.to_fs(:human_size) # => "123 Bytes"
|
82
|
+
# 1234.to_fs(:human_size) # => "1.21 KB"
|
83
|
+
# 12345.to_fs(:human_size) # => "12.1 KB"
|
84
|
+
# 1234567.to_fs(:human_size) # => "1.18 MB"
|
85
|
+
# 1234567890.to_fs(:human_size) # => "1.15 GB"
|
86
|
+
# 1234567890123.to_fs(:human_size) # => "1.12 TB"
|
87
|
+
# 1234567890123456.to_fs(:human_size) # => "1.1 PB"
|
88
|
+
# 1234567890123456789.to_fs(:human_size) # => "1.07 EB"
|
89
|
+
# 1234567.to_fs(:human_size, precision: 2) # => "1.2 MB"
|
90
|
+
# 1234567.to_fs(:human_size, precision: 2, round_mode: :up) # => "1.3 MB"
|
91
|
+
# 483989.to_fs(:human_size, precision: 2) # => "470 KB"
|
92
|
+
# 1234567.to_fs(:human_size, precision: 2, separator: ',') # => "1,2 MB"
|
93
|
+
# 1234567890123.to_fs(:human_size, precision: 5) # => "1.1228 TB"
|
94
|
+
# 524288000.to_fs(:human_size, precision: 5) # => "500 MB"
|
91
95
|
#
|
92
96
|
# Human-friendly format:
|
93
|
-
# 123.
|
94
|
-
# 1234.
|
95
|
-
# 12345.
|
96
|
-
# 1234567.
|
97
|
-
# 1234567890.
|
98
|
-
# 1234567890123.
|
99
|
-
# 1234567890123456.
|
100
|
-
# 1234567890123456789.
|
101
|
-
# 489939.
|
102
|
-
# 489939.
|
103
|
-
# 489939.
|
104
|
-
# 1234567.
|
105
|
-
# significant: false)
|
106
|
-
# 1234567.
|
97
|
+
# 123.to_fs(:human) # => "123"
|
98
|
+
# 1234.to_fs(:human) # => "1.23 Thousand"
|
99
|
+
# 12345.to_fs(:human) # => "12.3 Thousand"
|
100
|
+
# 1234567.to_fs(:human) # => "1.23 Million"
|
101
|
+
# 1234567890.to_fs(:human) # => "1.23 Billion"
|
102
|
+
# 1234567890123.to_fs(:human) # => "1.23 Trillion"
|
103
|
+
# 1234567890123456.to_fs(:human) # => "1.23 Quadrillion"
|
104
|
+
# 1234567890123456789.to_fs(:human) # => "1230 Quadrillion"
|
105
|
+
# 489939.to_fs(:human, precision: 2) # => "490 Thousand"
|
106
|
+
# 489939.to_fs(:human, precision: 2, round_mode: :down) # => "480 Thousand"
|
107
|
+
# 489939.to_fs(:human, precision: 4) # => "489.9 Thousand"
|
108
|
+
# 1234567.to_fs(:human, precision: 4,
|
109
|
+
# significant: false) # => "1.2346 Million"
|
110
|
+
# 1234567.to_fs(:human, precision: 1,
|
107
111
|
# separator: ',',
|
108
|
-
# significant: false)
|
109
|
-
def
|
112
|
+
# significant: false) # => "1,2 Million"
|
113
|
+
def to_fs(format = nil, options = nil)
|
114
|
+
return to_s if format.nil?
|
115
|
+
|
110
116
|
case format
|
111
|
-
when nil
|
112
|
-
super()
|
113
117
|
when Integer, String
|
114
|
-
|
118
|
+
to_s(format)
|
115
119
|
when :phone
|
116
120
|
ActiveSupport::NumberHelper.number_to_phone(self, options || {})
|
117
121
|
when :currency
|
@@ -127,11 +131,12 @@ module ActiveSupport
|
|
127
131
|
when :human_size
|
128
132
|
ActiveSupport::NumberHelper.number_to_human_size(self, options || {})
|
129
133
|
when Symbol
|
130
|
-
|
134
|
+
to_s
|
131
135
|
else
|
132
|
-
|
136
|
+
to_s(format)
|
133
137
|
end
|
134
138
|
end
|
139
|
+
alias_method :to_formatted_s, :to_fs
|
135
140
|
end
|
136
141
|
end
|
137
142
|
|
@@ -1,11 +1,35 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Object
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
# <tt>
|
8
|
-
#
|
4
|
+
# Provides a way to check whether some class acts like some other class based on the existence of
|
5
|
+
# an appropriately-named marker method.
|
6
|
+
#
|
7
|
+
# A class that provides the same interface as <tt>SomeClass</tt> may define a marker method named
|
8
|
+
# <tt>acts_like_some_class?</tt> to signal its compatibility to callers of
|
9
|
+
# <tt>acts_like?(:some_class)</tt>.
|
10
|
+
#
|
11
|
+
# For example, Active Support extends <tt>Date</tt> to define an <tt>acts_like_date?</tt> method,
|
12
|
+
# and extends <tt>Time</tt> to define <tt>acts_like_time?</tt>. As a result, developers can call
|
13
|
+
# <tt>x.acts_like?(:time)</tt> and <tt>x.acts_like?(:date)</tt> to test duck-type compatibility,
|
14
|
+
# and classes that are able to act like <tt>Time</tt> can also define an <tt>acts_like_time?</tt>
|
15
|
+
# method to interoperate.
|
16
|
+
#
|
17
|
+
# Note that the marker method is only expected to exist. It isn't called, so its body or return
|
18
|
+
# value are irrelevant.
|
19
|
+
#
|
20
|
+
# ==== Example: A class that provides the same interface as <tt>String</tt>
|
21
|
+
#
|
22
|
+
# This class may define:
|
23
|
+
#
|
24
|
+
# class Stringish
|
25
|
+
# def acts_like_string?
|
26
|
+
# end
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# Then client code can query for duck-type-safeness this way:
|
30
|
+
#
|
31
|
+
# Stringish.new.acts_like?(:string) # => true
|
32
|
+
#
|
9
33
|
def acts_like?(duck)
|
10
34
|
case duck
|
11
35
|
when :time
|
@@ -131,7 +131,7 @@ class String
|
|
131
131
|
end
|
132
132
|
end
|
133
133
|
|
134
|
-
class Numeric
|
134
|
+
class Numeric # :nodoc:
|
135
135
|
# No number is blank:
|
136
136
|
#
|
137
137
|
# 1.blank? # => false
|
@@ -143,7 +143,7 @@ class Numeric #:nodoc:
|
|
143
143
|
end
|
144
144
|
end
|
145
145
|
|
146
|
-
class Time
|
146
|
+
class Time # :nodoc:
|
147
147
|
# No Time is blank:
|
148
148
|
#
|
149
149
|
# Time.now.blank? # => false
|
@@ -43,7 +43,7 @@ class Hash
|
|
43
43
|
def deep_dup
|
44
44
|
hash = dup
|
45
45
|
each_pair do |key, value|
|
46
|
-
if
|
46
|
+
if ::String === key || ::Symbol === key
|
47
47
|
hash[key] = value.deep_dup
|
48
48
|
else
|
49
49
|
hash.delete(key)
|
@@ -53,3 +53,19 @@ class Hash
|
|
53
53
|
hash
|
54
54
|
end
|
55
55
|
end
|
56
|
+
|
57
|
+
class Module
|
58
|
+
# Returns a copy of module or class if it's anonymous. If it's
|
59
|
+
# named, returns +self+.
|
60
|
+
#
|
61
|
+
# Object.deep_dup == Object # => true
|
62
|
+
# klass = Class.new
|
63
|
+
# klass.deep_dup == klass # => false
|
64
|
+
def deep_dup
|
65
|
+
if name.nil?
|
66
|
+
super
|
67
|
+
else
|
68
|
+
self
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -31,8 +31,8 @@ end
|
|
31
31
|
class Method
|
32
32
|
# Methods are not duplicable:
|
33
33
|
#
|
34
|
-
#
|
35
|
-
#
|
34
|
+
# method(:puts).duplicable? # => false
|
35
|
+
# method(:puts).dup # => TypeError: allocator undefined for Method
|
36
36
|
def duplicable?
|
37
37
|
false
|
38
38
|
end
|
@@ -41,8 +41,19 @@ end
|
|
41
41
|
class UnboundMethod
|
42
42
|
# Unbound methods are not duplicable:
|
43
43
|
#
|
44
|
-
#
|
45
|
-
#
|
44
|
+
# method(:puts).unbind.duplicable? # => false
|
45
|
+
# method(:puts).unbind.dup # => TypeError: allocator undefined for UnboundMethod
|
46
|
+
def duplicable?
|
47
|
+
false
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
require "singleton"
|
52
|
+
|
53
|
+
module Singleton
|
54
|
+
# Singleton instances are not duplicable:
|
55
|
+
#
|
56
|
+
# Class.new.include(Singleton).instance.dup # TypeError (can't dup instance of singleton
|
46
57
|
def duplicable?
|
47
58
|
false
|
48
59
|
end
|
@@ -1,16 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Object
|
4
|
-
# Returns true if this object is included in the argument.
|
5
|
-
#
|
4
|
+
# Returns true if this object is included in the argument.
|
5
|
+
#
|
6
|
+
# When argument is a +Range+, +#cover?+ is used to properly handle inclusion
|
7
|
+
# check within open ranges. Otherwise, argument must be any object which responds
|
8
|
+
# to +#include?+. Usage:
|
6
9
|
#
|
7
10
|
# characters = ["Konata", "Kagami", "Tsukasa"]
|
8
11
|
# "Konata".in?(characters) # => true
|
9
12
|
#
|
10
|
-
#
|
11
|
-
# to +#include?+.
|
13
|
+
# For non +Range+ arguments, this will throw an +ArgumentError+ if the argument
|
14
|
+
# doesn't respond to +#include?+.
|
12
15
|
def in?(another_object)
|
13
|
-
another_object
|
16
|
+
case another_object
|
17
|
+
when Range
|
18
|
+
another_object.cover?(self)
|
19
|
+
else
|
20
|
+
another_object.include?(self)
|
21
|
+
end
|
14
22
|
rescue NoMethodError
|
15
23
|
raise ArgumentError.new("The parameter passed to #in? must respond to #include?")
|
16
24
|
end
|
@@ -12,19 +12,29 @@ class Object
|
|
12
12
|
#
|
13
13
|
# C.new(0, 1).instance_values # => {"x" => 0, "y" => 1}
|
14
14
|
def instance_values
|
15
|
-
|
15
|
+
instance_variables.to_h do |ivar|
|
16
|
+
[ivar[1..-1].freeze, instance_variable_get(ivar)]
|
17
|
+
end
|
16
18
|
end
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
20
|
+
if Symbol.method_defined?(:name) # RUBY_VERSION >= "3.0"
|
21
|
+
# Returns an array of instance variable names as strings including "@".
|
22
|
+
#
|
23
|
+
# class C
|
24
|
+
# def initialize(x, y)
|
25
|
+
# @x, @y = x, y
|
26
|
+
# end
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# C.new(0, 1).instance_variable_names # => ["@y", "@x"]
|
30
|
+
def instance_variable_names
|
31
|
+
instance_variables.map(&:name)
|
32
|
+
end
|
33
|
+
else
|
34
|
+
def instance_variable_names
|
35
|
+
variables = instance_variables
|
36
|
+
variables.map! { |s| s.to_s.freeze }
|
37
|
+
variables
|
38
|
+
end
|
29
39
|
end
|
30
40
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Hack to load
|
3
|
+
# Hack to load JSON gem first so we can override its to_json.
|
4
4
|
require "json"
|
5
5
|
require "bigdecimal"
|
6
6
|
require "ipaddr"
|
@@ -19,8 +19,7 @@ require "active_support/core_ext/date/conversions"
|
|
19
19
|
# The JSON gem adds a few modules to Ruby core classes containing :to_json definition, overwriting
|
20
20
|
# their default behavior. That said, we need to define the basic to_json method in all of them,
|
21
21
|
# otherwise they will always use to_json gem implementation, which is backwards incompatible in
|
22
|
-
# several cases (for instance, the JSON implementation for Hash does not work) with inheritance
|
23
|
-
# and consequently classes as ActiveSupport::OrderedHash cannot be serialized to json.
|
22
|
+
# several cases (for instance, the JSON implementation for Hash does not work) with inheritance.
|
24
23
|
#
|
25
24
|
# On the other hand, we should avoid conflict with ::JSON.{generate,dump}(obj). Unfortunately, the
|
26
25
|
# JSON gem's encoder relies on its own to_json implementation to encode objects. Since it always
|
@@ -30,7 +29,7 @@ require "active_support/core_ext/date/conversions"
|
|
30
29
|
# It should be noted that when using ::JSON.{generate,dump} directly, ActiveSupport's encoder is
|
31
30
|
# bypassed completely. This means that as_json won't be invoked and the JSON gem will simply
|
32
31
|
# ignore any options it does not natively understand. This also means that ::JSON.{generate,dump}
|
33
|
-
# should give exactly the same results with or without
|
32
|
+
# should give exactly the same results with or without Active Support.
|
34
33
|
|
35
34
|
module ActiveSupport
|
36
35
|
module ToJsonWithActiveSupportEncoder # :nodoc:
|
@@ -50,8 +49,14 @@ end
|
|
50
49
|
klass.prepend(ActiveSupport::ToJsonWithActiveSupportEncoder)
|
51
50
|
end
|
52
51
|
|
52
|
+
class Module
|
53
|
+
def as_json(options = nil) # :nodoc:
|
54
|
+
name
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
53
58
|
class Object
|
54
|
-
def as_json(options = nil)
|
59
|
+
def as_json(options = nil) # :nodoc:
|
55
60
|
if respond_to?(:to_hash)
|
56
61
|
to_hash.as_json(options)
|
57
62
|
else
|
@@ -60,44 +65,52 @@ class Object
|
|
60
65
|
end
|
61
66
|
end
|
62
67
|
|
63
|
-
|
68
|
+
if RUBY_VERSION >= "3.2"
|
69
|
+
class Data # :nodoc:
|
70
|
+
def as_json(options = nil)
|
71
|
+
to_h.as_json(options)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
class Struct # :nodoc:
|
64
77
|
def as_json(options = nil)
|
65
|
-
|
78
|
+
to_h.as_json(options)
|
66
79
|
end
|
67
80
|
end
|
68
81
|
|
69
82
|
class TrueClass
|
70
|
-
def as_json(options = nil)
|
83
|
+
def as_json(options = nil) # :nodoc:
|
71
84
|
self
|
72
85
|
end
|
73
86
|
end
|
74
87
|
|
75
88
|
class FalseClass
|
76
|
-
def as_json(options = nil)
|
89
|
+
def as_json(options = nil) # :nodoc:
|
77
90
|
self
|
78
91
|
end
|
79
92
|
end
|
80
93
|
|
81
94
|
class NilClass
|
82
|
-
def as_json(options = nil)
|
95
|
+
def as_json(options = nil) # :nodoc:
|
83
96
|
self
|
84
97
|
end
|
85
98
|
end
|
86
99
|
|
87
100
|
class String
|
88
|
-
def as_json(options = nil)
|
101
|
+
def as_json(options = nil) # :nodoc:
|
89
102
|
self
|
90
103
|
end
|
91
104
|
end
|
92
105
|
|
93
106
|
class Symbol
|
94
|
-
def as_json(options = nil)
|
107
|
+
def as_json(options = nil) # :nodoc:
|
95
108
|
to_s
|
96
109
|
end
|
97
110
|
end
|
98
111
|
|
99
112
|
class Numeric
|
100
|
-
def as_json(options = nil)
|
113
|
+
def as_json(options = nil) # :nodoc:
|
101
114
|
self
|
102
115
|
end
|
103
116
|
end
|
@@ -105,7 +118,7 @@ end
|
|
105
118
|
class Float
|
106
119
|
# Encoding Infinity or NaN to JSON should return "null". The default returns
|
107
120
|
# "Infinity" or "NaN" which are not valid JSON.
|
108
|
-
def as_json(options = nil)
|
121
|
+
def as_json(options = nil) # :nodoc:
|
109
122
|
finite? ? self : nil
|
110
123
|
end
|
111
124
|
end
|
@@ -120,43 +133,43 @@ class BigDecimal
|
|
120
133
|
# if the other end knows by contract that the data is supposed to be a
|
121
134
|
# BigDecimal, it still has the chance to post-process the string and get the
|
122
135
|
# real value.
|
123
|
-
def as_json(options = nil)
|
136
|
+
def as_json(options = nil) # :nodoc:
|
124
137
|
finite? ? to_s : nil
|
125
138
|
end
|
126
139
|
end
|
127
140
|
|
128
141
|
class Regexp
|
129
|
-
def as_json(options = nil)
|
142
|
+
def as_json(options = nil) # :nodoc:
|
130
143
|
to_s
|
131
144
|
end
|
132
145
|
end
|
133
146
|
|
134
147
|
module Enumerable
|
135
|
-
def as_json(options = nil)
|
148
|
+
def as_json(options = nil) # :nodoc:
|
136
149
|
to_a.as_json(options)
|
137
150
|
end
|
138
151
|
end
|
139
152
|
|
140
153
|
class IO
|
141
|
-
def as_json(options = nil)
|
154
|
+
def as_json(options = nil) # :nodoc:
|
142
155
|
to_s
|
143
156
|
end
|
144
157
|
end
|
145
158
|
|
146
159
|
class Range
|
147
|
-
def as_json(options = nil)
|
160
|
+
def as_json(options = nil) # :nodoc:
|
148
161
|
to_s
|
149
162
|
end
|
150
163
|
end
|
151
164
|
|
152
165
|
class Array
|
153
|
-
def as_json(options = nil)
|
166
|
+
def as_json(options = nil) # :nodoc:
|
154
167
|
map { |v| options ? v.as_json(options.dup) : v.as_json }
|
155
168
|
end
|
156
169
|
end
|
157
170
|
|
158
171
|
class Hash
|
159
|
-
def as_json(options = nil)
|
172
|
+
def as_json(options = nil) # :nodoc:
|
160
173
|
# create a subset of the hash by applying :only or :except
|
161
174
|
subset = if options
|
162
175
|
if attrs = options[:only]
|
@@ -179,7 +192,7 @@ class Hash
|
|
179
192
|
end
|
180
193
|
|
181
194
|
class Time
|
182
|
-
def as_json(options = nil)
|
195
|
+
def as_json(options = nil) # :nodoc:
|
183
196
|
if ActiveSupport::JSON::Encoding.use_standard_json_time_format
|
184
197
|
xmlschema(ActiveSupport::JSON::Encoding.time_precision)
|
185
198
|
else
|
@@ -189,7 +202,7 @@ class Time
|
|
189
202
|
end
|
190
203
|
|
191
204
|
class Date
|
192
|
-
def as_json(options = nil)
|
205
|
+
def as_json(options = nil) # :nodoc:
|
193
206
|
if ActiveSupport::JSON::Encoding.use_standard_json_time_format
|
194
207
|
strftime("%Y-%m-%d")
|
195
208
|
else
|
@@ -199,7 +212,7 @@ class Date
|
|
199
212
|
end
|
200
213
|
|
201
214
|
class DateTime
|
202
|
-
def as_json(options = nil)
|
215
|
+
def as_json(options = nil) # :nodoc:
|
203
216
|
if ActiveSupport::JSON::Encoding.use_standard_json_time_format
|
204
217
|
xmlschema(ActiveSupport::JSON::Encoding.time_precision)
|
205
218
|
else
|
@@ -208,13 +221,13 @@ class DateTime
|
|
208
221
|
end
|
209
222
|
end
|
210
223
|
|
211
|
-
class URI::Generic
|
224
|
+
class URI::Generic # :nodoc:
|
212
225
|
def as_json(options = nil)
|
213
226
|
to_s
|
214
227
|
end
|
215
228
|
end
|
216
229
|
|
217
|
-
class Pathname
|
230
|
+
class Pathname # :nodoc:
|
218
231
|
def as_json(options = nil)
|
219
232
|
to_s
|
220
233
|
end
|
@@ -226,7 +239,7 @@ class IPAddr # :nodoc:
|
|
226
239
|
end
|
227
240
|
end
|
228
241
|
|
229
|
-
class Process::Status
|
242
|
+
class Process::Status # :nodoc:
|
230
243
|
def as_json(options = nil)
|
231
244
|
{ exitstatus: exitstatus, pid: pid }
|
232
245
|
end
|
@@ -72,14 +72,12 @@ class Hash
|
|
72
72
|
#
|
73
73
|
# The string pairs "key=value" that conform the query string
|
74
74
|
# are sorted lexicographically in ascending order.
|
75
|
-
#
|
76
|
-
# This method is also aliased as +to_param+.
|
77
75
|
def to_query(namespace = nil)
|
78
|
-
query =
|
76
|
+
query = filter_map do |key, value|
|
79
77
|
unless (value.is_a?(Hash) || value.is_a?(Array)) && value.empty?
|
80
78
|
value.to_query(namespace ? "#{namespace}[#{key}]" : key)
|
81
79
|
end
|
82
|
-
end
|
80
|
+
end
|
83
81
|
|
84
82
|
query.sort! unless namespace.to_s.include?("[]")
|
85
83
|
query.join("&")
|