activesupport 1.2.4 → 8.1.2
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 +7 -0
- data/CHANGELOG.md +505 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +40 -0
- data/lib/active_support/actionable_error.rb +50 -0
- data/lib/active_support/all.rb +5 -0
- data/lib/active_support/array_inquirer.rb +50 -0
- data/lib/active_support/backtrace_cleaner.rb +234 -0
- data/lib/active_support/benchmark.rb +21 -0
- data/lib/active_support/benchmarkable.rb +53 -0
- data/lib/active_support/broadcast_logger.rb +238 -0
- data/lib/active_support/builder.rb +8 -0
- 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 +244 -0
- data/lib/active_support/cache/mem_cache_store.rb +288 -0
- data/lib/active_support/cache/memory_store.rb +264 -0
- data/lib/active_support/cache/null_store.rb +62 -0
- data/lib/active_support/cache/redis_cache_store.rb +498 -0
- data/lib/active_support/cache/serializer_with_fallback.rb +152 -0
- data/lib/active_support/cache/strategy/local_cache.rb +246 -0
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +45 -0
- data/lib/active_support/cache.rb +1170 -0
- data/lib/active_support/callbacks.rb +960 -0
- data/lib/active_support/class_attribute.rb +33 -0
- data/lib/active_support/code_generator.rb +79 -0
- data/lib/active_support/concern.rb +217 -0
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +18 -0
- data/lib/active_support/concurrency/null_lock.rb +13 -0
- data/lib/active_support/concurrency/share_lock.rb +225 -0
- data/lib/active_support/concurrency/thread_monitor.rb +55 -0
- data/lib/active_support/configurable.rb +193 -0
- data/lib/active_support/configuration_file.rb +60 -0
- data/lib/active_support/continuous_integration.rb +145 -0
- data/lib/active_support/core_ext/array/access.rb +100 -0
- data/lib/active_support/core_ext/array/conversions.rb +209 -26
- data/lib/active_support/core_ext/array/extract.rb +21 -0
- data/lib/active_support/core_ext/array/extract_options.rb +31 -0
- data/lib/active_support/core_ext/array/grouping.rb +109 -0
- data/lib/active_support/core_ext/array/inquiry.rb +19 -0
- data/lib/active_support/core_ext/array/wrap.rb +48 -0
- data/lib/active_support/core_ext/array.rb +8 -4
- data/lib/active_support/core_ext/benchmark.rb +6 -0
- data/lib/active_support/core_ext/big_decimal/conversions.rb +14 -0
- data/lib/active_support/core_ext/big_decimal.rb +3 -0
- data/lib/active_support/core_ext/class/attribute.rb +137 -0
- data/lib/active_support/core_ext/class/attribute_accessors.rb +6 -0
- data/lib/active_support/core_ext/class/subclasses.rb +24 -0
- data/lib/active_support/core_ext/class.rb +4 -0
- data/lib/active_support/core_ext/date/acts_like.rb +10 -0
- data/lib/active_support/core_ext/date/blank.rb +18 -0
- data/lib/active_support/core_ext/date/calculations.rb +161 -0
- data/lib/active_support/core_ext/date/conversions.rb +95 -28
- data/lib/active_support/core_ext/date/zones.rb +8 -0
- data/lib/active_support/core_ext/date.rb +6 -5
- data/lib/active_support/core_ext/date_and_time/calculations.rb +374 -0
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +23 -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 +16 -0
- data/lib/active_support/core_ext/date_time/blank.rb +18 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +215 -0
- data/lib/active_support/core_ext/date_time/compatibility.rb +16 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +108 -0
- data/lib/active_support/core_ext/date_time.rb +7 -0
- data/lib/active_support/core_ext/digest/uuid.rb +76 -0
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/enumerable.rb +277 -7
- data/lib/active_support/core_ext/erb/util.rb +201 -0
- data/lib/active_support/core_ext/file/atomic.rb +72 -0
- data/lib/active_support/core_ext/file.rb +3 -0
- data/lib/active_support/core_ext/hash/conversions.rb +262 -0
- data/lib/active_support/core_ext/hash/deep_merge.rb +43 -0
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
- data/lib/active_support/core_ext/hash/except.rb +12 -0
- data/lib/active_support/core_ext/hash/indifferent_access.rb +19 -55
- data/lib/active_support/core_ext/hash/keys.rb +134 -44
- data/lib/active_support/core_ext/hash/reverse_merge.rb +22 -22
- data/lib/active_support/core_ext/hash/slice.rb +27 -0
- data/lib/active_support/core_ext/hash.rb +9 -8
- data/lib/active_support/core_ext/integer/inflections.rb +29 -13
- data/lib/active_support/core_ext/integer/multiple.rb +12 -0
- data/lib/active_support/core_ext/integer/time.rb +22 -0
- data/lib/active_support/core_ext/integer.rb +4 -6
- data/lib/active_support/core_ext/kernel/concern.rb +14 -0
- data/lib/active_support/core_ext/kernel/reporting.rb +45 -0
- data/lib/active_support/core_ext/kernel/singleton_class.rb +8 -0
- data/lib/active_support/core_ext/kernel.rb +4 -78
- data/lib/active_support/core_ext/load_error.rb +6 -35
- data/lib/active_support/core_ext/module/aliasing.rb +31 -0
- data/lib/active_support/core_ext/module/anonymous.rb +30 -0
- data/lib/active_support/core_ext/module/attr_internal.rb +48 -0
- data/lib/active_support/core_ext/module/attribute_accessors.rb +214 -0
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +175 -0
- data/lib/active_support/core_ext/module/concerning.rb +140 -0
- data/lib/active_support/core_ext/module/delegation.rb +225 -0
- data/lib/active_support/core_ext/module/deprecation.rb +25 -0
- data/lib/active_support/core_ext/module/introspection.rb +65 -0
- data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
- data/lib/active_support/core_ext/module/remove_method.rb +17 -0
- data/lib/active_support/core_ext/module.rb +13 -0
- data/lib/active_support/core_ext/name_error.rb +59 -0
- data/lib/active_support/core_ext/numeric/bytes.rb +73 -42
- data/lib/active_support/core_ext/numeric/conversions.rb +145 -0
- data/lib/active_support/core_ext/numeric/time.rb +64 -57
- data/lib/active_support/core_ext/numeric.rb +4 -6
- data/lib/active_support/core_ext/object/acts_like.rb +45 -0
- data/lib/active_support/core_ext/object/blank.rb +199 -0
- data/lib/active_support/core_ext/object/conversions.rb +6 -0
- data/lib/active_support/core_ext/object/deep_dup.rb +71 -0
- data/lib/active_support/core_ext/object/duplicable.rb +69 -0
- data/lib/active_support/core_ext/object/inclusion.rb +37 -0
- data/lib/active_support/core_ext/object/instance_variables.rb +32 -0
- data/lib/active_support/core_ext/object/json.rb +267 -0
- data/lib/active_support/core_ext/object/to_param.rb +3 -0
- data/lib/active_support/core_ext/object/to_query.rb +93 -0
- data/lib/active_support/core_ext/object/try.rb +158 -0
- data/lib/active_support/core_ext/object/with.rb +46 -0
- data/lib/active_support/core_ext/object/with_options.rb +101 -0
- data/lib/active_support/core_ext/object.rb +17 -0
- data/lib/active_support/core_ext/pathname/blank.rb +20 -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 +57 -0
- data/lib/active_support/core_ext/range/conversions.rb +58 -17
- data/lib/active_support/core_ext/range/overlap.rb +40 -0
- data/lib/active_support/core_ext/range/sole.rb +17 -0
- data/lib/active_support/core_ext/range.rb +5 -4
- data/lib/active_support/core_ext/regexp.rb +14 -0
- data/lib/active_support/core_ext/securerandom.rb +57 -0
- data/lib/active_support/core_ext/string/access.rb +93 -56
- data/lib/active_support/core_ext/string/behavior.rb +8 -0
- data/lib/active_support/core_ext/string/conversions.rb +57 -16
- data/lib/active_support/core_ext/string/exclude.rb +13 -0
- data/lib/active_support/core_ext/string/filters.rb +151 -0
- data/lib/active_support/core_ext/string/indent.rb +45 -0
- data/lib/active_support/core_ext/string/inflections.rb +297 -54
- data/lib/active_support/core_ext/string/inquiry.rb +16 -0
- data/lib/active_support/core_ext/string/multibyte.rb +67 -0
- data/lib/active_support/core_ext/string/output_safety.rb +235 -0
- data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -18
- data/lib/active_support/core_ext/string/strip.rb +27 -0
- data/lib/active_support/core_ext/string/zones.rb +16 -0
- data/lib/active_support/core_ext/string.rb +14 -10
- 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/thread/backtrace/location.rb +7 -0
- data/lib/active_support/core_ext/time/acts_like.rb +10 -0
- data/lib/active_support/core_ext/time/calculations.rb +358 -153
- data/lib/active_support/core_ext/time/compatibility.rb +15 -0
- data/lib/active_support/core_ext/time/conversions.rb +69 -30
- data/lib/active_support/core_ext/time/zones.rb +97 -0
- data/lib/active_support/core_ext/time.rb +6 -6
- data/lib/active_support/core_ext.rb +5 -1
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/current_attributes.rb +243 -0
- data/lib/active_support/deep_mergeable.rb +53 -0
- data/lib/active_support/delegation.rb +183 -0
- data/lib/active_support/dependencies/autoload.rb +72 -0
- data/lib/active_support/dependencies/interlock.rb +55 -0
- data/lib/active_support/dependencies/require_dependency.rb +28 -0
- data/lib/active_support/dependencies.rb +84 -222
- data/lib/active_support/deprecation/behaviors.rb +148 -0
- data/lib/active_support/deprecation/constant_accessor.rb +74 -0
- data/lib/active_support/deprecation/deprecators.rb +104 -0
- data/lib/active_support/deprecation/disallowed.rb +54 -0
- data/lib/active_support/deprecation/method_wrappers.rb +68 -0
- data/lib/active_support/deprecation/proxy_wrappers.rb +189 -0
- data/lib/active_support/deprecation/reporting.rb +162 -0
- data/lib/active_support/deprecation.rb +81 -0
- data/lib/active_support/deprecator.rb +7 -0
- data/lib/active_support/descendants_tracker.rb +112 -0
- 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 +64 -0
- data/lib/active_support/duration.rb +524 -0
- data/lib/active_support/editor.rb +70 -0
- data/lib/active_support/encrypted_configuration.rb +126 -0
- data/lib/active_support/encrypted_file.rb +133 -0
- data/lib/active_support/environment_inquirer.rb +40 -0
- data/lib/active_support/error_reporter/test_helper.rb +15 -0
- data/lib/active_support/error_reporter.rb +318 -0
- data/lib/active_support/event_reporter/test_helper.rb +32 -0
- data/lib/active_support/event_reporter.rb +592 -0
- data/lib/active_support/evented_file_update_checker.rb +185 -0
- data/lib/active_support/execution_context/test_helper.rb +13 -0
- data/lib/active_support/execution_context.rb +110 -0
- data/lib/active_support/execution_wrapper.rb +150 -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 +166 -0
- data/lib/active_support/fork_tracker.rb +43 -0
- data/lib/active_support/gem_version.rb +17 -0
- data/lib/active_support/gzip.rb +41 -0
- data/lib/active_support/hash_with_indifferent_access.rb +464 -0
- data/lib/active_support/html_safe_translation.rb +56 -0
- data/lib/active_support/i18n.rb +17 -0
- data/lib/active_support/i18n_railtie.rb +140 -0
- data/lib/active_support/inflections.rb +68 -49
- data/lib/active_support/inflector/inflections.rb +290 -0
- data/lib/active_support/inflector/methods.rb +387 -0
- data/lib/active_support/inflector/transliterate.rb +147 -0
- data/lib/active_support/inflector.rb +7 -164
- data/lib/active_support/isolated_execution_state.rb +76 -0
- data/lib/active_support/json/decoding.rb +78 -0
- data/lib/active_support/json/encoding.rb +256 -0
- data/lib/active_support/json.rb +4 -0
- data/lib/active_support/key_generator.rb +66 -0
- data/lib/active_support/lazy_load_hooks.rb +107 -0
- data/lib/active_support/locale/en.rb +33 -0
- data/lib/active_support/locale/en.yml +141 -0
- data/lib/active_support/log_subscriber/test_helper.rb +106 -0
- data/lib/active_support/log_subscriber.rb +188 -0
- data/lib/active_support/logger.rb +55 -0
- data/lib/active_support/logger_silence.rb +21 -0
- data/lib/active_support/logger_thread_safe_level.rb +50 -0
- data/lib/active_support/message_encryptor.rb +374 -0
- data/lib/active_support/message_encryptors.rb +193 -0
- data/lib/active_support/message_pack/cache_serializer.rb +23 -0
- data/lib/active_support/message_pack/extensions.rb +310 -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 +377 -0
- data/lib/active_support/message_verifiers.rb +189 -0
- data/lib/active_support/messages/codec.rb +65 -0
- data/lib/active_support/messages/metadata.rb +146 -0
- data/lib/active_support/messages/rotation_configuration.rb +23 -0
- data/lib/active_support/messages/rotation_coordinator.rb +102 -0
- data/lib/active_support/messages/rotator.rb +69 -0
- data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
- data/lib/active_support/multibyte/chars.rb +188 -0
- data/lib/active_support/multibyte/unicode.rb +42 -0
- data/lib/active_support/multibyte.rb +27 -0
- data/lib/active_support/notifications/fanout.rb +467 -0
- data/lib/active_support/notifications/instrumenter.rb +240 -0
- data/lib/active_support/notifications.rb +281 -0
- data/lib/active_support/number_helper/number_converter.rb +190 -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 +60 -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 +479 -0
- data/lib/active_support/option_merger.rb +38 -0
- data/lib/active_support/ordered_hash.rb +50 -0
- data/lib/active_support/ordered_options.rb +141 -25
- data/lib/active_support/parameter_filter.rb +157 -0
- data/lib/active_support/rails.rb +26 -0
- data/lib/active_support/railtie.rb +180 -0
- data/lib/active_support/reloader.rb +138 -0
- data/lib/active_support/rescuable.rb +176 -0
- data/lib/active_support/secure_compare_rotator.rb +58 -0
- data/lib/active_support/security_utils.rb +38 -0
- data/lib/active_support/string_inquirer.rb +35 -0
- data/lib/active_support/structured_event_subscriber.rb +99 -0
- data/lib/active_support/subscriber.rb +141 -0
- data/lib/active_support/syntax_error_proxy.rb +67 -0
- data/lib/active_support/tagged_logging.rb +157 -0
- data/lib/active_support/test_case.rb +365 -0
- data/lib/active_support/testing/assertions.rb +369 -0
- data/lib/active_support/testing/autorun.rb +10 -0
- data/lib/active_support/testing/constant_lookup.rb +51 -0
- data/lib/active_support/testing/constant_stubbing.rb +54 -0
- data/lib/active_support/testing/declarative.rb +28 -0
- data/lib/active_support/testing/deprecation.rb +82 -0
- data/lib/active_support/testing/error_reporter_assertions.rb +124 -0
- data/lib/active_support/testing/event_reporter_assertions.rb +227 -0
- data/lib/active_support/testing/file_fixtures.rb +38 -0
- data/lib/active_support/testing/isolation.rb +121 -0
- data/lib/active_support/testing/method_call_assertions.rb +69 -0
- data/lib/active_support/testing/notification_assertions.rb +92 -0
- data/lib/active_support/testing/parallelization/server.rb +98 -0
- data/lib/active_support/testing/parallelization/worker.rb +107 -0
- data/lib/active_support/testing/parallelization.rb +79 -0
- data/lib/active_support/testing/parallelize_executor.rb +81 -0
- data/lib/active_support/testing/setup_and_teardown.rb +57 -0
- data/lib/active_support/testing/stream.rb +41 -0
- data/lib/active_support/testing/tagged_logging.rb +27 -0
- data/lib/active_support/testing/tests_without_assertions.rb +19 -0
- data/lib/active_support/testing/time_helpers.rb +273 -0
- data/lib/active_support/time.rb +20 -0
- data/lib/active_support/time_with_zone.rb +613 -0
- data/lib/active_support/values/time_zone.rb +599 -158
- data/lib/active_support/version.rb +7 -6
- data/lib/active_support/xml_mini/jdom.rb +175 -0
- data/lib/active_support/xml_mini/libxml.rb +80 -0
- data/lib/active_support/xml_mini/libxmlsax.rb +83 -0
- data/lib/active_support/xml_mini/nokogiri.rb +83 -0
- data/lib/active_support/xml_mini/nokogirisax.rb +86 -0
- data/lib/active_support/xml_mini/rexml.rb +137 -0
- data/lib/active_support/xml_mini.rb +212 -0
- data/lib/active_support.rb +122 -10
- metadata +524 -93
- data/CHANGELOG +0 -283
- data/lib/active_support/binding_of_caller.rb +0 -84
- data/lib/active_support/breakpoint.rb +0 -523
- data/lib/active_support/class_attribute_accessors.rb +0 -57
- data/lib/active_support/class_inheritable_attributes.rb +0 -117
- data/lib/active_support/clean_logger.rb +0 -36
- data/lib/active_support/core_ext/blank.rb +0 -38
- data/lib/active_support/core_ext/cgi/escape_skipping_slashes.rb +0 -14
- data/lib/active_support/core_ext/cgi.rb +0 -5
- data/lib/active_support/core_ext/exception.rb +0 -29
- data/lib/active_support/core_ext/integer/even_odd.rb +0 -24
- data/lib/active_support/core_ext/object_and_class.rb +0 -44
- data/lib/active_support/module_attribute_accessors.rb +0 -57
- data/lib/active_support/whiny_nil.rb +0 -38
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_support/core_ext/big_decimal/conversions"
|
|
4
|
+
require "active_support/number_helper"
|
|
5
|
+
|
|
6
|
+
module ActiveSupport
|
|
7
|
+
module NumericWithFormat
|
|
8
|
+
# \Numeric With Format
|
|
9
|
+
#
|
|
10
|
+
# Provides options for converting numbers into formatted strings.
|
|
11
|
+
# Options are provided for phone numbers, currency, percentage,
|
|
12
|
+
# precision, positional notation, file size, and pretty printing.
|
|
13
|
+
#
|
|
14
|
+
# This method is aliased to <tt>to_formatted_s</tt>.
|
|
15
|
+
#
|
|
16
|
+
# ==== Options
|
|
17
|
+
#
|
|
18
|
+
# For details on which formats use which options, see ActiveSupport::NumberHelper
|
|
19
|
+
#
|
|
20
|
+
# ==== Examples
|
|
21
|
+
#
|
|
22
|
+
# Phone Numbers:
|
|
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: '.')
|
|
30
|
+
# # => "+1.123.555.1234 x 1343"
|
|
31
|
+
#
|
|
32
|
+
# Currency:
|
|
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)')
|
|
39
|
+
# # => "($1,234,567,890.50)"
|
|
40
|
+
# 1234567890.50.to_fs(:currency, unit: '£', separator: ',', delimiter: '')
|
|
41
|
+
# # => "£1234567890,50"
|
|
42
|
+
# 1234567890.50.to_fs(:currency, unit: '£', separator: ',', delimiter: '', format: '%n %u')
|
|
43
|
+
# # => "1234567890,50 £"
|
|
44
|
+
#
|
|
45
|
+
# Percentage:
|
|
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 %"
|
|
53
|
+
#
|
|
54
|
+
# Delimited:
|
|
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: ',')
|
|
62
|
+
# # => "98 765 432,98"
|
|
63
|
+
#
|
|
64
|
+
# Rounded:
|
|
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)
|
|
75
|
+
# # => "13"
|
|
76
|
+
# 389.32314.to_fs(:rounded, precision: 4, significant: true) # => "389.3"
|
|
77
|
+
# 1111.2345.to_fs(:rounded, precision: 2, separator: ',', delimiter: '.')
|
|
78
|
+
# # => "1.111,23"
|
|
79
|
+
#
|
|
80
|
+
# Human-friendly size in Bytes:
|
|
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"
|
|
95
|
+
#
|
|
96
|
+
# Human-friendly format:
|
|
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,
|
|
111
|
+
# separator: ',',
|
|
112
|
+
# significant: false) # => "1,2 Million"
|
|
113
|
+
def to_fs(format = nil, options = nil)
|
|
114
|
+
return to_s if format.nil?
|
|
115
|
+
|
|
116
|
+
case format
|
|
117
|
+
when Integer, String
|
|
118
|
+
to_s(format)
|
|
119
|
+
when :phone
|
|
120
|
+
ActiveSupport::NumberHelper.number_to_phone(self, options || {})
|
|
121
|
+
when :currency
|
|
122
|
+
ActiveSupport::NumberHelper.number_to_currency(self, options || {})
|
|
123
|
+
when :percentage
|
|
124
|
+
ActiveSupport::NumberHelper.number_to_percentage(self, options || {})
|
|
125
|
+
when :delimited
|
|
126
|
+
ActiveSupport::NumberHelper.number_to_delimited(self, options || {})
|
|
127
|
+
when :rounded
|
|
128
|
+
ActiveSupport::NumberHelper.number_to_rounded(self, options || {})
|
|
129
|
+
when :human
|
|
130
|
+
ActiveSupport::NumberHelper.number_to_human(self, options || {})
|
|
131
|
+
when :human_size
|
|
132
|
+
ActiveSupport::NumberHelper.number_to_human_size(self, options || {})
|
|
133
|
+
when Symbol
|
|
134
|
+
to_s
|
|
135
|
+
else
|
|
136
|
+
to_s(format)
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
alias_method :to_formatted_s, :to_fs
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
Integer.include ActiveSupport::NumericWithFormat
|
|
144
|
+
Float.include ActiveSupport::NumericWithFormat
|
|
145
|
+
BigDecimal.include ActiveSupport::NumericWithFormat
|
|
@@ -1,59 +1,66 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_support/duration"
|
|
4
|
+
require "active_support/core_ext/time/calculations"
|
|
5
|
+
require "active_support/core_ext/time/acts_like"
|
|
6
|
+
require "active_support/core_ext/date/calculations"
|
|
7
|
+
require "active_support/core_ext/date/acts_like"
|
|
8
|
+
|
|
9
|
+
class Numeric
|
|
10
|
+
# Returns a Duration instance matching the number of seconds provided.
|
|
11
|
+
#
|
|
12
|
+
# 2.seconds # => 2 seconds
|
|
13
|
+
def seconds
|
|
14
|
+
ActiveSupport::Duration.seconds(self)
|
|
15
|
+
end
|
|
16
|
+
alias :second :seconds
|
|
17
|
+
|
|
18
|
+
# Returns a Duration instance matching the number of minutes provided.
|
|
19
|
+
#
|
|
20
|
+
# 2.minutes # => 2 minutes
|
|
21
|
+
def minutes
|
|
22
|
+
ActiveSupport::Duration.minutes(self)
|
|
23
|
+
end
|
|
24
|
+
alias :minute :minutes
|
|
25
|
+
|
|
26
|
+
# Returns a Duration instance matching the number of hours provided.
|
|
27
|
+
#
|
|
28
|
+
# 2.hours # => 2 hours
|
|
29
|
+
def hours
|
|
30
|
+
ActiveSupport::Duration.hours(self)
|
|
31
|
+
end
|
|
32
|
+
alias :hour :hours
|
|
33
|
+
|
|
34
|
+
# Returns a Duration instance matching the number of days provided.
|
|
35
|
+
#
|
|
36
|
+
# 2.days # => 2 days
|
|
37
|
+
def days
|
|
38
|
+
ActiveSupport::Duration.days(self)
|
|
39
|
+
end
|
|
40
|
+
alias :day :days
|
|
41
|
+
|
|
42
|
+
# Returns a Duration instance matching the number of weeks provided.
|
|
43
|
+
#
|
|
44
|
+
# 2.weeks # => 2 weeks
|
|
45
|
+
def weeks
|
|
46
|
+
ActiveSupport::Duration.weeks(self)
|
|
47
|
+
end
|
|
48
|
+
alias :week :weeks
|
|
49
|
+
|
|
50
|
+
# Returns a Duration instance matching the number of fortnights provided.
|
|
51
|
+
#
|
|
52
|
+
# 2.fortnights # => 4 weeks
|
|
53
|
+
def fortnights
|
|
54
|
+
ActiveSupport::Duration.weeks(self * 2)
|
|
55
|
+
end
|
|
56
|
+
alias :fortnight :fortnights
|
|
57
|
+
|
|
58
|
+
# Returns the number of milliseconds equivalent to the seconds provided.
|
|
59
|
+
# Used with the standard time durations.
|
|
60
|
+
#
|
|
61
|
+
# 2.in_milliseconds # => 2000
|
|
62
|
+
# 1.hour.in_milliseconds # => 3600000
|
|
63
|
+
def in_milliseconds
|
|
64
|
+
self * 1000
|
|
58
65
|
end
|
|
59
66
|
end
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
require File.dirname(__FILE__) + '/numeric/bytes'
|
|
1
|
+
# frozen_string_literal: true
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
end
|
|
3
|
+
require_relative "numeric/bytes"
|
|
4
|
+
require_relative "numeric/time"
|
|
5
|
+
require_relative "numeric/conversions"
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class Object
|
|
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
|
+
#
|
|
33
|
+
def acts_like?(duck)
|
|
34
|
+
case duck
|
|
35
|
+
when :time
|
|
36
|
+
respond_to? :acts_like_time?
|
|
37
|
+
when :date
|
|
38
|
+
respond_to? :acts_like_date?
|
|
39
|
+
when :string
|
|
40
|
+
respond_to? :acts_like_string?
|
|
41
|
+
else
|
|
42
|
+
respond_to? :"acts_like_#{duck}?"
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "concurrent/map"
|
|
4
|
+
|
|
5
|
+
class Object
|
|
6
|
+
# An object is blank if it's false, empty, or a whitespace string.
|
|
7
|
+
# For example, +nil+, '', ' ', [], {}, and +false+ are all blank.
|
|
8
|
+
#
|
|
9
|
+
# This simplifies
|
|
10
|
+
#
|
|
11
|
+
# !address || address.empty?
|
|
12
|
+
#
|
|
13
|
+
# to
|
|
14
|
+
#
|
|
15
|
+
# address.blank?
|
|
16
|
+
#
|
|
17
|
+
# @return [true, false]
|
|
18
|
+
def blank?
|
|
19
|
+
respond_to?(:empty?) ? !!empty? : false
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# An object is present if it's not blank.
|
|
23
|
+
#
|
|
24
|
+
# @return [true, false]
|
|
25
|
+
def present?
|
|
26
|
+
!blank?
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Returns the receiver if it's present otherwise returns +nil+.
|
|
30
|
+
# <tt>object.presence</tt> is equivalent to
|
|
31
|
+
#
|
|
32
|
+
# object.present? ? object : nil
|
|
33
|
+
#
|
|
34
|
+
# For example, something like
|
|
35
|
+
#
|
|
36
|
+
# state = params[:state] if params[:state].present?
|
|
37
|
+
# country = params[:country] if params[:country].present?
|
|
38
|
+
# region = state || country || 'US'
|
|
39
|
+
#
|
|
40
|
+
# becomes
|
|
41
|
+
#
|
|
42
|
+
# region = params[:state].presence || params[:country].presence || 'US'
|
|
43
|
+
#
|
|
44
|
+
# @return [Object]
|
|
45
|
+
def presence
|
|
46
|
+
self if present?
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
class NilClass
|
|
51
|
+
# +nil+ is blank:
|
|
52
|
+
#
|
|
53
|
+
# nil.blank? # => true
|
|
54
|
+
#
|
|
55
|
+
# @return [true]
|
|
56
|
+
def blank?
|
|
57
|
+
true
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def present? # :nodoc:
|
|
61
|
+
false
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
class FalseClass
|
|
66
|
+
# +false+ is blank:
|
|
67
|
+
#
|
|
68
|
+
# false.blank? # => true
|
|
69
|
+
#
|
|
70
|
+
# @return [true]
|
|
71
|
+
def blank?
|
|
72
|
+
true
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def present? # :nodoc:
|
|
76
|
+
false
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
class TrueClass
|
|
81
|
+
# +true+ is not blank:
|
|
82
|
+
#
|
|
83
|
+
# true.blank? # => false
|
|
84
|
+
#
|
|
85
|
+
# @return [false]
|
|
86
|
+
def blank?
|
|
87
|
+
false
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def present? # :nodoc:
|
|
91
|
+
true
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
class Array
|
|
96
|
+
# An array is blank if it's empty:
|
|
97
|
+
#
|
|
98
|
+
# [].blank? # => true
|
|
99
|
+
# [1,2,3].blank? # => false
|
|
100
|
+
#
|
|
101
|
+
# @return [true, false]
|
|
102
|
+
alias_method :blank?, :empty?
|
|
103
|
+
|
|
104
|
+
def present? # :nodoc:
|
|
105
|
+
!empty?
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
class Hash
|
|
110
|
+
# A hash is blank if it's empty:
|
|
111
|
+
#
|
|
112
|
+
# {}.blank? # => true
|
|
113
|
+
# { key: 'value' }.blank? # => false
|
|
114
|
+
#
|
|
115
|
+
# @return [true, false]
|
|
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
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
class String
|
|
136
|
+
BLANK_RE = /\A[[:space:]]*\z/
|
|
137
|
+
ENCODED_BLANKS = Concurrent::Map.new do |h, enc|
|
|
138
|
+
h[enc] = Regexp.new(BLANK_RE.source.encode(enc), BLANK_RE.options | Regexp::FIXEDENCODING)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# A string is blank if it's empty or contains whitespaces only:
|
|
142
|
+
#
|
|
143
|
+
# ''.blank? # => true
|
|
144
|
+
# ' '.blank? # => true
|
|
145
|
+
# "\t\n\r".blank? # => true
|
|
146
|
+
# ' blah '.blank? # => false
|
|
147
|
+
#
|
|
148
|
+
# Unicode whitespace is supported:
|
|
149
|
+
#
|
|
150
|
+
# "\u00a0".blank? # => true
|
|
151
|
+
#
|
|
152
|
+
# @return [true, false]
|
|
153
|
+
def blank?
|
|
154
|
+
# The regexp that matches blank strings is expensive. For the case of empty
|
|
155
|
+
# strings we can speed up this method (~3.5x) with an empty? call. The
|
|
156
|
+
# penalty for the rest of strings is marginal.
|
|
157
|
+
empty? ||
|
|
158
|
+
begin
|
|
159
|
+
BLANK_RE.match?(self)
|
|
160
|
+
rescue Encoding::CompatibilityError
|
|
161
|
+
ENCODED_BLANKS[self.encoding].match?(self)
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def present? # :nodoc:
|
|
166
|
+
!blank?
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
class Numeric # :nodoc:
|
|
171
|
+
# No number is blank:
|
|
172
|
+
#
|
|
173
|
+
# 1.blank? # => false
|
|
174
|
+
# 0.blank? # => false
|
|
175
|
+
#
|
|
176
|
+
# @return [false]
|
|
177
|
+
def blank?
|
|
178
|
+
false
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def present?
|
|
182
|
+
true
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
class Time # :nodoc:
|
|
187
|
+
# No Time is blank:
|
|
188
|
+
#
|
|
189
|
+
# Time.now.blank? # => false
|
|
190
|
+
#
|
|
191
|
+
# @return [false]
|
|
192
|
+
def blank?
|
|
193
|
+
false
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def present?
|
|
197
|
+
true
|
|
198
|
+
end
|
|
199
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_support/core_ext/object/duplicable"
|
|
4
|
+
|
|
5
|
+
class Object
|
|
6
|
+
# Returns a deep copy of object if it's duplicable. If it's
|
|
7
|
+
# not duplicable, returns +self+.
|
|
8
|
+
#
|
|
9
|
+
# object = Object.new
|
|
10
|
+
# dup = object.deep_dup
|
|
11
|
+
# dup.instance_variable_set(:@a, 1)
|
|
12
|
+
#
|
|
13
|
+
# object.instance_variable_defined?(:@a) # => false
|
|
14
|
+
# dup.instance_variable_defined?(:@a) # => true
|
|
15
|
+
def deep_dup
|
|
16
|
+
duplicable? ? dup : self
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class Array
|
|
21
|
+
# Returns a deep copy of array.
|
|
22
|
+
#
|
|
23
|
+
# array = [1, [2, 3]]
|
|
24
|
+
# dup = array.deep_dup
|
|
25
|
+
# dup[1][2] = 4
|
|
26
|
+
#
|
|
27
|
+
# array[1][2] # => nil
|
|
28
|
+
# dup[1][2] # => 4
|
|
29
|
+
def deep_dup
|
|
30
|
+
map(&:deep_dup)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
class Hash
|
|
35
|
+
# Returns a deep copy of hash.
|
|
36
|
+
#
|
|
37
|
+
# hash = { a: { b: 'b' } }
|
|
38
|
+
# dup = hash.deep_dup
|
|
39
|
+
# dup[:a][:c] = 'c'
|
|
40
|
+
#
|
|
41
|
+
# hash[:a][:c] # => nil
|
|
42
|
+
# dup[:a][:c] # => "c"
|
|
43
|
+
def deep_dup
|
|
44
|
+
hash = dup
|
|
45
|
+
each_pair do |key, value|
|
|
46
|
+
if ::String === key || ::Symbol === key
|
|
47
|
+
hash[key] = value.deep_dup
|
|
48
|
+
else
|
|
49
|
+
hash.delete(key)
|
|
50
|
+
hash[key.deep_dup] = value.deep_dup
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
hash
|
|
54
|
+
end
|
|
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
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#--
|
|
4
|
+
# Most objects are cloneable, but not all. For example you can't dup methods:
|
|
5
|
+
#
|
|
6
|
+
# method(:puts).dup # => TypeError: allocator undefined for Method
|
|
7
|
+
#
|
|
8
|
+
# Classes may signal their instances are not duplicable removing +dup+/+clone+
|
|
9
|
+
# or raising exceptions from them. So, to dup an arbitrary object you normally
|
|
10
|
+
# use an optimistic approach and are ready to catch an exception, say:
|
|
11
|
+
#
|
|
12
|
+
# arbitrary_object.dup rescue object
|
|
13
|
+
#
|
|
14
|
+
# Rails dups objects in a few critical spots where they are not that arbitrary.
|
|
15
|
+
# That rescue is very expensive (like 40 times slower than a predicate), and it
|
|
16
|
+
# is often triggered.
|
|
17
|
+
#
|
|
18
|
+
# That's why we hardcode the following cases and check duplicable? instead of
|
|
19
|
+
# using that rescue idiom.
|
|
20
|
+
#++
|
|
21
|
+
class Object
|
|
22
|
+
# Can you safely dup this object?
|
|
23
|
+
#
|
|
24
|
+
# False for method objects;
|
|
25
|
+
# true otherwise.
|
|
26
|
+
def duplicable?
|
|
27
|
+
true
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
methods_are_duplicable = begin
|
|
32
|
+
Object.instance_method(:duplicable?).dup
|
|
33
|
+
true
|
|
34
|
+
rescue TypeError
|
|
35
|
+
false
|
|
36
|
+
end
|
|
37
|
+
|
|
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
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
require "singleton"
|
|
61
|
+
|
|
62
|
+
module Singleton
|
|
63
|
+
# Singleton instances are not duplicable:
|
|
64
|
+
#
|
|
65
|
+
# Class.new.include(Singleton).instance.dup # TypeError (can't dup instance of singleton
|
|
66
|
+
def duplicable?
|
|
67
|
+
false
|
|
68
|
+
end
|
|
69
|
+
end
|