activesupport 5.0.0 → 6.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activesupport might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +343 -590
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -4
- data/lib/active_support/actionable_error.rb +48 -0
- data/lib/active_support/all.rb +5 -3
- data/lib/active_support/array_inquirer.rb +11 -5
- data/lib/active_support/backtrace_cleaner.rb +33 -5
- data/lib/active_support/benchmarkable.rb +5 -3
- data/lib/active_support/builder.rb +3 -1
- data/lib/active_support/cache/file_store.rb +45 -53
- data/lib/active_support/cache/mem_cache_store.rb +81 -79
- data/lib/active_support/cache/memory_store.rb +69 -41
- data/lib/active_support/cache/null_store.rb +11 -4
- data/lib/active_support/cache/redis_cache_store.rb +493 -0
- data/lib/active_support/cache/strategy/local_cache.rb +74 -37
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
- data/lib/active_support/cache.rb +332 -161
- data/lib/active_support/callbacks.rb +657 -586
- data/lib/active_support/concern.rb +79 -6
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +35 -0
- data/lib/active_support/concurrency/share_lock.rb +59 -19
- data/lib/active_support/configurable.rb +15 -17
- data/lib/active_support/configuration_file.rb +46 -0
- data/lib/active_support/core_ext/array/access.rb +21 -7
- data/lib/active_support/core_ext/array/conversions.rb +20 -18
- data/lib/active_support/core_ext/array/extract.rb +21 -0
- data/lib/active_support/core_ext/array/extract_options.rb +2 -0
- data/lib/active_support/core_ext/array/grouping.rb +3 -1
- data/lib/active_support/core_ext/array/inquiry.rb +3 -1
- data/lib/active_support/core_ext/array/wrap.rb +2 -0
- data/lib/active_support/core_ext/array.rb +9 -7
- data/lib/active_support/core_ext/benchmark.rb +5 -3
- data/lib/active_support/core_ext/big_decimal/conversions.rb +6 -6
- data/lib/active_support/core_ext/big_decimal.rb +3 -1
- data/lib/active_support/core_ext/class/attribute.rb +52 -49
- data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
- data/lib/active_support/core_ext/class/subclasses.rb +18 -26
- data/lib/active_support/core_ext/class.rb +4 -2
- data/lib/active_support/core_ext/date/acts_like.rb +3 -1
- data/lib/active_support/core_ext/date/blank.rb +3 -1
- data/lib/active_support/core_ext/date/calculations.rb +16 -13
- data/lib/active_support/core_ext/date/conversions.rb +23 -21
- data/lib/active_support/core_ext/date/zones.rb +4 -2
- data/lib/active_support/core_ext/date.rb +7 -5
- data/lib/active_support/core_ext/date_and_time/calculations.rb +82 -53
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +18 -5
- data/lib/active_support/core_ext/date_and_time/zones.rb +9 -9
- data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
- data/lib/active_support/core_ext/date_time/blank.rb +3 -1
- data/lib/active_support/core_ext/date_time/calculations.rb +23 -11
- data/lib/active_support/core_ext/date_time/compatibility.rb +15 -2
- data/lib/active_support/core_ext/date_time/conversions.rb +14 -13
- data/lib/active_support/core_ext/date_time.rb +7 -5
- data/lib/active_support/core_ext/digest/uuid.rb +7 -5
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/enumerable.rb +165 -29
- data/lib/active_support/core_ext/file/atomic.rb +7 -5
- data/lib/active_support/core_ext/file.rb +3 -1
- data/lib/active_support/core_ext/hash/conversions.rb +40 -39
- data/lib/active_support/core_ext/hash/deep_merge.rb +8 -12
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
- data/lib/active_support/core_ext/hash/except.rb +4 -2
- data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -2
- data/lib/active_support/core_ext/hash/keys.rb +9 -36
- data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
- data/lib/active_support/core_ext/hash/slice.rb +8 -29
- data/lib/active_support/core_ext/hash.rb +10 -9
- data/lib/active_support/core_ext/integer/inflections.rb +3 -1
- data/lib/active_support/core_ext/integer/multiple.rb +3 -1
- data/lib/active_support/core_ext/integer/time.rb +11 -18
- data/lib/active_support/core_ext/integer.rb +5 -3
- data/lib/active_support/core_ext/kernel/concern.rb +3 -1
- data/lib/active_support/core_ext/kernel/reporting.rb +3 -1
- data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
- data/lib/active_support/core_ext/kernel.rb +5 -4
- data/lib/active_support/core_ext/load_error.rb +2 -23
- data/lib/active_support/core_ext/marshal.rb +6 -2
- data/lib/active_support/core_ext/module/aliasing.rb +5 -48
- data/lib/active_support/core_ext/module/anonymous.rb +2 -0
- data/lib/active_support/core_ext/module/attr_internal.rb +7 -5
- data/lib/active_support/core_ext/module/attribute_accessors.rb +53 -59
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +31 -24
- data/lib/active_support/core_ext/module/concerning.rb +16 -11
- data/lib/active_support/core_ext/module/delegation.rb +159 -44
- data/lib/active_support/core_ext/module/deprecation.rb +2 -0
- data/lib/active_support/core_ext/module/introspection.rb +23 -26
- data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
- data/lib/active_support/core_ext/module/remove_method.rb +5 -23
- data/lib/active_support/core_ext/module.rb +13 -12
- data/lib/active_support/core_ext/name_error.rb +36 -2
- data/lib/active_support/core_ext/numeric/bytes.rb +2 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +129 -134
- data/lib/active_support/core_ext/numeric/time.rb +18 -26
- data/lib/active_support/core_ext/numeric.rb +5 -4
- data/lib/active_support/core_ext/object/acts_like.rb +12 -1
- data/lib/active_support/core_ext/object/blank.rb +14 -2
- data/lib/active_support/core_ext/object/conversions.rb +6 -4
- data/lib/active_support/core_ext/object/deep_dup.rb +4 -2
- data/lib/active_support/core_ext/object/duplicable.rb +13 -62
- data/lib/active_support/core_ext/object/inclusion.rb +3 -1
- data/lib/active_support/core_ext/object/instance_variables.rb +2 -0
- data/lib/active_support/core_ext/object/json.rb +42 -15
- data/lib/active_support/core_ext/object/to_param.rb +3 -1
- data/lib/active_support/core_ext/object/to_query.rb +10 -5
- data/lib/active_support/core_ext/object/try.rb +20 -8
- data/lib/active_support/core_ext/object/with_options.rb +15 -2
- data/lib/active_support/core_ext/object.rb +14 -12
- data/lib/active_support/core_ext/range/compare_range.rb +82 -0
- data/lib/active_support/core_ext/range/conversions.rb +35 -25
- data/lib/active_support/core_ext/range/each.rb +5 -2
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +28 -0
- data/lib/active_support/core_ext/range/overlaps.rb +2 -0
- data/lib/active_support/core_ext/range.rb +7 -4
- data/lib/active_support/core_ext/regexp.rb +10 -1
- data/lib/active_support/core_ext/securerandom.rb +28 -6
- data/lib/active_support/core_ext/string/access.rb +9 -18
- data/lib/active_support/core_ext/string/behavior.rb +2 -0
- data/lib/active_support/core_ext/string/conversions.rb +5 -2
- data/lib/active_support/core_ext/string/exclude.rb +2 -0
- data/lib/active_support/core_ext/string/filters.rb +47 -4
- data/lib/active_support/core_ext/string/indent.rb +6 -4
- data/lib/active_support/core_ext/string/inflections.rb +78 -29
- data/lib/active_support/core_ext/string/inquiry.rb +4 -1
- data/lib/active_support/core_ext/string/multibyte.rb +10 -5
- data/lib/active_support/core_ext/string/output_safety.rb +86 -31
- data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
- data/lib/active_support/core_ext/string/strip.rb +5 -1
- data/lib/active_support/core_ext/string/zones.rb +4 -2
- data/lib/active_support/core_ext/string.rb +15 -13
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
- data/lib/active_support/core_ext/symbol.rb +3 -0
- data/lib/active_support/core_ext/time/acts_like.rb +3 -1
- data/lib/active_support/core_ext/time/calculations.rb +117 -45
- data/lib/active_support/core_ext/time/compatibility.rb +13 -2
- data/lib/active_support/core_ext/time/conversions.rb +18 -12
- data/lib/active_support/core_ext/time/zones.rb +9 -7
- data/lib/active_support/core_ext/time.rb +7 -5
- data/lib/active_support/core_ext/uri.rb +12 -7
- data/lib/active_support/core_ext.rb +3 -2
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/current_attributes.rb +208 -0
- data/lib/active_support/dependencies/autoload.rb +2 -0
- data/lib/active_support/dependencies/interlock.rb +7 -1
- data/lib/active_support/dependencies/zeitwerk_integration.rb +117 -0
- data/lib/active_support/dependencies.rb +172 -98
- data/lib/active_support/deprecation/behaviors.rb +45 -13
- data/lib/active_support/deprecation/constant_accessor.rb +52 -0
- data/lib/active_support/deprecation/disallowed.rb +56 -0
- data/lib/active_support/deprecation/instance_delegator.rb +16 -2
- data/lib/active_support/deprecation/method_wrappers.rb +32 -17
- data/lib/active_support/deprecation/proxy_wrappers.rb +35 -7
- data/lib/active_support/deprecation/reporting.rb +61 -16
- data/lib/active_support/deprecation.rb +17 -9
- data/lib/active_support/descendants_tracker.rb +61 -9
- data/lib/active_support/digest.rb +20 -0
- data/lib/active_support/duration/iso8601_parser.rb +67 -66
- data/lib/active_support/duration/iso8601_serializer.rb +25 -17
- data/lib/active_support/duration.rb +349 -46
- data/lib/active_support/encrypted_configuration.rb +45 -0
- data/lib/active_support/encrypted_file.rb +117 -0
- data/lib/active_support/environment_inquirer.rb +20 -0
- data/lib/active_support/evented_file_update_checker.rb +88 -112
- data/lib/active_support/execution_wrapper.rb +25 -13
- data/lib/active_support/executor.rb +3 -1
- data/lib/active_support/file_update_checker.rb +56 -51
- data/lib/active_support/fork_tracker.rb +62 -0
- data/lib/active_support/gem_version.rb +4 -2
- data/lib/active_support/gzip.rb +7 -5
- data/lib/active_support/hash_with_indifferent_access.rb +153 -49
- data/lib/active_support/i18n.rb +9 -6
- data/lib/active_support/i18n_railtie.rb +30 -20
- data/lib/active_support/inflections.rb +13 -11
- data/lib/active_support/inflector/inflections.rb +28 -15
- data/lib/active_support/inflector/methods.rb +120 -109
- data/lib/active_support/inflector/transliterate.rb +60 -25
- data/lib/active_support/inflector.rb +7 -5
- data/lib/active_support/json/decoding.rb +30 -29
- data/lib/active_support/json/encoding.rb +22 -11
- data/lib/active_support/json.rb +4 -2
- data/lib/active_support/key_generator.rb +6 -36
- data/lib/active_support/lazy_load_hooks.rb +53 -20
- data/lib/active_support/locale/en.rb +33 -0
- data/lib/active_support/locale/en.yml +7 -3
- data/lib/active_support/log_subscriber/test_helper.rb +11 -9
- data/lib/active_support/log_subscriber.rb +51 -18
- data/lib/active_support/logger.rb +9 -22
- data/lib/active_support/logger_silence.rb +14 -21
- data/lib/active_support/logger_thread_safe_level.rb +55 -8
- data/lib/active_support/message_encryptor.rb +170 -53
- data/lib/active_support/message_verifier.rb +91 -20
- data/lib/active_support/messages/metadata.rb +80 -0
- data/lib/active_support/messages/rotation_configuration.rb +23 -0
- data/lib/active_support/messages/rotator.rb +57 -0
- data/lib/active_support/multibyte/chars.rb +24 -78
- data/lib/active_support/multibyte/unicode.rb +21 -352
- data/lib/active_support/multibyte.rb +4 -2
- data/lib/active_support/notifications/fanout.rb +121 -19
- data/lib/active_support/notifications/instrumenter.rb +78 -14
- data/lib/active_support/notifications.rb +80 -12
- data/lib/active_support/number_helper/number_converter.rb +17 -16
- data/lib/active_support/number_helper/number_to_currency_converter.rb +6 -9
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +5 -3
- data/lib/active_support/number_helper/number_to_human_converter.rb +13 -12
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +11 -13
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +5 -4
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +18 -55
- data/lib/active_support/number_helper/rounding_helper.rb +50 -0
- data/lib/active_support/number_helper.rb +45 -16
- data/lib/active_support/option_merger.rb +25 -4
- data/lib/active_support/ordered_hash.rb +6 -4
- data/lib/active_support/ordered_options.rb +23 -9
- data/lib/active_support/parameter_filter.rb +133 -0
- data/lib/active_support/per_thread_registry.rb +7 -5
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/rails.rb +8 -9
- data/lib/active_support/railtie.rb +62 -11
- data/lib/active_support/reloader.rb +12 -11
- data/lib/active_support/rescuable.rb +20 -11
- data/lib/active_support/secure_compare_rotator.rb +51 -0
- data/lib/active_support/security_utils.rb +26 -15
- data/lib/active_support/string_inquirer.rb +12 -3
- data/lib/active_support/subscriber.rb +77 -23
- data/lib/active_support/tagged_logging.rb +52 -17
- data/lib/active_support/test_case.rb +106 -29
- data/lib/active_support/testing/assertions.rb +144 -8
- data/lib/active_support/testing/autorun.rb +5 -10
- data/lib/active_support/testing/constant_lookup.rb +2 -1
- data/lib/active_support/testing/declarative.rb +3 -1
- data/lib/active_support/testing/deprecation.rb +4 -2
- data/lib/active_support/testing/file_fixtures.rb +4 -0
- data/lib/active_support/testing/isolation.rb +19 -24
- data/lib/active_support/testing/method_call_assertions.rb +31 -2
- data/lib/active_support/testing/parallelization/server.rb +78 -0
- data/lib/active_support/testing/parallelization/worker.rb +100 -0
- data/lib/active_support/testing/parallelization.rb +51 -0
- data/lib/active_support/testing/setup_and_teardown.rb +13 -8
- data/lib/active_support/testing/stream.rb +30 -29
- data/lib/active_support/testing/tagged_logging.rb +3 -1
- data/lib/active_support/testing/time_helpers.rb +125 -24
- data/lib/active_support/time.rb +14 -12
- data/lib/active_support/time_with_zone.rb +142 -55
- data/lib/active_support/values/time_zone.rb +160 -53
- data/lib/active_support/version.rb +3 -1
- data/lib/active_support/xml_mini/jdom.rb +115 -114
- data/lib/active_support/xml_mini/libxml.rb +15 -14
- data/lib/active_support/xml_mini/libxmlsax.rb +16 -18
- data/lib/active_support/xml_mini/nokogiri.rb +13 -13
- data/lib/active_support/xml_mini/nokogirisax.rb +15 -16
- data/lib/active_support/xml_mini/rexml.rb +18 -9
- data/lib/active_support/xml_mini.rb +44 -42
- data/lib/active_support.rb +19 -10
- metadata +79 -37
- data/lib/active_support/concurrency/latch.rb +0 -19
- data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
- data/lib/active_support/core_ext/hash/compact.rb +0 -20
- data/lib/active_support/core_ext/hash/transform_values.rb +0 -29
- data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
- data/lib/active_support/core_ext/kernel/debugger.rb +0 -3
- data/lib/active_support/core_ext/module/method_transplanting.rb +0 -3
- data/lib/active_support/core_ext/module/qualified_const.rb +0 -70
- data/lib/active_support/core_ext/module/reachable.rb +0 -8
- data/lib/active_support/core_ext/numeric/inquiry.rb +0 -26
- data/lib/active_support/core_ext/range/include_range.rb +0 -23
- data/lib/active_support/core_ext/struct.rb +0 -3
- data/lib/active_support/core_ext/time/marshal.rb +0 -3
- data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,3 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/number_helper/number_converter"
|
4
|
+
|
1
5
|
module ActiveSupport
|
2
6
|
module NumberHelper
|
3
7
|
class NumberToHumanConverter < NumberConverter # :nodoc:
|
@@ -9,38 +13,35 @@ module ActiveSupport
|
|
9
13
|
self.validate_float = true
|
10
14
|
|
11
15
|
def convert # :nodoc:
|
16
|
+
@number = RoundingHelper.new(options).round(number)
|
12
17
|
@number = Float(number)
|
13
18
|
|
14
|
-
#
|
19
|
+
# For backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files.
|
15
20
|
unless options.key?(:strip_insignificant_zeros)
|
16
21
|
options[:strip_insignificant_zeros] = true
|
17
22
|
end
|
18
23
|
|
19
24
|
units = opts[:units]
|
20
25
|
exponent = calculate_exponent(units)
|
21
|
-
@number = number / (10
|
26
|
+
@number = number / (10**exponent)
|
22
27
|
|
23
|
-
|
24
|
-
@number = number / 1000.0
|
25
|
-
exponent += 3
|
26
|
-
end
|
28
|
+
rounded_number = NumberToRoundedConverter.convert(number, options)
|
27
29
|
unit = determine_unit(units, exponent)
|
28
|
-
format.gsub(
|
30
|
+
format.gsub("%n", rounded_number).gsub("%u", unit).strip
|
29
31
|
end
|
30
32
|
|
31
33
|
private
|
32
|
-
|
33
34
|
def format
|
34
|
-
options[:format] || translate_in_locale(
|
35
|
+
options[:format] || translate_in_locale("human.decimal_units.format")
|
35
36
|
end
|
36
37
|
|
37
38
|
def determine_unit(units, exponent)
|
38
39
|
exp = DECIMAL_UNITS[exponent]
|
39
40
|
case units
|
40
41
|
when Hash
|
41
|
-
units[exp] ||
|
42
|
+
units[exp] || ""
|
42
43
|
when String, Symbol
|
43
|
-
I18n.translate("#{units}.#{exp}", :
|
44
|
+
I18n.translate("#{units}.#{exp}", locale: options[:locale], count: number.to_i)
|
44
45
|
else
|
45
46
|
translate_in_locale("human.decimal_units.units.#{exp}", count: number.to_i)
|
46
47
|
end
|
@@ -56,7 +57,7 @@ module ActiveSupport
|
|
56
57
|
when Hash
|
57
58
|
units
|
58
59
|
when String, Symbol
|
59
|
-
I18n.translate(units.to_s, :
|
60
|
+
I18n.translate(units.to_s, locale: options[:locale], raise: true)
|
60
61
|
when nil
|
61
62
|
translate_in_locale("human.decimal_units.units", raise: true)
|
62
63
|
else
|
@@ -1,3 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/number_helper/number_converter"
|
4
|
+
|
1
5
|
module ActiveSupport
|
2
6
|
module NumberHelper
|
3
7
|
class NumberToHumanSizeConverter < NumberConverter #:nodoc:
|
@@ -7,13 +11,9 @@ module ActiveSupport
|
|
7
11
|
self.validate_float = true
|
8
12
|
|
9
13
|
def convert
|
10
|
-
if opts.key?(:prefix)
|
11
|
-
ActiveSupport::Deprecation.warn('The :prefix option of `number_to_human_size` is deprecated and will be removed in Rails 5.1 with no replacement.')
|
12
|
-
end
|
13
|
-
|
14
14
|
@number = Float(number)
|
15
15
|
|
16
|
-
#
|
16
|
+
# For backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files.
|
17
17
|
unless options.key?(:strip_insignificant_zeros)
|
18
18
|
options[:strip_insignificant_zeros] = true
|
19
19
|
end
|
@@ -21,24 +21,23 @@ module ActiveSupport
|
|
21
21
|
if smaller_than_base?
|
22
22
|
number_to_format = number.to_i.to_s
|
23
23
|
else
|
24
|
-
human_size = number / (base
|
24
|
+
human_size = number / (base**exponent)
|
25
25
|
number_to_format = NumberToRoundedConverter.convert(human_size, options)
|
26
26
|
end
|
27
|
-
conversion_format.gsub(
|
27
|
+
conversion_format.gsub("%n", number_to_format).gsub("%u", unit)
|
28
28
|
end
|
29
29
|
|
30
30
|
private
|
31
|
-
|
32
31
|
def conversion_format
|
33
|
-
translate_number_value_with_default(
|
32
|
+
translate_number_value_with_default("human.storage_units.format", locale: options[:locale], raise: true)
|
34
33
|
end
|
35
34
|
|
36
35
|
def unit
|
37
|
-
translate_number_value_with_default(storage_unit_key, :
|
36
|
+
translate_number_value_with_default(storage_unit_key, locale: options[:locale], count: number.to_i, raise: true)
|
38
37
|
end
|
39
38
|
|
40
39
|
def storage_unit_key
|
41
|
-
key_end = smaller_than_base? ?
|
40
|
+
key_end = smaller_than_base? ? "byte" : STORAGE_UNITS[exponent]
|
42
41
|
"human.storage_units.units.#{key_end}"
|
43
42
|
end
|
44
43
|
|
@@ -54,9 +53,8 @@ module ActiveSupport
|
|
54
53
|
end
|
55
54
|
|
56
55
|
def base
|
57
|
-
|
56
|
+
1024
|
58
57
|
end
|
59
58
|
end
|
60
59
|
end
|
61
60
|
end
|
62
|
-
|
@@ -1,3 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/number_helper/number_converter"
|
4
|
+
|
1
5
|
module ActiveSupport
|
2
6
|
module NumberHelper
|
3
7
|
class NumberToPercentageConverter < NumberConverter # :nodoc:
|
@@ -5,7 +9,7 @@ module ActiveSupport
|
|
5
9
|
|
6
10
|
def convert
|
7
11
|
rounded_number = NumberToRoundedConverter.convert(number, options)
|
8
|
-
options[:format].gsub(
|
12
|
+
options[:format].gsub("%n", rounded_number)
|
9
13
|
end
|
10
14
|
end
|
11
15
|
end
|
@@ -1,14 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/number_helper/number_converter"
|
4
|
+
|
1
5
|
module ActiveSupport
|
2
6
|
module NumberHelper
|
3
7
|
class NumberToPhoneConverter < NumberConverter #:nodoc:
|
4
8
|
def convert
|
5
|
-
str
|
9
|
+
str = country_code(opts[:country_code]).dup
|
6
10
|
str << convert_to_phone_number(number.to_s.strip)
|
7
11
|
str << phone_ext(opts[:extension])
|
8
12
|
end
|
9
13
|
|
10
14
|
private
|
11
|
-
|
12
15
|
def convert_to_phone_number(number)
|
13
16
|
if opts[:area_code]
|
14
17
|
convert_with_area_code(number)
|
@@ -51,8 +54,6 @@ module ActiveSupport
|
|
51
54
|
def regexp_pattern(default_pattern)
|
52
55
|
opts.fetch :pattern, default_pattern
|
53
56
|
end
|
54
|
-
|
55
57
|
end
|
56
58
|
end
|
57
59
|
end
|
58
|
-
|
@@ -1,3 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/number_helper/number_converter"
|
4
|
+
|
1
5
|
module ActiveSupport
|
2
6
|
module NumberHelper
|
3
7
|
class NumberToRoundedConverter < NumberConverter # :nodoc:
|
@@ -5,40 +9,28 @@ module ActiveSupport
|
|
5
9
|
self.validate_float = true
|
6
10
|
|
7
11
|
def convert
|
8
|
-
|
9
|
-
|
10
|
-
if precision
|
11
|
-
case number
|
12
|
-
when Float, String
|
13
|
-
@number = BigDecimal(number.to_s)
|
14
|
-
when Rational
|
15
|
-
@number = BigDecimal(number, digit_count(number.to_i) + precision)
|
16
|
-
else
|
17
|
-
@number = number.to_d
|
18
|
-
end
|
12
|
+
helper = RoundingHelper.new(options)
|
13
|
+
rounded_number = helper.round(number)
|
19
14
|
|
20
|
-
|
21
|
-
|
15
|
+
if precision = options[:precision]
|
16
|
+
if options[:significant] && precision > 0
|
17
|
+
digits = helper.digit_count(rounded_number)
|
22
18
|
precision -= digits
|
23
19
|
precision = 0 if precision < 0 # don't let it be negative
|
24
|
-
else
|
25
|
-
rounded_number = number.round(precision)
|
26
|
-
rounded_number = rounded_number.to_i if precision == 0 && rounded_number.finite?
|
27
|
-
rounded_number = rounded_number.abs if rounded_number.zero? # prevent showing negative zeros
|
28
20
|
end
|
29
21
|
|
30
22
|
formatted_string =
|
31
|
-
if
|
32
|
-
s = rounded_number.to_s('F')
|
33
|
-
s << '0'.freeze * precision
|
34
|
-
a, b = s.split('.'.freeze, 2)
|
35
|
-
a << '.'.freeze
|
36
|
-
a << b[0, precision]
|
37
|
-
else
|
23
|
+
if rounded_number.nan? || rounded_number.infinite? || rounded_number == rounded_number.to_i
|
38
24
|
"%00.#{precision}f" % rounded_number
|
25
|
+
else
|
26
|
+
s = rounded_number.to_s("F")
|
27
|
+
s << "0" * precision
|
28
|
+
a, b = s.split(".", 2)
|
29
|
+
a << "."
|
30
|
+
a << b[0, precision]
|
39
31
|
end
|
40
32
|
else
|
41
|
-
formatted_string =
|
33
|
+
formatted_string = rounded_number
|
42
34
|
end
|
43
35
|
|
44
36
|
delimited_number = NumberToDelimitedConverter.convert(formatted_string, options)
|
@@ -46,27 +38,6 @@ module ActiveSupport
|
|
46
38
|
end
|
47
39
|
|
48
40
|
private
|
49
|
-
|
50
|
-
def digits_and_rounded_number(precision)
|
51
|
-
if zero?
|
52
|
-
[1, 0]
|
53
|
-
else
|
54
|
-
digits = digit_count(number)
|
55
|
-
multiplier = 10 ** (digits - precision)
|
56
|
-
rounded_number = calculate_rounded_number(multiplier)
|
57
|
-
digits = digit_count(rounded_number) # After rounding, the number of digits may have changed
|
58
|
-
[digits, rounded_number]
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def calculate_rounded_number(multiplier)
|
63
|
-
(number / BigDecimal.new(multiplier.to_f.to_s)).round * multiplier
|
64
|
-
end
|
65
|
-
|
66
|
-
def digit_count(number)
|
67
|
-
number.zero? ? 1 : (Math.log10(absolute_number(number)) + 1).floor
|
68
|
-
end
|
69
|
-
|
70
41
|
def strip_insignificant_zeros
|
71
42
|
options[:strip_insignificant_zeros]
|
72
43
|
end
|
@@ -74,19 +45,11 @@ module ActiveSupport
|
|
74
45
|
def format_number(number)
|
75
46
|
if strip_insignificant_zeros
|
76
47
|
escaped_separator = Regexp.escape(options[:separator])
|
77
|
-
number.sub(/(#{escaped_separator})(\d*[1-9])?0+\z/, '\1\2').sub(/#{escaped_separator}\z/,
|
48
|
+
number.sub(/(#{escaped_separator})(\d*[1-9])?0+\z/, '\1\2').sub(/#{escaped_separator}\z/, "")
|
78
49
|
else
|
79
50
|
number
|
80
51
|
end
|
81
52
|
end
|
82
|
-
|
83
|
-
def absolute_number(number)
|
84
|
-
number.respond_to?(:abs) ? number.abs : number.to_d.abs
|
85
|
-
end
|
86
|
-
|
87
|
-
def zero?
|
88
|
-
number.respond_to?(:zero?) ? number.zero? : number.to_d.zero?
|
89
|
-
end
|
90
53
|
end
|
91
54
|
end
|
92
55
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveSupport
|
4
|
+
module NumberHelper
|
5
|
+
class RoundingHelper # :nodoc:
|
6
|
+
attr_reader :options
|
7
|
+
|
8
|
+
def initialize(options)
|
9
|
+
@options = options
|
10
|
+
end
|
11
|
+
|
12
|
+
def round(number)
|
13
|
+
precision = absolute_precision(number)
|
14
|
+
return number unless precision
|
15
|
+
|
16
|
+
rounded_number = convert_to_decimal(number).round(precision, options.fetch(:round_mode, :default))
|
17
|
+
rounded_number.zero? ? rounded_number.abs : rounded_number # prevent showing negative zeros
|
18
|
+
end
|
19
|
+
|
20
|
+
def digit_count(number)
|
21
|
+
return 1 if number.zero?
|
22
|
+
(Math.log10(number.abs) + 1).floor
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
def convert_to_decimal(number)
|
27
|
+
case number
|
28
|
+
when Float, String
|
29
|
+
BigDecimal(number.to_s)
|
30
|
+
when Rational
|
31
|
+
BigDecimal(number, digit_count(number.to_i) + options[:precision])
|
32
|
+
else
|
33
|
+
number.to_d
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def absolute_precision(number)
|
38
|
+
if significant && options[:precision] > 0
|
39
|
+
options[:precision] - digit_count(convert_to_decimal(number))
|
40
|
+
else
|
41
|
+
options[:precision]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def significant
|
46
|
+
options[:significant]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -1,9 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveSupport
|
2
4
|
module NumberHelper
|
3
5
|
extend ActiveSupport::Autoload
|
4
6
|
|
5
7
|
eager_autoload do
|
6
8
|
autoload :NumberConverter
|
9
|
+
autoload :RoundingHelper
|
7
10
|
autoload :NumberToRoundedConverter
|
8
11
|
autoload :NumberToDelimitedConverter
|
9
12
|
autoload :NumberToHumanConverter
|
@@ -45,7 +48,7 @@ module ActiveSupport
|
|
45
48
|
#
|
46
49
|
# number_to_phone(75561234567, pattern: /(\d{1,4})(\d{4})(\d{4})$/, area_code: true)
|
47
50
|
# # => "(755) 6123-4567"
|
48
|
-
# number_to_phone(13312345678, pattern: /(\d{3})(\d{4})(\d{4})$/)
|
51
|
+
# number_to_phone(13312345678, pattern: /(\d{3})(\d{4})(\d{4})$/)
|
49
52
|
# # => "133-1234-5678"
|
50
53
|
def number_to_phone(number, options = {})
|
51
54
|
NumberToPhoneConverter.convert(number, options)
|
@@ -68,6 +71,8 @@ module ActiveSupport
|
|
68
71
|
# (defaults to current locale).
|
69
72
|
# * <tt>:precision</tt> - Sets the level of precision (defaults
|
70
73
|
# to 2).
|
74
|
+
# * <tt>:round_mode</tt> - Determine how rounding is performed
|
75
|
+
# (defaults to :default. See BigDecimal::mode)
|
71
76
|
# * <tt>:unit</tt> - Sets the denomination of the currency
|
72
77
|
# (defaults to "$").
|
73
78
|
# * <tt>:separator</tt> - Sets the separator between the units
|
@@ -78,10 +83,13 @@ module ActiveSupport
|
|
78
83
|
# (defaults to "%u%n"). Fields are <tt>%u</tt> for the
|
79
84
|
# currency, and <tt>%n</tt> for the number.
|
80
85
|
# * <tt>:negative_format</tt> - Sets the format for negative
|
81
|
-
# numbers (defaults to prepending
|
86
|
+
# numbers (defaults to prepending a hyphen to the formatted
|
82
87
|
# number given by <tt>:format</tt>). Accepts the same fields
|
83
88
|
# than <tt>:format</tt>, except <tt>%n</tt> is here the
|
84
89
|
# absolute value of the number.
|
90
|
+
# * <tt>:strip_insignificant_zeros</tt> - If +true+ removes
|
91
|
+
# insignificant zeros after the decimal separator (defaults to
|
92
|
+
# +false+).
|
85
93
|
#
|
86
94
|
# ==== Examples
|
87
95
|
#
|
@@ -91,12 +99,20 @@ module ActiveSupport
|
|
91
99
|
# number_to_currency(1234567890.506, locale: :fr) # => "1 234 567 890,51 €"
|
92
100
|
# number_to_currency('123a456') # => "$123a456"
|
93
101
|
#
|
102
|
+
# number_to_currency("123a456", raise: true) # => InvalidNumberError
|
103
|
+
#
|
104
|
+
# number_to_currency(-0.456789, precision: 0)
|
105
|
+
# # => "$0"
|
94
106
|
# number_to_currency(-1234567890.50, negative_format: '(%u%n)')
|
95
107
|
# # => "($1,234,567,890.50)"
|
96
108
|
# number_to_currency(1234567890.50, unit: '£', separator: ',', delimiter: '')
|
97
109
|
# # => "£1234567890,50"
|
98
110
|
# number_to_currency(1234567890.50, unit: '£', separator: ',', delimiter: '', format: '%n %u')
|
99
111
|
# # => "1234567890,50 £"
|
112
|
+
# number_to_currency(1234567890.50, strip_insignificant_zeros: true)
|
113
|
+
# # => "$1,234,567,890.5"
|
114
|
+
# number_to_currency(1234567890.50, precision: 0, round_mode: :up)
|
115
|
+
# # => "$1,234,567,891"
|
100
116
|
def number_to_currency(number, options = {})
|
101
117
|
NumberToCurrencyConverter.convert(number, options)
|
102
118
|
end
|
@@ -109,7 +125,9 @@ module ActiveSupport
|
|
109
125
|
# * <tt>:locale</tt> - Sets the locale to be used for formatting
|
110
126
|
# (defaults to current locale).
|
111
127
|
# * <tt>:precision</tt> - Sets the precision of the number
|
112
|
-
# (defaults to 3). Keeps the number's precision if nil
|
128
|
+
# (defaults to 3). Keeps the number's precision if +nil+.
|
129
|
+
# * <tt>:round_mode</tt> - Determine how rounding is performed
|
130
|
+
# (defaults to :default. See BigDecimal::mode)
|
113
131
|
# * <tt>:significant</tt> - If +true+, precision will be the number
|
114
132
|
# of significant_digits. If +false+, the number of fractional
|
115
133
|
# digits (defaults to +false+).
|
@@ -125,15 +143,16 @@ module ActiveSupport
|
|
125
143
|
#
|
126
144
|
# ==== Examples
|
127
145
|
#
|
128
|
-
# number_to_percentage(100)
|
129
|
-
# number_to_percentage('98')
|
130
|
-
# number_to_percentage(100, precision: 0)
|
131
|
-
# number_to_percentage(1000, delimiter: '.', separator: ',')
|
132
|
-
# number_to_percentage(302.24398923423, precision: 5)
|
133
|
-
# number_to_percentage(1000, locale: :fr)
|
134
|
-
# number_to_percentage(1000, precision: nil)
|
135
|
-
# number_to_percentage('98a')
|
136
|
-
# number_to_percentage(100, format: '%n %')
|
146
|
+
# number_to_percentage(100) # => "100.000%"
|
147
|
+
# number_to_percentage('98') # => "98.000%"
|
148
|
+
# number_to_percentage(100, precision: 0) # => "100%"
|
149
|
+
# number_to_percentage(1000, delimiter: '.', separator: ',') # => "1.000,000%"
|
150
|
+
# number_to_percentage(302.24398923423, precision: 5) # => "302.24399%"
|
151
|
+
# number_to_percentage(1000, locale: :fr) # => "1000,000%"
|
152
|
+
# number_to_percentage(1000, precision: nil) # => "1000%"
|
153
|
+
# number_to_percentage('98a') # => "98a%"
|
154
|
+
# number_to_percentage(100, format: '%n %') # => "100.000 %"
|
155
|
+
# number_to_percentage(302.24398923423, precision: 5, round_mode: :down) # => "302.24398%"
|
137
156
|
def number_to_percentage(number, options = {})
|
138
157
|
NumberToPercentageConverter.convert(number, options)
|
139
158
|
end
|
@@ -183,7 +202,9 @@ module ActiveSupport
|
|
183
202
|
# * <tt>:locale</tt> - Sets the locale to be used for formatting
|
184
203
|
# (defaults to current locale).
|
185
204
|
# * <tt>:precision</tt> - Sets the precision of the number
|
186
|
-
# (defaults to 3). Keeps the number's precision if nil
|
205
|
+
# (defaults to 3). Keeps the number's precision if +nil+.
|
206
|
+
# * <tt>:round_mode</tt> - Determine how rounding is performed
|
207
|
+
# (defaults to :default. See BigDecimal::mode)
|
187
208
|
# * <tt>:significant</tt> - If +true+, precision will be the number
|
188
209
|
# of significant_digits. If +false+, the number of fractional
|
189
210
|
# digits (defaults to +false+).
|
@@ -205,6 +226,7 @@ module ActiveSupport
|
|
205
226
|
# number_to_rounded(111.2345, precision: 1, significant: true) # => "100"
|
206
227
|
# number_to_rounded(13, precision: 5, significant: true) # => "13.000"
|
207
228
|
# number_to_rounded(13, precision: nil) # => "13"
|
229
|
+
# number_to_rounded(389.32314, precision: 0, round_mode: :up) # => "390"
|
208
230
|
# number_to_rounded(111.234, locale: :fr) # => "111,234"
|
209
231
|
#
|
210
232
|
# number_to_rounded(13, precision: 5, significant: true, strip_insignificant_zeros: true)
|
@@ -218,7 +240,7 @@ module ActiveSupport
|
|
218
240
|
end
|
219
241
|
|
220
242
|
# Formats the bytes in +number+ into a more understandable
|
221
|
-
# representation (e.g., giving it 1500 yields 1.
|
243
|
+
# representation (e.g., giving it 1500 yields 1.46 KB). This
|
222
244
|
# method is useful for reporting file sizes to users. You can
|
223
245
|
# customize the format in the +options+ hash.
|
224
246
|
#
|
@@ -231,6 +253,8 @@ module ActiveSupport
|
|
231
253
|
# (defaults to current locale).
|
232
254
|
# * <tt>:precision</tt> - Sets the precision of the number
|
233
255
|
# (defaults to 3).
|
256
|
+
# * <tt>:round_mode</tt> - Determine how rounding is performed
|
257
|
+
# (defaults to :default. See BigDecimal::mode)
|
234
258
|
# * <tt>:significant</tt> - If +true+, precision will be the number
|
235
259
|
# of significant_digits. If +false+, the number of fractional
|
236
260
|
# digits (defaults to +true+)
|
@@ -254,6 +278,7 @@ module ActiveSupport
|
|
254
278
|
# number_to_human_size(1234567890123456789) # => "1.07 EB"
|
255
279
|
# number_to_human_size(1234567, precision: 2) # => "1.2 MB"
|
256
280
|
# number_to_human_size(483989, precision: 2) # => "470 KB"
|
281
|
+
# number_to_human_size(483989, precision: 2, round_mode: :up) # => "480 KB"
|
257
282
|
# number_to_human_size(1234567, precision: 2, separator: ',') # => "1,2 MB"
|
258
283
|
# number_to_human_size(1234567890123, precision: 5) # => "1.1228 TB"
|
259
284
|
# number_to_human_size(524288000, precision: 5) # => "500 MB"
|
@@ -262,7 +287,7 @@ module ActiveSupport
|
|
262
287
|
end
|
263
288
|
|
264
289
|
# Pretty prints (formats and approximates) a number in a way it
|
265
|
-
# is more readable by humans (
|
290
|
+
# is more readable by humans (e.g.: 1200000000 becomes "1.2
|
266
291
|
# Billion"). This is useful for numbers that can get very large
|
267
292
|
# (and too hard to read).
|
268
293
|
#
|
@@ -270,7 +295,7 @@ module ActiveSupport
|
|
270
295
|
# size.
|
271
296
|
#
|
272
297
|
# You can also define your own unit-quantifier names if you want
|
273
|
-
# to use other decimal units (
|
298
|
+
# to use other decimal units (e.g.: 1500 becomes "1.5
|
274
299
|
# kilometers", 0.150 becomes "150 milliliters", etc). You may
|
275
300
|
# define a wide range of unit quantifiers, even fractional ones
|
276
301
|
# (centi, deci, mili, etc).
|
@@ -281,6 +306,8 @@ module ActiveSupport
|
|
281
306
|
# (defaults to current locale).
|
282
307
|
# * <tt>:precision</tt> - Sets the precision of the number
|
283
308
|
# (defaults to 3).
|
309
|
+
# * <tt>:round_mode</tt> - Determine how rounding is performed
|
310
|
+
# (defaults to :default. See BigDecimal::mode)
|
284
311
|
# * <tt>:significant</tt> - If +true+, precision will be the number
|
285
312
|
# of significant_digits. If +false+, the number of fractional
|
286
313
|
# digits (defaults to +true+)
|
@@ -318,6 +345,8 @@ module ActiveSupport
|
|
318
345
|
# number_to_human(1234567890123456789) # => "1230 Quadrillion"
|
319
346
|
# number_to_human(489939, precision: 2) # => "490 Thousand"
|
320
347
|
# number_to_human(489939, precision: 4) # => "489.9 Thousand"
|
348
|
+
# number_to_human(489939, precision: 2
|
349
|
+
# , round_mode: :down) # => "480 Thousand"
|
321
350
|
# number_to_human(1234567, precision: 4,
|
322
351
|
# significant: false) # => "1.2346 Million"
|
323
352
|
# number_to_human(1234567, precision: 1,
|
@@ -1,9 +1,12 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/hash/deep_merge"
|
4
|
+
require "active_support/core_ext/symbol/starts_ends_with"
|
2
5
|
|
3
6
|
module ActiveSupport
|
4
7
|
class OptionMerger #:nodoc:
|
5
8
|
instance_methods.each do |method|
|
6
|
-
undef_method(method)
|
9
|
+
undef_method(method) unless method.start_with?("__", "instance_eval", "class", "object_id")
|
7
10
|
end
|
8
11
|
|
9
12
|
def initialize(context, options)
|
@@ -12,14 +15,32 @@ module ActiveSupport
|
|
12
15
|
|
13
16
|
private
|
14
17
|
def method_missing(method, *arguments, &block)
|
18
|
+
options = nil
|
15
19
|
if arguments.first.is_a?(Proc)
|
16
20
|
proc = arguments.pop
|
17
21
|
arguments << lambda { |*args| @options.deep_merge(proc.call(*args)) }
|
22
|
+
elsif arguments.last.respond_to?(:to_hash)
|
23
|
+
options = @options.deep_merge(arguments.pop)
|
18
24
|
else
|
19
|
-
|
25
|
+
options = @options
|
20
26
|
end
|
21
27
|
|
22
|
-
|
28
|
+
invoke_method(method, arguments, options, &block)
|
29
|
+
end
|
30
|
+
|
31
|
+
if RUBY_VERSION >= "2.7"
|
32
|
+
def invoke_method(method, arguments, options, &block)
|
33
|
+
if options
|
34
|
+
@context.__send__(method, *arguments, **options, &block)
|
35
|
+
else
|
36
|
+
@context.__send__(method, *arguments, &block)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
else
|
40
|
+
def invoke_method(method, arguments, options, &block)
|
41
|
+
arguments << options.dup if options
|
42
|
+
@context.__send__(method, *arguments, &block)
|
43
|
+
end
|
23
44
|
end
|
24
45
|
end
|
25
46
|
end
|
@@ -1,7 +1,9 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "yaml"
|
2
4
|
|
3
5
|
YAML.add_builtin_type("omap") do |type, val|
|
4
|
-
ActiveSupport::OrderedHash[val.map{ |v| v.to_a.first }]
|
6
|
+
ActiveSupport::OrderedHash[val.map { |v| v.to_a.first }]
|
5
7
|
end
|
6
8
|
|
7
9
|
module ActiveSupport
|
@@ -14,7 +16,7 @@ module ActiveSupport
|
|
14
16
|
# oh.keys # => [:a, :b], this order is guaranteed
|
15
17
|
#
|
16
18
|
# Also, maps the +omap+ feature for YAML files
|
17
|
-
# (See
|
19
|
+
# (See https://yaml.org/type/omap.html) to support ordered items
|
18
20
|
# when loading from yaml.
|
19
21
|
#
|
20
22
|
# <tt>ActiveSupport::OrderedHash</tt> is namespaced to prevent conflicts
|
@@ -25,7 +27,7 @@ module ActiveSupport
|
|
25
27
|
end
|
26
28
|
|
27
29
|
def encode_with(coder)
|
28
|
-
coder.represent_seq
|
30
|
+
coder.represent_seq "!omap", map { |k, v| { k => v } }
|
29
31
|
end
|
30
32
|
|
31
33
|
def select(*args, &block)
|
@@ -1,5 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/object/blank"
|
4
|
+
|
1
5
|
module ActiveSupport
|
2
|
-
#
|
6
|
+
# +OrderedOptions+ inherits from +Hash+ and provides dynamic accessor methods.
|
7
|
+
#
|
8
|
+
# With a +Hash+, key-value pairs are typically managed like this:
|
3
9
|
#
|
4
10
|
# h = {}
|
5
11
|
# h[:boy] = 'John'
|
@@ -8,7 +14,7 @@ module ActiveSupport
|
|
8
14
|
# h[:girl] # => 'Mary'
|
9
15
|
# h[:dog] # => nil
|
10
16
|
#
|
11
|
-
# Using +OrderedOptions+, the above code
|
17
|
+
# Using +OrderedOptions+, the above code can be written as:
|
12
18
|
#
|
13
19
|
# h = ActiveSupport::OrderedOptions.new
|
14
20
|
# h.boy = 'John'
|
@@ -20,7 +26,7 @@ module ActiveSupport
|
|
20
26
|
# To raise an exception when the value is blank, append a
|
21
27
|
# bang to the key name, like:
|
22
28
|
#
|
23
|
-
# h.dog! # => raises KeyError:
|
29
|
+
# h.dog! # => raises KeyError: :dog is blank
|
24
30
|
#
|
25
31
|
class OrderedOptions < Hash
|
26
32
|
alias_method :_get, :[] # preserve the original #[] method
|
@@ -35,14 +41,14 @@ module ActiveSupport
|
|
35
41
|
end
|
36
42
|
|
37
43
|
def method_missing(name, *args)
|
38
|
-
name_string = name.to_s
|
39
|
-
if name_string.chomp!(
|
44
|
+
name_string = +name.to_s
|
45
|
+
if name_string.chomp!("=")
|
40
46
|
self[name_string] = args.first
|
41
47
|
else
|
42
|
-
bangs = name_string.chomp!(
|
48
|
+
bangs = name_string.chomp!("!")
|
43
49
|
|
44
50
|
if bangs
|
45
|
-
|
51
|
+
self[name_string].presence || raise(KeyError.new(":#{name_string} is blank"))
|
46
52
|
else
|
47
53
|
self[name_string]
|
48
54
|
end
|
@@ -52,6 +58,14 @@ module ActiveSupport
|
|
52
58
|
def respond_to_missing?(name, include_private)
|
53
59
|
true
|
54
60
|
end
|
61
|
+
|
62
|
+
def extractable_options?
|
63
|
+
true
|
64
|
+
end
|
65
|
+
|
66
|
+
def inspect
|
67
|
+
"#<#{self.class.name} #{super}>"
|
68
|
+
end
|
55
69
|
end
|
56
70
|
|
57
71
|
# +InheritableOptions+ provides a constructor to build an +OrderedOptions+
|
@@ -66,9 +80,9 @@ module ActiveSupport
|
|
66
80
|
def initialize(parent = nil)
|
67
81
|
if parent.kind_of?(OrderedOptions)
|
68
82
|
# use the faster _get when dealing with OrderedOptions
|
69
|
-
super() { |h,k| parent._get(k) }
|
83
|
+
super() { |h, k| parent._get(k) }
|
70
84
|
elsif parent
|
71
|
-
super() { |h,k| parent[k] }
|
85
|
+
super() { |h, k| parent[k] }
|
72
86
|
else
|
73
87
|
super()
|
74
88
|
end
|