activesupport 7.0.0 → 7.2.2.1
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 +4 -4
- data/CHANGELOG.md +156 -255
- data/MIT-LICENSE +1 -1
- data/README.rdoc +6 -6
- data/lib/active_support/actionable_error.rb +3 -1
- data/lib/active_support/array_inquirer.rb +3 -1
- data/lib/active_support/backtrace_cleaner.rb +41 -9
- data/lib/active_support/benchmarkable.rb +1 -0
- data/lib/active_support/broadcast_logger.rb +251 -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 +49 -17
- data/lib/active_support/cache/mem_cache_store.rb +111 -129
- data/lib/active_support/cache/memory_store.rb +81 -26
- data/lib/active_support/cache/null_store.rb +6 -0
- data/lib/active_support/cache/redis_cache_store.rb +175 -154
- data/lib/active_support/cache/serializer_with_fallback.rb +152 -0
- data/lib/active_support/cache/strategy/local_cache.rb +31 -13
- data/lib/active_support/cache.rb +457 -377
- data/lib/active_support/callbacks.rb +123 -139
- data/lib/active_support/code_generator.rb +15 -10
- data/lib/active_support/concern.rb +4 -2
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +42 -3
- data/lib/active_support/concurrency/null_lock.rb +13 -0
- data/lib/active_support/configurable.rb +12 -2
- data/lib/active_support/core_ext/array/conversions.rb +7 -9
- data/lib/active_support/core_ext/array/inquiry.rb +2 -2
- data/lib/active_support/core_ext/array.rb +0 -1
- data/lib/active_support/core_ext/class/subclasses.rb +4 -15
- data/lib/active_support/core_ext/date/blank.rb +4 -0
- data/lib/active_support/core_ext/date/calculations.rb +20 -5
- data/lib/active_support/core_ext/date/conversions.rb +15 -16
- data/lib/active_support/core_ext/date.rb +0 -1
- data/lib/active_support/core_ext/date_and_time/calculations.rb +14 -4
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +29 -2
- data/lib/active_support/core_ext/date_time/blank.rb +4 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +4 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +15 -15
- data/lib/active_support/core_ext/date_time.rb +0 -1
- data/lib/active_support/core_ext/digest/uuid.rb +7 -10
- data/lib/active_support/core_ext/enumerable.rb +51 -101
- data/lib/active_support/core_ext/erb/util.rb +201 -0
- data/lib/active_support/core_ext/file/atomic.rb +2 -0
- 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 +7 -7
- data/lib/active_support/core_ext/integer/inflections.rb +12 -12
- data/lib/active_support/core_ext/kernel/singleton_class.rb +1 -1
- data/lib/active_support/core_ext/module/attr_internal.rb +17 -6
- data/lib/active_support/core_ext/module/attribute_accessors.rb +6 -0
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +38 -20
- data/lib/active_support/core_ext/module/concerning.rb +6 -6
- data/lib/active_support/core_ext/module/delegation.rb +20 -119
- data/lib/active_support/core_ext/module/deprecation.rb +12 -12
- data/lib/active_support/core_ext/module/introspection.rb +0 -1
- data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +77 -75
- data/lib/active_support/core_ext/numeric.rb +0 -1
- data/lib/active_support/core_ext/object/acts_like.rb +29 -5
- data/lib/active_support/core_ext/object/blank.rb +45 -1
- data/lib/active_support/core_ext/object/deep_dup.rb +16 -0
- data/lib/active_support/core_ext/object/duplicable.rb +25 -16
- data/lib/active_support/core_ext/object/inclusion.rb +13 -5
- data/lib/active_support/core_ext/object/instance_variables.rb +4 -2
- data/lib/active_support/core_ext/object/json.rb +17 -7
- data/lib/active_support/core_ext/object/to_query.rb +0 -2
- data/lib/active_support/core_ext/object/with.rb +46 -0
- data/lib/active_support/core_ext/object/with_options.rb +9 -9
- data/lib/active_support/core_ext/object.rb +1 -0
- data/lib/active_support/core_ext/pathname/blank.rb +20 -0
- data/lib/active_support/core_ext/pathname/existence.rb +2 -0
- data/lib/active_support/core_ext/pathname.rb +1 -0
- data/lib/active_support/core_ext/range/conversions.rb +32 -11
- 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 +2 -6
- data/lib/active_support/core_ext/string/conversions.rb +3 -3
- 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 +16 -9
- data/lib/active_support/core_ext/string/inquiry.rb +1 -1
- data/lib/active_support/core_ext/string/multibyte.rb +1 -1
- data/lib/active_support/core_ext/string/output_safety.rb +39 -150
- data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
- data/lib/active_support/core_ext/time/calculations.rb +42 -32
- data/lib/active_support/core_ext/time/compatibility.rb +16 -0
- data/lib/active_support/core_ext/time/conversions.rb +13 -15
- data/lib/active_support/core_ext/time/zones.rb +8 -9
- data/lib/active_support/core_ext/time.rb +0 -1
- data/lib/active_support/core_ext.rb +0 -1
- data/lib/active_support/current_attributes.rb +53 -46
- data/lib/active_support/deep_mergeable.rb +53 -0
- data/lib/active_support/delegation.rb +202 -0
- data/lib/active_support/dependencies/autoload.rb +9 -16
- data/lib/active_support/deprecation/behaviors.rb +65 -42
- data/lib/active_support/deprecation/constant_accessor.rb +47 -25
- data/lib/active_support/deprecation/deprecators.rb +104 -0
- data/lib/active_support/deprecation/disallowed.rb +6 -8
- data/lib/active_support/deprecation/method_wrappers.rb +6 -23
- data/lib/active_support/deprecation/proxy_wrappers.rb +34 -22
- data/lib/active_support/deprecation/reporting.rb +49 -27
- data/lib/active_support/deprecation.rb +39 -9
- data/lib/active_support/deprecator.rb +7 -0
- data/lib/active_support/descendants_tracker.rb +66 -175
- data/lib/active_support/duration/iso8601_parser.rb +2 -2
- data/lib/active_support/duration/iso8601_serializer.rb +1 -4
- data/lib/active_support/duration.rb +13 -7
- data/lib/active_support/encrypted_configuration.rb +63 -10
- data/lib/active_support/encrypted_file.rb +29 -13
- data/lib/active_support/environment_inquirer.rb +22 -2
- data/lib/active_support/error_reporter/test_helper.rb +15 -0
- data/lib/active_support/error_reporter.rb +160 -36
- data/lib/active_support/evented_file_update_checker.rb +19 -7
- data/lib/active_support/execution_wrapper.rb +23 -28
- data/lib/active_support/file_update_checker.rb +5 -3
- data/lib/active_support/fork_tracker.rb +4 -32
- 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 +41 -25
- data/lib/active_support/html_safe_translation.rb +19 -6
- data/lib/active_support/i18n.rb +1 -1
- data/lib/active_support/i18n_railtie.rb +20 -13
- data/lib/active_support/inflector/inflections.rb +2 -0
- data/lib/active_support/inflector/methods.rb +28 -18
- data/lib/active_support/inflector/transliterate.rb +4 -2
- data/lib/active_support/isolated_execution_state.rb +39 -19
- data/lib/active_support/json/decoding.rb +2 -1
- data/lib/active_support/json/encoding.rb +25 -43
- data/lib/active_support/key_generator.rb +13 -5
- data/lib/active_support/lazy_load_hooks.rb +33 -7
- data/lib/active_support/locale/en.yml +2 -0
- data/lib/active_support/log_subscriber/test_helper.rb +2 -2
- data/lib/active_support/log_subscriber.rb +76 -36
- data/lib/active_support/logger.rb +22 -60
- data/lib/active_support/logger_thread_safe_level.rb +10 -32
- data/lib/active_support/message_encryptor.rb +200 -55
- 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 +305 -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 +220 -89
- 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 +111 -45
- 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 +4 -2
- data/lib/active_support/multibyte/unicode.rb +9 -37
- data/lib/active_support/notifications/fanout.rb +248 -87
- data/lib/active_support/notifications/instrumenter.rb +93 -25
- data/lib/active_support/notifications.rb +38 -31
- data/lib/active_support/number_helper/number_converter.rb +16 -7
- data/lib/active_support/number_helper/number_to_currency_converter.rb +6 -6
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +3 -3
- data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -0
- data/lib/active_support/number_helper.rb +379 -317
- data/lib/active_support/option_merger.rb +4 -4
- data/lib/active_support/ordered_hash.rb +3 -3
- data/lib/active_support/ordered_options.rb +68 -16
- data/lib/active_support/parameter_filter.rb +103 -84
- data/lib/active_support/proxy_object.rb +8 -3
- data/lib/active_support/railtie.rb +30 -25
- data/lib/active_support/reloader.rb +13 -5
- data/lib/active_support/rescuable.rb +12 -10
- data/lib/active_support/secure_compare_rotator.rb +17 -10
- data/lib/active_support/string_inquirer.rb +4 -2
- data/lib/active_support/subscriber.rb +10 -27
- data/lib/active_support/syntax_error_proxy.rb +60 -0
- data/lib/active_support/tagged_logging.rb +64 -25
- data/lib/active_support/test_case.rb +160 -7
- data/lib/active_support/testing/assertions.rb +29 -13
- data/lib/active_support/testing/autorun.rb +0 -2
- data/lib/active_support/testing/constant_stubbing.rb +54 -0
- data/lib/active_support/testing/deprecation.rb +20 -27
- data/lib/active_support/testing/error_reporter_assertions.rb +107 -0
- data/lib/active_support/testing/isolation.rb +46 -33
- data/lib/active_support/testing/method_call_assertions.rb +7 -8
- data/lib/active_support/testing/parallelization/server.rb +3 -0
- data/lib/active_support/testing/parallelize_executor.rb +8 -3
- data/lib/active_support/testing/setup_and_teardown.rb +2 -0
- data/lib/active_support/testing/stream.rb +1 -1
- data/lib/active_support/testing/strict_warnings.rb +43 -0
- data/lib/active_support/testing/tests_without_assertions.rb +19 -0
- data/lib/active_support/testing/time_helpers.rb +38 -16
- data/lib/active_support/time_with_zone.rb +28 -54
- data/lib/active_support/values/time_zone.rb +26 -15
- data/lib/active_support/version.rb +1 -1
- data/lib/active_support/xml_mini/jdom.rb +3 -10
- data/lib/active_support/xml_mini/nokogiri.rb +1 -1
- data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
- data/lib/active_support/xml_mini/rexml.rb +1 -1
- data/lib/active_support/xml_mini.rb +13 -4
- data/lib/active_support.rb +15 -3
- metadata +142 -21
- data/lib/active_support/core_ext/array/deprecated_conversions.rb +0 -25
- data/lib/active_support/core_ext/date/deprecated_conversions.rb +0 -26
- data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +0 -22
- data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +0 -60
- data/lib/active_support/core_ext/range/deprecated_conversions.rb +0 -26
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -7
- data/lib/active_support/core_ext/range/overlaps.rb +0 -10
- data/lib/active_support/core_ext/time/deprecated_conversions.rb +0 -22
- data/lib/active_support/core_ext/uri.rb +0 -5
- data/lib/active_support/deprecation/instance_delegator.rb +0 -38
- data/lib/active_support/per_thread_registry.rb +0 -65
- data/lib/active_support/ruby_features.rb +0 -7
@@ -5,11 +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.
|
11
13
|
#
|
12
|
-
# This method is aliased to <tt>
|
14
|
+
# This method is aliased to <tt>to_formatted_s</tt>.
|
13
15
|
#
|
14
16
|
# ==== Options
|
15
17
|
#
|
@@ -18,97 +20,97 @@ module ActiveSupport
|
|
18
20
|
# ==== Examples
|
19
21
|
#
|
20
22
|
# Phone Numbers:
|
21
|
-
# 5551234.
|
22
|
-
# 1235551234.
|
23
|
-
# 1235551234.
|
24
|
-
# 1235551234.
|
25
|
-
# 1235551234.
|
26
|
-
# 1235551234.
|
27
|
-
# 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: '.')
|
28
30
|
# # => "+1.123.555.1234 x 1343"
|
29
31
|
#
|
30
32
|
# Currency:
|
31
|
-
# 1234567890.50.
|
32
|
-
# 1234567890.506.
|
33
|
-
# 1234567890.506.
|
34
|
-
# 1234567890.506.
|
35
|
-
# 1234567890.506.
|
36
|
-
# -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)')
|
37
39
|
# # => "($1,234,567,890.50)"
|
38
|
-
# 1234567890.50.
|
40
|
+
# 1234567890.50.to_fs(:currency, unit: '£', separator: ',', delimiter: '')
|
39
41
|
# # => "£1234567890,50"
|
40
|
-
# 1234567890.50.
|
42
|
+
# 1234567890.50.to_fs(:currency, unit: '£', separator: ',', delimiter: '', format: '%n %u')
|
41
43
|
# # => "1234567890,50 £"
|
42
44
|
#
|
43
45
|
# Percentage:
|
44
|
-
# 100.
|
45
|
-
# 100.
|
46
|
-
# 1000.
|
47
|
-
# 302.24398923423.
|
48
|
-
# 302.24398923423.
|
49
|
-
# 1000.
|
50
|
-
# 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 %"
|
51
53
|
#
|
52
54
|
# Delimited:
|
53
|
-
# 12345678.
|
54
|
-
# 12345678.05.
|
55
|
-
# 12345678.
|
56
|
-
# 12345678.
|
57
|
-
# 12345678.05.
|
58
|
-
# 12345678.05.
|
59
|
-
# 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: ',')
|
60
62
|
# # => "98 765 432,98"
|
61
63
|
#
|
62
64
|
# Rounded:
|
63
|
-
# 111.2345.
|
64
|
-
# 111.2345.
|
65
|
-
# 111.2345.
|
66
|
-
# 13.
|
67
|
-
# 389.32314.
|
68
|
-
# 111.2345.
|
69
|
-
# 111.2345.
|
70
|
-
# 13.
|
71
|
-
# 111.234.
|
72
|
-
# 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)
|
73
75
|
# # => "13"
|
74
|
-
# 389.32314.
|
75
|
-
# 1111.2345.
|
76
|
+
# 389.32314.to_fs(:rounded, precision: 4, significant: true) # => "389.3"
|
77
|
+
# 1111.2345.to_fs(:rounded, precision: 2, separator: ',', delimiter: '.')
|
76
78
|
# # => "1.111,23"
|
77
79
|
#
|
78
80
|
# Human-friendly size in Bytes:
|
79
|
-
# 123.
|
80
|
-
# 1234.
|
81
|
-
# 12345.
|
82
|
-
# 1234567.
|
83
|
-
# 1234567890.
|
84
|
-
# 1234567890123.
|
85
|
-
# 1234567890123456.
|
86
|
-
# 1234567890123456789.
|
87
|
-
# 1234567.
|
88
|
-
# 1234567.
|
89
|
-
# 483989.
|
90
|
-
# 1234567.
|
91
|
-
# 1234567890123.
|
92
|
-
# 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"
|
93
95
|
#
|
94
96
|
# Human-friendly format:
|
95
|
-
# 123.
|
96
|
-
# 1234.
|
97
|
-
# 12345.
|
98
|
-
# 1234567.
|
99
|
-
# 1234567890.
|
100
|
-
# 1234567890123.
|
101
|
-
# 1234567890123456.
|
102
|
-
# 1234567890123456789.
|
103
|
-
# 489939.
|
104
|
-
# 489939.
|
105
|
-
# 489939.
|
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,
|
107
109
|
# significant: false) # => "1.2346 Million"
|
108
|
-
# 1234567.
|
110
|
+
# 1234567.to_fs(:human, precision: 1,
|
109
111
|
# separator: ',',
|
110
112
|
# significant: false) # => "1,2 Million"
|
111
|
-
def
|
113
|
+
def to_fs(format = nil, options = nil)
|
112
114
|
return to_s if format.nil?
|
113
115
|
|
114
116
|
case format
|
@@ -134,10 +136,10 @@ module ActiveSupport
|
|
134
136
|
to_s(format)
|
135
137
|
end
|
136
138
|
end
|
137
|
-
alias_method :
|
139
|
+
alias_method :to_formatted_s, :to_fs
|
138
140
|
end
|
139
141
|
end
|
140
142
|
|
141
|
-
Integer.
|
142
|
-
Float.
|
143
|
-
BigDecimal.
|
143
|
+
Integer.include ActiveSupport::NumericWithFormat
|
144
|
+
Float.include ActiveSupport::NumericWithFormat
|
145
|
+
BigDecimal.include ActiveSupport::NumericWithFormat
|
@@ -3,4 +3,3 @@
|
|
3
3
|
require "active_support/core_ext/numeric/bytes"
|
4
4
|
require "active_support/core_ext/numeric/time"
|
5
5
|
require "active_support/core_ext/numeric/conversions"
|
6
|
-
require "active_support/core_ext/numeric/deprecated_conversions" unless ENV["RAILS_DISABLE_DEPRECATED_TO_S_CONVERSION"]
|
@@ -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
|
@@ -16,7 +16,7 @@ class Object
|
|
16
16
|
#
|
17
17
|
# @return [true, false]
|
18
18
|
def blank?
|
19
|
-
respond_to?(:empty?) ? !!empty? :
|
19
|
+
respond_to?(:empty?) ? !!empty? : false
|
20
20
|
end
|
21
21
|
|
22
22
|
# An object is present if it's not blank.
|
@@ -56,6 +56,10 @@ class NilClass
|
|
56
56
|
def blank?
|
57
57
|
true
|
58
58
|
end
|
59
|
+
|
60
|
+
def present? # :nodoc:
|
61
|
+
false
|
62
|
+
end
|
59
63
|
end
|
60
64
|
|
61
65
|
class FalseClass
|
@@ -67,6 +71,10 @@ class FalseClass
|
|
67
71
|
def blank?
|
68
72
|
true
|
69
73
|
end
|
74
|
+
|
75
|
+
def present? # :nodoc:
|
76
|
+
false
|
77
|
+
end
|
70
78
|
end
|
71
79
|
|
72
80
|
class TrueClass
|
@@ -78,6 +86,10 @@ class TrueClass
|
|
78
86
|
def blank?
|
79
87
|
false
|
80
88
|
end
|
89
|
+
|
90
|
+
def present? # :nodoc:
|
91
|
+
true
|
92
|
+
end
|
81
93
|
end
|
82
94
|
|
83
95
|
class Array
|
@@ -88,6 +100,10 @@ class Array
|
|
88
100
|
#
|
89
101
|
# @return [true, false]
|
90
102
|
alias_method :blank?, :empty?
|
103
|
+
|
104
|
+
def present? # :nodoc:
|
105
|
+
!empty?
|
106
|
+
end
|
91
107
|
end
|
92
108
|
|
93
109
|
class Hash
|
@@ -98,6 +114,22 @@ class Hash
|
|
98
114
|
#
|
99
115
|
# @return [true, false]
|
100
116
|
alias_method :blank?, :empty?
|
117
|
+
|
118
|
+
def present? # :nodoc:
|
119
|
+
!empty?
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
class Symbol
|
124
|
+
# A Symbol is blank if it's empty:
|
125
|
+
#
|
126
|
+
# :''.blank? # => true
|
127
|
+
# :symbol.blank? # => false
|
128
|
+
alias_method :blank?, :empty?
|
129
|
+
|
130
|
+
def present? # :nodoc:
|
131
|
+
!empty?
|
132
|
+
end
|
101
133
|
end
|
102
134
|
|
103
135
|
class String
|
@@ -129,6 +161,10 @@ class String
|
|
129
161
|
ENCODED_BLANKS[self.encoding].match?(self)
|
130
162
|
end
|
131
163
|
end
|
164
|
+
|
165
|
+
def present? # :nodoc:
|
166
|
+
!blank?
|
167
|
+
end
|
132
168
|
end
|
133
169
|
|
134
170
|
class Numeric # :nodoc:
|
@@ -141,6 +177,10 @@ class Numeric # :nodoc:
|
|
141
177
|
def blank?
|
142
178
|
false
|
143
179
|
end
|
180
|
+
|
181
|
+
def present?
|
182
|
+
true
|
183
|
+
end
|
144
184
|
end
|
145
185
|
|
146
186
|
class Time # :nodoc:
|
@@ -152,4 +192,8 @@ class Time # :nodoc:
|
|
152
192
|
def blank?
|
153
193
|
false
|
154
194
|
end
|
195
|
+
|
196
|
+
def present?
|
197
|
+
true
|
198
|
+
end
|
155
199
|
end
|
@@ -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
|
@@ -28,23 +28,32 @@ class Object
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
def duplicable?
|
37
|
-
false
|
38
|
-
end
|
31
|
+
methods_are_duplicable = begin
|
32
|
+
Object.instance_method(:duplicable?).dup
|
33
|
+
true
|
34
|
+
rescue TypeError
|
35
|
+
false
|
39
36
|
end
|
40
37
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
38
|
+
unless methods_are_duplicable
|
39
|
+
class Method
|
40
|
+
# Methods are not duplicable:
|
41
|
+
#
|
42
|
+
# method(:puts).duplicable? # => false
|
43
|
+
# method(:puts).dup # => TypeError: allocator undefined for Method
|
44
|
+
def duplicable?
|
45
|
+
false
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class UnboundMethod
|
50
|
+
# Unbound methods are not duplicable:
|
51
|
+
#
|
52
|
+
# method(:puts).unbind.duplicable? # => false
|
53
|
+
# method(:puts).unbind.dup # => TypeError: allocator undefined for UnboundMethod
|
54
|
+
def duplicable?
|
55
|
+
false
|
56
|
+
end
|
48
57
|
end
|
49
58
|
end
|
50
59
|
|
@@ -53,7 +62,7 @@ require "singleton"
|
|
53
62
|
module Singleton
|
54
63
|
# Singleton instances are not duplicable:
|
55
64
|
#
|
56
|
-
#
|
65
|
+
# Class.new.include(Singleton).instance.dup # TypeError (can't dup instance of singleton
|
57
66
|
def duplicable?
|
58
67
|
false
|
59
68
|
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,7 +12,9 @@ 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
20
|
# Returns an array of instance variable names as strings including "@".
|
@@ -25,6 +27,6 @@ class Object
|
|
25
27
|
#
|
26
28
|
# C.new(0, 1).instance_variable_names # => ["@y", "@x"]
|
27
29
|
def instance_variable_names
|
28
|
-
instance_variables.map(&:
|
30
|
+
instance_variables.map(&:name)
|
29
31
|
end
|
30
32
|
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"
|
@@ -29,7 +29,7 @@ require "active_support/core_ext/date/conversions"
|
|
29
29
|
# It should be noted that when using ::JSON.{generate,dump} directly, ActiveSupport's encoder is
|
30
30
|
# bypassed completely. This means that as_json won't be invoked and the JSON gem will simply
|
31
31
|
# ignore any options it does not natively understand. This also means that ::JSON.{generate,dump}
|
32
|
-
# should give exactly the same results with or without
|
32
|
+
# should give exactly the same results with or without Active Support.
|
33
33
|
|
34
34
|
module ActiveSupport
|
35
35
|
module ToJsonWithActiveSupportEncoder # :nodoc:
|
@@ -46,7 +46,7 @@ module ActiveSupport
|
|
46
46
|
end
|
47
47
|
|
48
48
|
[Enumerable, Object, Array, FalseClass, Float, Hash, Integer, NilClass, String, TrueClass].reverse_each do |klass|
|
49
|
-
klass.
|
49
|
+
klass.include(ActiveSupport::ToJsonWithActiveSupportEncoder)
|
50
50
|
end
|
51
51
|
|
52
52
|
class Module
|
@@ -65,9 +65,17 @@ class Object
|
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
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
|
+
|
68
76
|
class Struct # :nodoc:
|
69
77
|
def as_json(options = nil)
|
70
|
-
|
78
|
+
to_h.as_json(options)
|
71
79
|
end
|
72
80
|
end
|
73
81
|
|
@@ -225,9 +233,11 @@ class Pathname # :nodoc:
|
|
225
233
|
end
|
226
234
|
end
|
227
235
|
|
228
|
-
|
229
|
-
|
230
|
-
|
236
|
+
unless IPAddr.method_defined?(:as_json, false)
|
237
|
+
class IPAddr # :nodoc:
|
238
|
+
def as_json(options = nil)
|
239
|
+
to_s
|
240
|
+
end
|
231
241
|
end
|
232
242
|
end
|
233
243
|
|
@@ -72,8 +72,6 @@ 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
76
|
query = filter_map do |key, value|
|
79
77
|
unless (value.is_a?(Hash) || value.is_a?(Array)) && value.empty?
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Object
|
4
|
+
# Set and restore public attributes around a block.
|
5
|
+
#
|
6
|
+
# client.timeout # => 5
|
7
|
+
# client.with(timeout: 1) do |c|
|
8
|
+
# c.timeout # => 1
|
9
|
+
# end
|
10
|
+
# client.timeout # => 5
|
11
|
+
#
|
12
|
+
# The receiver is yielded to the provided block.
|
13
|
+
#
|
14
|
+
# This method is a shorthand for the common begin/ensure pattern:
|
15
|
+
#
|
16
|
+
# old_value = object.attribute
|
17
|
+
# begin
|
18
|
+
# object.attribute = new_value
|
19
|
+
# # do things
|
20
|
+
# ensure
|
21
|
+
# object.attribute = old_value
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# It can be used on any object as long as both the reader and writer methods
|
25
|
+
# are public.
|
26
|
+
def with(**attributes)
|
27
|
+
old_values = {}
|
28
|
+
begin
|
29
|
+
attributes.each do |key, value|
|
30
|
+
old_values[key] = public_send(key)
|
31
|
+
public_send("#{key}=", value)
|
32
|
+
end
|
33
|
+
yield self
|
34
|
+
ensure
|
35
|
+
old_values.each do |key, old_value|
|
36
|
+
public_send("#{key}=", old_value)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# #with isn't usable on immediates, so we might as well undefine the
|
43
|
+
# method in common immediate classes to avoid potential confusion.
|
44
|
+
[NilClass, TrueClass, FalseClass, Integer, Float, Symbol].each do |klass|
|
45
|
+
klass.undef_method(:with)
|
46
|
+
end
|
@@ -5,9 +5,9 @@ require "active_support/option_merger"
|
|
5
5
|
class Object
|
6
6
|
# An elegant way to factor duplication out of options passed to a series of
|
7
7
|
# method calls. Each method called in the block, with the block variable as
|
8
|
-
# the receiver, will have its options merged with the default +options+
|
9
|
-
# provided. Each method called on
|
10
|
-
# hash as its final argument.
|
8
|
+
# the receiver, will have its options merged with the default +options+
|
9
|
+
# <tt>Hash</tt> or <tt>Hash</tt>-like object provided. Each method called on
|
10
|
+
# the block variable must take an options hash as its final argument.
|
11
11
|
#
|
12
12
|
# Without <tt>with_options</tt>, this code contains duplication:
|
13
13
|
#
|
@@ -64,11 +64,11 @@ class Object
|
|
64
64
|
#
|
65
65
|
# Hence the inherited default for +if+ key is ignored.
|
66
66
|
#
|
67
|
-
# NOTE: You cannot call class methods implicitly inside of with_options
|
67
|
+
# NOTE: You cannot call class methods implicitly inside of +with_options+.
|
68
68
|
# You can access these methods using the class name instead:
|
69
69
|
#
|
70
70
|
# class Phone < ActiveRecord::Base
|
71
|
-
# enum phone_number_type
|
71
|
+
# enum :phone_number_type, { home: 0, office: 1, mobile: 2 }
|
72
72
|
#
|
73
73
|
# with_options presence: true do
|
74
74
|
# validates :phone_number_type, inclusion: { in: Phone.phone_number_types.keys }
|
@@ -83,11 +83,11 @@ class Object
|
|
83
83
|
# end
|
84
84
|
# end
|
85
85
|
#
|
86
|
-
#
|
87
|
-
# #
|
86
|
+
# styled.link_to "I'm red", "/"
|
87
|
+
# # => <a href="/" style="color: red;">I'm red</a>
|
88
88
|
#
|
89
|
-
#
|
90
|
-
# #
|
89
|
+
# styled.button_tag "I'm red too!"
|
90
|
+
# # => <button style="color: red;">I'm red too!</button>
|
91
91
|
#
|
92
92
|
def with_options(options, &block)
|
93
93
|
option_merger = ActiveSupport::OptionMerger.new(self, options)
|
@@ -13,4 +13,5 @@ require "active_support/core_ext/object/instance_variables"
|
|
13
13
|
require "active_support/core_ext/object/json"
|
14
14
|
require "active_support/core_ext/object/to_param"
|
15
15
|
require "active_support/core_ext/object/to_query"
|
16
|
+
require "active_support/core_ext/object/with"
|
16
17
|
require "active_support/core_ext/object/with_options"
|