activesupport 4.2.11.1 → 6.0.3.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.
Potentially problematic release.
This version of activesupport might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +399 -411
- data/MIT-LICENSE +2 -2
- data/README.rdoc +7 -7
- data/lib/active_support/actionable_error.rb +48 -0
- data/lib/active_support/all.rb +5 -3
- data/lib/active_support/array_inquirer.rb +48 -0
- data/lib/active_support/backtrace_cleaner.rb +34 -6
- data/lib/active_support/benchmarkable.rb +6 -4
- data/lib/active_support/builder.rb +3 -1
- data/lib/active_support/cache/file_store.rb +58 -53
- data/lib/active_support/cache/mem_cache_store.rb +95 -91
- data/lib/active_support/cache/memory_store.rb +39 -36
- data/lib/active_support/cache/null_store.rb +11 -7
- data/lib/active_support/cache/redis_cache_store.rb +493 -0
- data/lib/active_support/cache/strategy/local_cache.rb +75 -42
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
- data/lib/active_support/cache.rb +331 -217
- data/lib/active_support/callbacks.rb +650 -592
- data/lib/active_support/concern.rb +35 -6
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +35 -0
- data/lib/active_support/concurrency/share_lock.rb +226 -0
- data/lib/active_support/configurable.rb +13 -14
- data/lib/active_support/core_ext/array/access.rb +41 -1
- data/lib/active_support/core_ext/array/conversions.rb +24 -20
- 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 +11 -18
- data/lib/active_support/core_ext/array/inquiry.rb +19 -0
- data/lib/active_support/core_ext/array/prepend_and_append.rb +4 -6
- data/lib/active_support/core_ext/array/wrap.rb +7 -4
- data/lib/active_support/core_ext/array.rb +9 -6
- data/lib/active_support/core_ext/benchmark.rb +3 -1
- data/lib/active_support/core_ext/big_decimal/conversions.rb +10 -12
- data/lib/active_support/core_ext/big_decimal.rb +3 -1
- data/lib/active_support/core_ext/class/attribute.rb +45 -31
- data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
- data/lib/active_support/core_ext/class/subclasses.rb +20 -6
- data/lib/active_support/core_ext/class.rb +4 -3
- data/lib/active_support/core_ext/date/acts_like.rb +3 -1
- data/lib/active_support/core_ext/date/blank.rb +14 -0
- data/lib/active_support/core_ext/date/calculations.rb +17 -14
- data/lib/active_support/core_ext/date/conversions.rb +25 -23
- data/lib/active_support/core_ext/date/zones.rb +4 -2
- data/lib/active_support/core_ext/date.rb +6 -4
- data/lib/active_support/core_ext/date_and_time/calculations.rb +154 -65
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +4 -3
- data/lib/active_support/core_ext/date_and_time/zones.rb +12 -13
- data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
- data/lib/active_support/core_ext/date_time/blank.rb +14 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +37 -19
- data/lib/active_support/core_ext/date_time/compatibility.rb +8 -6
- data/lib/active_support/core_ext/date_time/conversions.rb +16 -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 +114 -22
- data/lib/active_support/core_ext/file/atomic.rb +38 -31
- data/lib/active_support/core_ext/file.rb +3 -1
- data/lib/active_support/core_ext/hash/compact.rb +4 -23
- data/lib/active_support/core_ext/hash/conversions.rb +62 -41
- data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
- data/lib/active_support/core_ext/hash/except.rb +12 -9
- data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -3
- data/lib/active_support/core_ext/hash/keys.rb +19 -42
- data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
- data/lib/active_support/core_ext/hash/slice.rb +5 -27
- data/lib/active_support/core_ext/hash/transform_values.rb +4 -22
- 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 +5 -1
- data/lib/active_support/core_ext/kernel/reporting.rb +4 -84
- data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
- data/lib/active_support/core_ext/kernel.rb +5 -5
- data/lib/active_support/core_ext/load_error.rb +3 -22
- data/lib/active_support/core_ext/marshal.rb +8 -8
- data/lib/active_support/core_ext/module/aliasing.rb +6 -44
- data/lib/active_support/core_ext/module/anonymous.rb +12 -1
- data/lib/active_support/core_ext/module/attr_internal.rb +8 -9
- data/lib/active_support/core_ext/module/attribute_accessors.rb +46 -46
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +144 -0
- data/lib/active_support/core_ext/module/concerning.rb +11 -12
- data/lib/active_support/core_ext/module/delegation.rb +133 -30
- data/lib/active_support/core_ext/module/deprecation.rb +4 -2
- data/lib/active_support/core_ext/module/introspection.rb +44 -19
- data/lib/active_support/core_ext/module/reachable.rb +5 -7
- data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
- data/lib/active_support/core_ext/module/remove_method.rb +8 -3
- data/lib/active_support/core_ext/module.rb +13 -11
- data/lib/active_support/core_ext/name_error.rb +22 -2
- data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +129 -136
- data/lib/active_support/core_ext/numeric/inquiry.rb +5 -0
- data/lib/active_support/core_ext/numeric/time.rb +35 -23
- data/lib/active_support/core_ext/numeric.rb +5 -3
- data/lib/active_support/core_ext/object/acts_like.rb +12 -1
- data/lib/active_support/core_ext/object/blank.rb +27 -3
- data/lib/active_support/core_ext/object/conversions.rb +6 -4
- data/lib/active_support/core_ext/object/deep_dup.rb +13 -4
- data/lib/active_support/core_ext/object/duplicable.rb +13 -93
- data/lib/active_support/core_ext/object/inclusion.rb +5 -3
- data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
- data/lib/active_support/core_ext/object/json.rb +51 -20
- 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 +81 -23
- data/lib/active_support/core_ext/object/with_options.rb +16 -3
- data/lib/active_support/core_ext/object.rb +14 -13
- data/lib/active_support/core_ext/range/compare_range.rb +76 -0
- data/lib/active_support/core_ext/range/conversions.rb +37 -15
- data/lib/active_support/core_ext/range/each.rb +18 -17
- data/lib/active_support/core_ext/range/include_range.rb +7 -21
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -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 +2 -0
- data/lib/active_support/core_ext/securerandom.rb +45 -0
- data/lib/active_support/core_ext/string/access.rb +16 -6
- data/lib/active_support/core_ext/string/behavior.rb +3 -1
- data/lib/active_support/core_ext/string/conversions.rb +7 -4
- data/lib/active_support/core_ext/string/exclude.rb +2 -0
- data/lib/active_support/core_ext/string/filters.rb +48 -6
- data/lib/active_support/core_ext/string/indent.rb +6 -4
- data/lib/active_support/core_ext/string/inflections.rb +66 -24
- data/lib/active_support/core_ext/string/inquiry.rb +3 -1
- data/lib/active_support/core_ext/string/multibyte.rb +16 -7
- data/lib/active_support/core_ext/string/output_safety.rb +93 -40
- data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
- data/lib/active_support/core_ext/string/strip.rb +6 -5
- 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/time/acts_like.rb +3 -1
- data/lib/active_support/core_ext/time/calculations.rb +115 -52
- data/lib/active_support/core_ext/time/compatibility.rb +4 -2
- data/lib/active_support/core_ext/time/conversions.rb +20 -13
- data/lib/active_support/core_ext/time/zones.rb +41 -7
- data/lib/active_support/core_ext/time.rb +7 -6
- data/lib/active_support/core_ext/uri.rb +6 -7
- data/lib/active_support/core_ext.rb +3 -1
- data/lib/active_support/current_attributes.rb +203 -0
- data/lib/active_support/dependencies/autoload.rb +2 -0
- data/lib/active_support/dependencies/interlock.rb +57 -0
- data/lib/active_support/dependencies/zeitwerk_integration.rb +117 -0
- data/lib/active_support/dependencies.rb +208 -166
- data/lib/active_support/deprecation/behaviors.rb +44 -11
- data/lib/active_support/deprecation/constant_accessor.rb +52 -0
- data/lib/active_support/deprecation/instance_delegator.rb +17 -2
- data/lib/active_support/deprecation/method_wrappers.rb +61 -21
- data/lib/active_support/deprecation/proxy_wrappers.rb +81 -30
- data/lib/active_support/deprecation/reporting.rb +32 -12
- data/lib/active_support/deprecation.rb +12 -9
- data/lib/active_support/descendants_tracker.rb +57 -9
- data/lib/active_support/digest.rb +20 -0
- data/lib/active_support/duration/iso8601_parser.rb +123 -0
- data/lib/active_support/duration/iso8601_serializer.rb +53 -0
- data/lib/active_support/duration.rb +315 -40
- data/lib/active_support/encrypted_configuration.rb +45 -0
- data/lib/active_support/encrypted_file.rb +100 -0
- data/lib/active_support/evented_file_update_checker.rb +234 -0
- data/lib/active_support/execution_wrapper.rb +129 -0
- data/lib/active_support/executor.rb +8 -0
- data/lib/active_support/file_update_checker.rb +62 -37
- data/lib/active_support/gem_version.rb +6 -4
- data/lib/active_support/gzip.rb +7 -5
- data/lib/active_support/hash_with_indifferent_access.rb +129 -30
- data/lib/active_support/i18n.rb +9 -6
- data/lib/active_support/i18n_railtie.rb +50 -14
- data/lib/active_support/inflections.rb +13 -11
- data/lib/active_support/inflector/inflections.rb +58 -13
- data/lib/active_support/inflector/methods.rb +159 -145
- data/lib/active_support/inflector/transliterate.rb +84 -34
- data/lib/active_support/inflector.rb +7 -5
- data/lib/active_support/json/decoding.rb +32 -30
- data/lib/active_support/json/encoding.rb +17 -60
- data/lib/active_support/json.rb +4 -2
- data/lib/active_support/key_generator.rb +11 -43
- 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 +2 -0
- data/lib/active_support/log_subscriber/test_helper.rb +14 -12
- data/lib/active_support/log_subscriber.rb +44 -19
- data/lib/active_support/logger.rb +9 -23
- data/lib/active_support/logger_silence.rb +32 -14
- data/lib/active_support/logger_thread_safe_level.rb +32 -8
- data/lib/active_support/message_encryptor.rb +166 -53
- data/lib/active_support/message_verifier.rb +149 -16
- data/lib/active_support/messages/metadata.rb +72 -0
- data/lib/active_support/messages/rotation_configuration.rb +22 -0
- data/lib/active_support/messages/rotator.rb +56 -0
- data/lib/active_support/multibyte/chars.rb +56 -63
- data/lib/active_support/multibyte/unicode.rb +56 -290
- data/lib/active_support/multibyte.rb +4 -2
- data/lib/active_support/notifications/fanout.rb +109 -22
- data/lib/active_support/notifications/instrumenter.rb +107 -16
- data/lib/active_support/notifications.rb +51 -10
- data/lib/active_support/number_helper/number_converter.rb +16 -15
- data/lib/active_support/number_helper/number_to_currency_converter.rb +14 -15
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +11 -4
- data/lib/active_support/number_helper/number_to_human_converter.rb +13 -10
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +11 -9
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +15 -5
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +25 -57
- data/lib/active_support/number_helper/rounding_helper.rb +66 -0
- data/lib/active_support/number_helper.rb +105 -68
- data/lib/active_support/option_merger.rb +24 -4
- data/lib/active_support/ordered_hash.rb +7 -5
- data/lib/active_support/ordered_options.rb +27 -5
- data/lib/active_support/parameter_filter.rb +128 -0
- data/lib/active_support/per_thread_registry.rb +9 -4
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/rails.rb +10 -8
- data/lib/active_support/railtie.rb +43 -9
- data/lib/active_support/reloader.rb +130 -0
- data/lib/active_support/rescuable.rb +108 -53
- data/lib/active_support/security_utils.rb +15 -11
- data/lib/active_support/string_inquirer.rb +11 -4
- data/lib/active_support/subscriber.rb +74 -30
- data/lib/active_support/tagged_logging.rb +25 -13
- data/lib/active_support/test_case.rb +107 -44
- data/lib/active_support/testing/assertions.rb +151 -20
- data/lib/active_support/testing/autorun.rb +4 -2
- 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 +13 -10
- data/lib/active_support/testing/file_fixtures.rb +38 -0
- data/lib/active_support/testing/isolation.rb +35 -26
- data/lib/active_support/testing/method_call_assertions.rb +70 -0
- data/lib/active_support/testing/parallelization.rb +134 -0
- data/lib/active_support/testing/setup_and_teardown.rb +13 -8
- data/lib/active_support/testing/stream.rb +43 -0
- data/lib/active_support/testing/tagged_logging.rb +3 -1
- data/lib/active_support/testing/time_helpers.rb +84 -20
- data/lib/active_support/time.rb +14 -12
- data/lib/active_support/time_with_zone.rb +179 -39
- data/lib/active_support/values/time_zone.rb +203 -63
- data/lib/active_support/version.rb +3 -1
- data/lib/active_support/xml_mini/jdom.rb +116 -115
- data/lib/active_support/xml_mini/libxml.rb +16 -13
- data/lib/active_support/xml_mini/libxmlsax.rb +15 -14
- data/lib/active_support/xml_mini/nokogiri.rb +14 -12
- data/lib/active_support/xml_mini/nokogirisax.rb +14 -13
- data/lib/active_support/xml_mini/rexml.rb +11 -9
- data/lib/active_support/xml_mini.rb +38 -46
- data/lib/active_support.rb +13 -11
- metadata +84 -26
- data/lib/active_support/concurrency/latch.rb +0 -27
- data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -16
- data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
- data/lib/active_support/core_ext/date_time/zones.rb +0 -6
- data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
- data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
- data/lib/active_support/core_ext/module/method_transplanting.rb +0 -13
- data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
- data/lib/active_support/core_ext/object/itself.rb +0 -15
- data/lib/active_support/core_ext/struct.rb +0 -6
- data/lib/active_support/core_ext/thread.rb +0 -86
- data/lib/active_support/core_ext/time/marshal.rb +0 -30
- 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 NumberToRoundedConverter < NumberConverter # :nodoc:
|
@@ -5,63 +9,35 @@ module ActiveSupport
|
|
5
9
|
self.validate_float = true
|
6
10
|
|
7
11
|
def convert
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
@number = number.to_d
|
18
|
-
end
|
12
|
+
helper = RoundingHelper.new(options)
|
13
|
+
rounded_number = helper.round(number)
|
14
|
+
|
15
|
+
if precision = options[:precision]
|
16
|
+
if options[:significant] && precision > 0
|
17
|
+
digits = helper.digit_count(rounded_number)
|
18
|
+
precision -= digits
|
19
|
+
precision = 0 if precision < 0 # don't let it be negative
|
20
|
+
end
|
19
21
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
22
|
+
formatted_string =
|
23
|
+
if BigDecimal === rounded_number && rounded_number.finite?
|
24
|
+
s = rounded_number.to_s("F")
|
25
|
+
s << "0" * precision
|
26
|
+
a, b = s.split(".", 2)
|
27
|
+
a << "."
|
28
|
+
a << b[0, precision]
|
29
|
+
else
|
30
|
+
"%00.#{precision}f" % rounded_number
|
31
|
+
end
|
24
32
|
else
|
25
|
-
|
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
|
33
|
+
formatted_string = rounded_number
|
28
34
|
end
|
29
35
|
|
30
|
-
formatted_string =
|
31
|
-
if BigDecimal === rounded_number && rounded_number.finite?
|
32
|
-
s = rounded_number.to_s('F') + '0'*precision
|
33
|
-
a, b = s.split('.', 2)
|
34
|
-
a + '.' + b[0, precision]
|
35
|
-
else
|
36
|
-
"%00.#{precision}f" % rounded_number
|
37
|
-
end
|
38
|
-
|
39
36
|
delimited_number = NumberToDelimitedConverter.convert(formatted_string, options)
|
40
37
|
format_number(delimited_number)
|
41
38
|
end
|
42
39
|
|
43
40
|
private
|
44
|
-
|
45
|
-
def digits_and_rounded_number(precision)
|
46
|
-
if zero?
|
47
|
-
[1, 0]
|
48
|
-
else
|
49
|
-
digits = digit_count(number)
|
50
|
-
multiplier = 10 ** (digits - precision)
|
51
|
-
rounded_number = calculate_rounded_number(multiplier)
|
52
|
-
digits = digit_count(rounded_number) # After rounding, the number of digits may have changed
|
53
|
-
[digits, rounded_number]
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
def calculate_rounded_number(multiplier)
|
58
|
-
(number / BigDecimal.new(multiplier.to_f.to_s)).round * multiplier
|
59
|
-
end
|
60
|
-
|
61
|
-
def digit_count(number)
|
62
|
-
number.zero? ? 1 : (Math.log10(absolute_number(number)) + 1).floor
|
63
|
-
end
|
64
|
-
|
65
41
|
def strip_insignificant_zeros
|
66
42
|
options[:strip_insignificant_zeros]
|
67
43
|
end
|
@@ -69,19 +45,11 @@ module ActiveSupport
|
|
69
45
|
def format_number(number)
|
70
46
|
if strip_insignificant_zeros
|
71
47
|
escaped_separator = Regexp.escape(options[:separator])
|
72
|
-
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/, "")
|
73
49
|
else
|
74
50
|
number
|
75
51
|
end
|
76
52
|
end
|
77
|
-
|
78
|
-
def absolute_number(number)
|
79
|
-
number.respond_to?(:abs) ? number.abs : number.to_d.abs
|
80
|
-
end
|
81
|
-
|
82
|
-
def zero?
|
83
|
-
number.respond_to?(:zero?) ? number.zero? : number.to_d.zero?
|
84
|
-
end
|
85
53
|
end
|
86
54
|
end
|
87
55
|
end
|
@@ -0,0 +1,66 @@
|
|
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
|
+
return number unless precision
|
14
|
+
number = convert_to_decimal(number)
|
15
|
+
if significant && precision > 0
|
16
|
+
round_significant(number)
|
17
|
+
else
|
18
|
+
round_without_significant(number)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def digit_count(number)
|
23
|
+
return 1 if number.zero?
|
24
|
+
(Math.log10(absolute_number(number)) + 1).floor
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
def round_without_significant(number)
|
29
|
+
number = number.round(precision)
|
30
|
+
number = number.to_i if precision == 0 && number.finite?
|
31
|
+
number = number.abs if number.zero? # prevent showing negative zeros
|
32
|
+
number
|
33
|
+
end
|
34
|
+
|
35
|
+
def round_significant(number)
|
36
|
+
return 0 if number.zero?
|
37
|
+
digits = digit_count(number)
|
38
|
+
multiplier = 10**(digits - precision)
|
39
|
+
(number / BigDecimal(multiplier.to_f.to_s)).round * multiplier
|
40
|
+
end
|
41
|
+
|
42
|
+
def convert_to_decimal(number)
|
43
|
+
case number
|
44
|
+
when Float, String
|
45
|
+
BigDecimal(number.to_s)
|
46
|
+
when Rational
|
47
|
+
BigDecimal(number, digit_count(number.to_i) + precision)
|
48
|
+
else
|
49
|
+
number.to_d
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def precision
|
54
|
+
options[:precision]
|
55
|
+
end
|
56
|
+
|
57
|
+
def significant
|
58
|
+
options[:significant]
|
59
|
+
end
|
60
|
+
|
61
|
+
def absolute_number(number)
|
62
|
+
number.respond_to?(:abs) ? number.abs : number.to_d.abs
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -1,9 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/dependencies/autoload"
|
4
|
+
|
1
5
|
module ActiveSupport
|
2
6
|
module NumberHelper
|
3
7
|
extend ActiveSupport::Autoload
|
4
8
|
|
5
9
|
eager_autoload do
|
6
10
|
autoload :NumberConverter
|
11
|
+
autoload :RoundingHelper
|
7
12
|
autoload :NumberToRoundedConverter
|
8
13
|
autoload :NumberToDelimitedConverter
|
9
14
|
autoload :NumberToHumanConverter
|
@@ -15,7 +20,7 @@ module ActiveSupport
|
|
15
20
|
|
16
21
|
extend self
|
17
22
|
|
18
|
-
# Formats a +number+ into a
|
23
|
+
# Formats a +number+ into a phone number (US by default e.g., (555)
|
19
24
|
# 123-9876). You can customize the format in the +options+ hash.
|
20
25
|
#
|
21
26
|
# ==== Options
|
@@ -27,19 +32,26 @@ module ActiveSupport
|
|
27
32
|
# end of the generated number.
|
28
33
|
# * <tt>:country_code</tt> - Sets the country code for the phone
|
29
34
|
# number.
|
35
|
+
# * <tt>:pattern</tt> - Specifies how the number is divided into three
|
36
|
+
# groups with the custom regexp to override the default format.
|
30
37
|
# ==== Examples
|
31
38
|
#
|
32
|
-
# number_to_phone(5551234) # => 555-1234
|
33
|
-
# number_to_phone('5551234') # => 555-1234
|
34
|
-
# number_to_phone(1235551234) # => 123-555-1234
|
35
|
-
# number_to_phone(1235551234, area_code: true) # => (123) 555-1234
|
36
|
-
# number_to_phone(1235551234, delimiter: ' ') # => 123 555 1234
|
37
|
-
# number_to_phone(1235551234, area_code: true, extension: 555) # => (123) 555-1234 x 555
|
38
|
-
# number_to_phone(1235551234, country_code: 1) # => +1-123-555-1234
|
39
|
-
# number_to_phone('123a456') # => 123a456
|
39
|
+
# number_to_phone(5551234) # => "555-1234"
|
40
|
+
# number_to_phone('5551234') # => "555-1234"
|
41
|
+
# number_to_phone(1235551234) # => "123-555-1234"
|
42
|
+
# number_to_phone(1235551234, area_code: true) # => "(123) 555-1234"
|
43
|
+
# number_to_phone(1235551234, delimiter: ' ') # => "123 555 1234"
|
44
|
+
# number_to_phone(1235551234, area_code: true, extension: 555) # => "(123) 555-1234 x 555"
|
45
|
+
# number_to_phone(1235551234, country_code: 1) # => "+1-123-555-1234"
|
46
|
+
# number_to_phone('123a456') # => "123a456"
|
40
47
|
#
|
41
48
|
# number_to_phone(1235551234, country_code: 1, extension: 1343, delimiter: '.')
|
42
|
-
# # => +1.123.555.1234 x 1343
|
49
|
+
# # => "+1.123.555.1234 x 1343"
|
50
|
+
#
|
51
|
+
# number_to_phone(75561234567, pattern: /(\d{1,4})(\d{4})(\d{4})$/, area_code: true)
|
52
|
+
# # => "(755) 6123-4567"
|
53
|
+
# number_to_phone(13312345678, pattern: /(\d{3})(\d{4})(\d{4})$/)
|
54
|
+
# # => "133-1234-5678"
|
43
55
|
def number_to_phone(number, options = {})
|
44
56
|
NumberToPhoneConverter.convert(number, options)
|
45
57
|
end
|
@@ -47,6 +59,14 @@ module ActiveSupport
|
|
47
59
|
# Formats a +number+ into a currency string (e.g., $13.65). You
|
48
60
|
# can customize the format in the +options+ hash.
|
49
61
|
#
|
62
|
+
# The currency unit and number formatting of the current locale will be used
|
63
|
+
# unless otherwise specified in the provided options. No currency conversion
|
64
|
+
# is performed. If the user is given a way to change their locale, they will
|
65
|
+
# also be able to change the relative value of the currency displayed with
|
66
|
+
# this helper. If your application will ever support multiple locales, you
|
67
|
+
# may want to specify a constant <tt>:locale</tt> option or consider
|
68
|
+
# using a library capable of currency conversion.
|
69
|
+
#
|
50
70
|
# ==== Options
|
51
71
|
#
|
52
72
|
# * <tt>:locale</tt> - Sets the locale to be used for formatting
|
@@ -63,25 +83,34 @@ module ActiveSupport
|
|
63
83
|
# (defaults to "%u%n"). Fields are <tt>%u</tt> for the
|
64
84
|
# currency, and <tt>%n</tt> for the number.
|
65
85
|
# * <tt>:negative_format</tt> - Sets the format for negative
|
66
|
-
# numbers (defaults to prepending
|
86
|
+
# numbers (defaults to prepending a hyphen to the formatted
|
67
87
|
# number given by <tt>:format</tt>). Accepts the same fields
|
68
88
|
# than <tt>:format</tt>, except <tt>%n</tt> is here the
|
69
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+).
|
70
93
|
#
|
71
94
|
# ==== Examples
|
72
95
|
#
|
73
|
-
# number_to_currency(1234567890.50) # => $1,234,567,890.50
|
74
|
-
# number_to_currency(1234567890.506) # => $1,234,567,890.51
|
75
|
-
# number_to_currency(1234567890.506, precision: 3) # => $1,234,567,890.506
|
76
|
-
# number_to_currency(1234567890.506, locale: :fr) # => 1 234 567 890,51 €
|
77
|
-
# number_to_currency('123a456') # => $123a456
|
96
|
+
# number_to_currency(1234567890.50) # => "$1,234,567,890.50"
|
97
|
+
# number_to_currency(1234567890.506) # => "$1,234,567,890.51"
|
98
|
+
# number_to_currency(1234567890.506, precision: 3) # => "$1,234,567,890.506"
|
99
|
+
# number_to_currency(1234567890.506, locale: :fr) # => "1 234 567 890,51 €"
|
100
|
+
# number_to_currency('123a456') # => "$123a456"
|
101
|
+
#
|
102
|
+
# number_to_currency("123a456", raise: true) # => InvalidNumberError
|
78
103
|
#
|
104
|
+
# number_to_currency(-0.456789, precision: 0)
|
105
|
+
# # => "$0"
|
79
106
|
# number_to_currency(-1234567890.50, negative_format: '(%u%n)')
|
80
|
-
# # => ($1,234,567,890.50)
|
107
|
+
# # => "($1,234,567,890.50)"
|
81
108
|
# number_to_currency(1234567890.50, unit: '£', separator: ',', delimiter: '')
|
82
|
-
# # => £1234567890,50
|
109
|
+
# # => "£1234567890,50"
|
83
110
|
# number_to_currency(1234567890.50, unit: '£', separator: ',', delimiter: '', format: '%n %u')
|
84
|
-
# # => 1234567890,50 £
|
111
|
+
# # => "1234567890,50 £"
|
112
|
+
# number_to_currency(1234567890.50, strip_insignificant_zeros: true)
|
113
|
+
# # => "$1,234,567,890.5"
|
85
114
|
def number_to_currency(number, options = {})
|
86
115
|
NumberToCurrencyConverter.convert(number, options)
|
87
116
|
end
|
@@ -94,9 +123,9 @@ module ActiveSupport
|
|
94
123
|
# * <tt>:locale</tt> - Sets the locale to be used for formatting
|
95
124
|
# (defaults to current locale).
|
96
125
|
# * <tt>:precision</tt> - Sets the precision of the number
|
97
|
-
# (defaults to 3).
|
98
|
-
# * <tt>:significant</tt> - If +true+, precision will be the
|
99
|
-
# of significant_digits. If +false+, the
|
126
|
+
# (defaults to 3). Keeps the number's precision if +nil+.
|
127
|
+
# * <tt>:significant</tt> - If +true+, precision will be the number
|
128
|
+
# of significant_digits. If +false+, the number of fractional
|
100
129
|
# digits (defaults to +false+).
|
101
130
|
# * <tt>:separator</tt> - Sets the separator between the
|
102
131
|
# fractional and integer digits (defaults to ".").
|
@@ -110,14 +139,15 @@ module ActiveSupport
|
|
110
139
|
#
|
111
140
|
# ==== Examples
|
112
141
|
#
|
113
|
-
# number_to_percentage(100) # => 100.000%
|
114
|
-
# number_to_percentage('98') # => 98.000%
|
115
|
-
# number_to_percentage(100, precision: 0) # => 100%
|
116
|
-
# number_to_percentage(1000, delimiter: '.', separator: ',') # => 1.000,000%
|
117
|
-
# number_to_percentage(302.24398923423, precision: 5) # => 302.24399%
|
118
|
-
# number_to_percentage(1000, locale: :fr) # =>
|
119
|
-
# number_to_percentage(
|
120
|
-
# number_to_percentage(
|
142
|
+
# number_to_percentage(100) # => "100.000%"
|
143
|
+
# number_to_percentage('98') # => "98.000%"
|
144
|
+
# number_to_percentage(100, precision: 0) # => "100%"
|
145
|
+
# number_to_percentage(1000, delimiter: '.', separator: ',') # => "1.000,000%"
|
146
|
+
# number_to_percentage(302.24398923423, precision: 5) # => "302.24399%"
|
147
|
+
# number_to_percentage(1000, locale: :fr) # => "1000,000%"
|
148
|
+
# number_to_percentage(1000, precision: nil) # => "1000%"
|
149
|
+
# number_to_percentage('98a') # => "98a%"
|
150
|
+
# number_to_percentage(100, format: '%n %') # => "100.000 %"
|
121
151
|
def number_to_percentage(number, options = {})
|
122
152
|
NumberToPercentageConverter.convert(number, options)
|
123
153
|
end
|
@@ -134,19 +164,25 @@ module ActiveSupport
|
|
134
164
|
# to ",").
|
135
165
|
# * <tt>:separator</tt> - Sets the separator between the
|
136
166
|
# fractional and integer digits (defaults to ".").
|
167
|
+
# * <tt>:delimiter_pattern</tt> - Sets a custom regular expression used for
|
168
|
+
# deriving the placement of delimiter. Helpful when using currency formats
|
169
|
+
# like INR.
|
137
170
|
#
|
138
171
|
# ==== Examples
|
139
172
|
#
|
140
|
-
# number_to_delimited(12345678) # => 12,345,678
|
141
|
-
# number_to_delimited('123456') # => 123,456
|
142
|
-
# number_to_delimited(12345678.05) # => 12,345,678.05
|
143
|
-
# number_to_delimited(12345678, delimiter: '.') # => 12.345.678
|
144
|
-
# number_to_delimited(12345678, delimiter: ',') # => 12,345,678
|
145
|
-
# number_to_delimited(12345678.05, separator: ' ') # => 12,345,678 05
|
146
|
-
# number_to_delimited(12345678.05, locale: :fr) # => 12 345 678,05
|
147
|
-
# number_to_delimited('112a') # => 112a
|
173
|
+
# number_to_delimited(12345678) # => "12,345,678"
|
174
|
+
# number_to_delimited('123456') # => "123,456"
|
175
|
+
# number_to_delimited(12345678.05) # => "12,345,678.05"
|
176
|
+
# number_to_delimited(12345678, delimiter: '.') # => "12.345.678"
|
177
|
+
# number_to_delimited(12345678, delimiter: ',') # => "12,345,678"
|
178
|
+
# number_to_delimited(12345678.05, separator: ' ') # => "12,345,678 05"
|
179
|
+
# number_to_delimited(12345678.05, locale: :fr) # => "12 345 678,05"
|
180
|
+
# number_to_delimited('112a') # => "112a"
|
148
181
|
# number_to_delimited(98765432.98, delimiter: ' ', separator: ',')
|
149
|
-
#
|
182
|
+
# # => "98 765 432,98"
|
183
|
+
# number_to_delimited("123456.78",
|
184
|
+
# delimiter_pattern: /(\d+?)(?=(\d\d)+(\d)(?!\d))/)
|
185
|
+
# # => "1,23,456.78"
|
150
186
|
def number_to_delimited(number, options = {})
|
151
187
|
NumberToDelimitedConverter.convert(number, options)
|
152
188
|
end
|
@@ -161,9 +197,9 @@ module ActiveSupport
|
|
161
197
|
# * <tt>:locale</tt> - Sets the locale to be used for formatting
|
162
198
|
# (defaults to current locale).
|
163
199
|
# * <tt>:precision</tt> - Sets the precision of the number
|
164
|
-
# (defaults to 3).
|
165
|
-
# * <tt>:significant</tt> - If +true+, precision will be the
|
166
|
-
# of significant_digits. If +false+, the
|
200
|
+
# (defaults to 3). Keeps the number's precision if +nil+.
|
201
|
+
# * <tt>:significant</tt> - If +true+, precision will be the number
|
202
|
+
# of significant_digits. If +false+, the number of fractional
|
167
203
|
# digits (defaults to +false+).
|
168
204
|
# * <tt>:separator</tt> - Sets the separator between the
|
169
205
|
# fractional and integer digits (defaults to ".").
|
@@ -175,21 +211,22 @@ module ActiveSupport
|
|
175
211
|
#
|
176
212
|
# ==== Examples
|
177
213
|
#
|
178
|
-
# number_to_rounded(111.2345) # => 111.235
|
179
|
-
# number_to_rounded(111.2345, precision: 2) # => 111.23
|
180
|
-
# number_to_rounded(13, precision: 5) # => 13.00000
|
181
|
-
# number_to_rounded(389.32314, precision: 0) # => 389
|
182
|
-
# number_to_rounded(111.2345, significant: true) # => 111
|
183
|
-
# number_to_rounded(111.2345, precision: 1, significant: true) # => 100
|
184
|
-
# number_to_rounded(13, precision: 5, significant: true) # => 13.000
|
185
|
-
# number_to_rounded(
|
214
|
+
# number_to_rounded(111.2345) # => "111.235"
|
215
|
+
# number_to_rounded(111.2345, precision: 2) # => "111.23"
|
216
|
+
# number_to_rounded(13, precision: 5) # => "13.00000"
|
217
|
+
# number_to_rounded(389.32314, precision: 0) # => "389"
|
218
|
+
# number_to_rounded(111.2345, significant: true) # => "111"
|
219
|
+
# number_to_rounded(111.2345, precision: 1, significant: true) # => "100"
|
220
|
+
# number_to_rounded(13, precision: 5, significant: true) # => "13.000"
|
221
|
+
# number_to_rounded(13, precision: nil) # => "13"
|
222
|
+
# number_to_rounded(111.234, locale: :fr) # => "111,234"
|
186
223
|
#
|
187
224
|
# number_to_rounded(13, precision: 5, significant: true, strip_insignificant_zeros: true)
|
188
|
-
# # => 13
|
225
|
+
# # => "13"
|
189
226
|
#
|
190
|
-
# number_to_rounded(389.32314, precision: 4, significant: true) # => 389.3
|
227
|
+
# number_to_rounded(389.32314, precision: 4, significant: true) # => "389.3"
|
191
228
|
# number_to_rounded(1111.2345, precision: 2, separator: ',', delimiter: '.')
|
192
|
-
# # => 1.111,23
|
229
|
+
# # => "1.111,23"
|
193
230
|
def number_to_rounded(number, options = {})
|
194
231
|
NumberToRoundedConverter.convert(number, options)
|
195
232
|
end
|
@@ -208,8 +245,8 @@ module ActiveSupport
|
|
208
245
|
# (defaults to current locale).
|
209
246
|
# * <tt>:precision</tt> - Sets the precision of the number
|
210
247
|
# (defaults to 3).
|
211
|
-
# * <tt>:significant</tt> - If +true+, precision will be the
|
212
|
-
# of significant_digits. If +false+, the
|
248
|
+
# * <tt>:significant</tt> - If +true+, precision will be the number
|
249
|
+
# of significant_digits. If +false+, the number of fractional
|
213
250
|
# digits (defaults to +true+)
|
214
251
|
# * <tt>:separator</tt> - Sets the separator between the
|
215
252
|
# fractional and integer digits (defaults to ".").
|
@@ -218,20 +255,20 @@ module ActiveSupport
|
|
218
255
|
# * <tt>:strip_insignificant_zeros</tt> - If +true+ removes
|
219
256
|
# insignificant zeros after the decimal separator (defaults to
|
220
257
|
# +true+)
|
221
|
-
# * <tt>:prefix</tt> - If +:si+ formats the number using the SI
|
222
|
-
# prefix (defaults to :binary)
|
223
258
|
#
|
224
259
|
# ==== Examples
|
225
260
|
#
|
226
|
-
# number_to_human_size(123) # => 123 Bytes
|
227
|
-
# number_to_human_size(1234) # => 1.21 KB
|
228
|
-
# number_to_human_size(12345) # => 12.1 KB
|
229
|
-
# number_to_human_size(1234567) # => 1.18 MB
|
230
|
-
# number_to_human_size(1234567890) # => 1.15 GB
|
231
|
-
# number_to_human_size(1234567890123) # => 1.12 TB
|
232
|
-
# number_to_human_size(
|
233
|
-
# number_to_human_size(
|
234
|
-
# number_to_human_size(1234567, precision: 2
|
261
|
+
# number_to_human_size(123) # => "123 Bytes"
|
262
|
+
# number_to_human_size(1234) # => "1.21 KB"
|
263
|
+
# number_to_human_size(12345) # => "12.1 KB"
|
264
|
+
# number_to_human_size(1234567) # => "1.18 MB"
|
265
|
+
# number_to_human_size(1234567890) # => "1.15 GB"
|
266
|
+
# number_to_human_size(1234567890123) # => "1.12 TB"
|
267
|
+
# number_to_human_size(1234567890123456) # => "1.1 PB"
|
268
|
+
# number_to_human_size(1234567890123456789) # => "1.07 EB"
|
269
|
+
# number_to_human_size(1234567, precision: 2) # => "1.2 MB"
|
270
|
+
# number_to_human_size(483989, precision: 2) # => "470 KB"
|
271
|
+
# number_to_human_size(1234567, precision: 2, separator: ',') # => "1,2 MB"
|
235
272
|
# number_to_human_size(1234567890123, precision: 5) # => "1.1228 TB"
|
236
273
|
# number_to_human_size(524288000, precision: 5) # => "500 MB"
|
237
274
|
def number_to_human_size(number, options = {})
|
@@ -258,8 +295,8 @@ module ActiveSupport
|
|
258
295
|
# (defaults to current locale).
|
259
296
|
# * <tt>:precision</tt> - Sets the precision of the number
|
260
297
|
# (defaults to 3).
|
261
|
-
# * <tt>:significant</tt> - If +true+, precision will be the
|
262
|
-
# of significant_digits. If +false+, the
|
298
|
+
# * <tt>:significant</tt> - If +true+, precision will be the number
|
299
|
+
# of significant_digits. If +false+, the number of fractional
|
263
300
|
# digits (defaults to +true+)
|
264
301
|
# * <tt>:separator</tt> - Sets the separator between the
|
265
302
|
# fractional and integer digits (defaults to ".").
|
@@ -1,9 +1,11 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/hash/deep_merge"
|
2
4
|
|
3
5
|
module ActiveSupport
|
4
6
|
class OptionMerger #:nodoc:
|
5
7
|
instance_methods.each do |method|
|
6
|
-
undef_method(method) if
|
8
|
+
undef_method(method) if !/^(__|instance_eval|class|object_id)/.match?(method)
|
7
9
|
end
|
8
10
|
|
9
11
|
def initialize(context, options)
|
@@ -12,14 +14,32 @@ module ActiveSupport
|
|
12
14
|
|
13
15
|
private
|
14
16
|
def method_missing(method, *arguments, &block)
|
17
|
+
options = nil
|
15
18
|
if arguments.first.is_a?(Proc)
|
16
19
|
proc = arguments.pop
|
17
20
|
arguments << lambda { |*args| @options.deep_merge(proc.call(*args)) }
|
21
|
+
elsif arguments.last.respond_to?(:to_hash)
|
22
|
+
options = @options.deep_merge(arguments.pop)
|
18
23
|
else
|
19
|
-
|
24
|
+
options = @options
|
20
25
|
end
|
21
26
|
|
22
|
-
|
27
|
+
invoke_method(method, arguments, options, &block)
|
28
|
+
end
|
29
|
+
|
30
|
+
if RUBY_VERSION >= "2.7"
|
31
|
+
def invoke_method(method, arguments, options, &block)
|
32
|
+
if options
|
33
|
+
@context.__send__(method, *arguments, **options, &block)
|
34
|
+
else
|
35
|
+
@context.__send__(method, *arguments, &block)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
else
|
39
|
+
def invoke_method(method, arguments, options, &block)
|
40
|
+
arguments << options if options
|
41
|
+
@context.__send__(method, *arguments, &block)
|
42
|
+
end
|
23
43
|
end
|
24
44
|
end
|
25
45
|
end
|
@@ -1,11 +1,13 @@
|
|
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
|
8
|
-
# <tt>ActiveSupport::OrderedHash</tt> implements a hash that preserves
|
10
|
+
# DEPRECATED: <tt>ActiveSupport::OrderedHash</tt> implements a hash that preserves
|
9
11
|
# insertion order.
|
10
12
|
#
|
11
13
|
# oh = ActiveSupport::OrderedHash.new
|
@@ -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,3 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/object/blank"
|
4
|
+
|
1
5
|
module ActiveSupport
|
2
6
|
# Usually key value pairs are handled something like this:
|
3
7
|
#
|
@@ -6,6 +10,7 @@ module ActiveSupport
|
|
6
10
|
# h[:girl] = 'Mary'
|
7
11
|
# h[:boy] # => 'John'
|
8
12
|
# h[:girl] # => 'Mary'
|
13
|
+
# h[:dog] # => nil
|
9
14
|
#
|
10
15
|
# Using +OrderedOptions+, the above code could be reduced to:
|
11
16
|
#
|
@@ -14,6 +19,13 @@ module ActiveSupport
|
|
14
19
|
# h.girl = 'Mary'
|
15
20
|
# h.boy # => 'John'
|
16
21
|
# h.girl # => 'Mary'
|
22
|
+
# h.dog # => nil
|
23
|
+
#
|
24
|
+
# To raise an exception when the value is blank, append a
|
25
|
+
# bang to the key name, like:
|
26
|
+
#
|
27
|
+
# h.dog! # => raises KeyError: :dog is blank
|
28
|
+
#
|
17
29
|
class OrderedOptions < Hash
|
18
30
|
alias_method :_get, :[] # preserve the original #[] method
|
19
31
|
protected :_get # make it protected
|
@@ -27,17 +39,27 @@ module ActiveSupport
|
|
27
39
|
end
|
28
40
|
|
29
41
|
def method_missing(name, *args)
|
30
|
-
name_string = name.to_s
|
31
|
-
if name_string.chomp!(
|
42
|
+
name_string = +name.to_s
|
43
|
+
if name_string.chomp!("=")
|
32
44
|
self[name_string] = args.first
|
33
45
|
else
|
34
|
-
|
46
|
+
bangs = name_string.chomp!("!")
|
47
|
+
|
48
|
+
if bangs
|
49
|
+
self[name_string].presence || raise(KeyError.new(":#{name_string} is blank"))
|
50
|
+
else
|
51
|
+
self[name_string]
|
52
|
+
end
|
35
53
|
end
|
36
54
|
end
|
37
55
|
|
38
56
|
def respond_to_missing?(name, include_private)
|
39
57
|
true
|
40
58
|
end
|
59
|
+
|
60
|
+
def extractable_options?
|
61
|
+
true
|
62
|
+
end
|
41
63
|
end
|
42
64
|
|
43
65
|
# +InheritableOptions+ provides a constructor to build an +OrderedOptions+
|
@@ -52,9 +74,9 @@ module ActiveSupport
|
|
52
74
|
def initialize(parent = nil)
|
53
75
|
if parent.kind_of?(OrderedOptions)
|
54
76
|
# use the faster _get when dealing with OrderedOptions
|
55
|
-
super() { |h,k| parent._get(k) }
|
77
|
+
super() { |h, k| parent._get(k) }
|
56
78
|
elsif parent
|
57
|
-
super() { |h,k| parent[k] }
|
79
|
+
super() { |h, k| parent[k] }
|
58
80
|
else
|
59
81
|
super()
|
60
82
|
end
|