activesupport 5.1.7 → 7.0.4.1
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 +4 -4
- data/CHANGELOG.md +259 -585
- data/MIT-LICENSE +1 -1
- data/README.rdoc +6 -5
- data/lib/active_support/actionable_error.rb +48 -0
- data/lib/active_support/all.rb +2 -0
- data/lib/active_support/array_inquirer.rb +4 -2
- data/lib/active_support/backtrace_cleaner.rb +33 -5
- data/lib/active_support/benchmarkable.rb +5 -3
- data/lib/active_support/builder.rb +2 -0
- data/lib/active_support/cache/file_store.rb +50 -43
- data/lib/active_support/cache/mem_cache_store.rb +194 -67
- data/lib/active_support/cache/memory_store.rb +70 -34
- data/lib/active_support/cache/null_store.rb +18 -3
- data/lib/active_support/cache/redis_cache_store.rb +474 -0
- data/lib/active_support/cache/strategy/local_cache.rb +73 -50
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +2 -0
- data/lib/active_support/cache.rb +556 -220
- data/lib/active_support/callbacks.rb +264 -159
- data/lib/active_support/code_generator.rb +65 -0
- data/lib/active_support/concern.rb +81 -8
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +16 -0
- data/lib/active_support/concurrency/share_lock.rb +4 -3
- data/lib/active_support/configurable.rb +17 -16
- data/lib/active_support/configuration_file.rb +51 -0
- data/lib/active_support/core_ext/array/access.rb +18 -8
- data/lib/active_support/core_ext/array/conversions.rb +20 -17
- data/lib/active_support/core_ext/array/deprecated_conversions.rb +25 -0
- 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 +8 -6
- data/lib/active_support/core_ext/array/inquiry.rb +4 -2
- data/lib/active_support/core_ext/array/wrap.rb +2 -0
- data/lib/active_support/core_ext/array.rb +4 -1
- data/lib/active_support/core_ext/benchmark.rb +4 -2
- data/lib/active_support/core_ext/big_decimal/conversions.rb +3 -1
- data/lib/active_support/core_ext/big_decimal.rb +2 -0
- data/lib/active_support/core_ext/class/attribute.rb +50 -47
- data/lib/active_support/core_ext/class/attribute_accessors.rb +2 -0
- data/lib/active_support/core_ext/class/subclasses.rb +10 -24
- data/lib/active_support/core_ext/class.rb +2 -0
- data/lib/active_support/core_ext/date/acts_like.rb +2 -0
- data/lib/active_support/core_ext/date/blank.rb +3 -1
- data/lib/active_support/core_ext/date/calculations.rb +17 -14
- data/lib/active_support/core_ext/date/conversions.rb +24 -22
- data/lib/active_support/core_ext/date/deprecated_conversions.rb +26 -0
- data/lib/active_support/core_ext/date/zones.rb +2 -0
- data/lib/active_support/core_ext/date.rb +3 -0
- data/lib/active_support/core_ext/date_and_time/calculations.rb +65 -41
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +18 -1
- data/lib/active_support/core_ext/date_and_time/zones.rb +2 -1
- data/lib/active_support/core_ext/date_time/acts_like.rb +2 -0
- data/lib/active_support/core_ext/date_time/blank.rb +3 -1
- data/lib/active_support/core_ext/date_time/calculations.rb +3 -1
- data/lib/active_support/core_ext/date_time/compatibility.rb +7 -5
- data/lib/active_support/core_ext/date_time/conversions.rb +15 -14
- data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +22 -0
- data/lib/active_support/core_ext/date_time.rb +3 -0
- data/lib/active_support/core_ext/digest/uuid.rb +42 -14
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/enumerable.rb +244 -72
- data/lib/active_support/core_ext/file/atomic.rb +6 -2
- data/lib/active_support/core_ext/file.rb +2 -0
- data/lib/active_support/core_ext/hash/conversions.rb +7 -6
- 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 +5 -3
- data/lib/active_support/core_ext/hash/keys.rb +4 -31
- 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 +3 -2
- data/lib/active_support/core_ext/integer/inflections.rb +2 -0
- data/lib/active_support/core_ext/integer/multiple.rb +3 -1
- data/lib/active_support/core_ext/integer/time.rb +7 -14
- data/lib/active_support/core_ext/integer.rb +2 -0
- data/lib/active_support/core_ext/kernel/concern.rb +2 -0
- data/lib/active_support/core_ext/kernel/reporting.rb +6 -4
- data/lib/active_support/core_ext/kernel/singleton_class.rb +3 -1
- data/lib/active_support/core_ext/kernel.rb +2 -1
- data/lib/active_support/core_ext/load_error.rb +3 -8
- data/lib/active_support/core_ext/module/aliasing.rb +2 -0
- data/lib/active_support/core_ext/module/anonymous.rb +2 -0
- data/lib/active_support/core_ext/module/attr_internal.rb +4 -2
- data/lib/active_support/core_ext/module/attribute_accessors.rb +46 -56
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +36 -27
- data/lib/active_support/core_ext/module/concerning.rb +15 -10
- data/lib/active_support/core_ext/module/delegation.rb +97 -58
- data/lib/active_support/core_ext/module/deprecation.rb +2 -0
- data/lib/active_support/core_ext/module/introspection.rb +18 -15
- 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 +3 -1
- data/lib/active_support/core_ext/name_error.rb +30 -2
- data/lib/active_support/core_ext/numeric/bytes.rb +2 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +134 -129
- data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +60 -0
- data/lib/active_support/core_ext/numeric/time.rb +7 -15
- data/lib/active_support/core_ext/numeric.rb +3 -1
- data/lib/active_support/core_ext/object/acts_like.rb +41 -6
- data/lib/active_support/core_ext/object/blank.rb +15 -5
- data/lib/active_support/core_ext/object/conversions.rb +2 -0
- data/lib/active_support/core_ext/object/deep_dup.rb +3 -1
- data/lib/active_support/core_ext/object/duplicable.rb +16 -110
- data/lib/active_support/core_ext/object/inclusion.rb +2 -0
- data/lib/active_support/core_ext/object/instance_variables.rb +2 -0
- data/lib/active_support/core_ext/object/json.rb +51 -26
- data/lib/active_support/core_ext/object/to_param.rb +2 -0
- data/lib/active_support/core_ext/object/to_query.rb +4 -2
- data/lib/active_support/core_ext/object/try.rb +26 -14
- data/lib/active_support/core_ext/object/with_options.rb +24 -3
- data/lib/active_support/core_ext/object.rb +2 -0
- data/lib/active_support/core_ext/pathname/existence.rb +21 -0
- data/lib/active_support/core_ext/pathname.rb +3 -0
- data/lib/active_support/core_ext/range/compare_range.rb +57 -0
- data/lib/active_support/core_ext/range/conversions.rb +35 -25
- data/lib/active_support/core_ext/range/deprecated_conversions.rb +26 -0
- data/lib/active_support/core_ext/range/each.rb +6 -3
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +7 -0
- data/lib/active_support/core_ext/range/overlaps.rb +3 -1
- data/lib/active_support/core_ext/range.rb +4 -1
- data/lib/active_support/core_ext/regexp.rb +10 -5
- data/lib/active_support/core_ext/securerandom.rb +25 -3
- data/lib/active_support/core_ext/string/access.rb +7 -16
- 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 +44 -1
- data/lib/active_support/core_ext/string/indent.rb +2 -0
- data/lib/active_support/core_ext/string/inflections.rb +69 -16
- data/lib/active_support/core_ext/string/inquiry.rb +4 -1
- data/lib/active_support/core_ext/string/multibyte.rb +9 -4
- data/lib/active_support/core_ext/string/output_safety.rb +135 -27
- 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 +2 -0
- data/lib/active_support/core_ext/string.rb +2 -0
- 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/time/acts_like.rb +2 -0
- data/lib/active_support/core_ext/time/calculations.rb +81 -24
- data/lib/active_support/core_ext/time/compatibility.rb +4 -2
- data/lib/active_support/core_ext/time/conversions.rb +17 -12
- data/lib/active_support/core_ext/time/deprecated_conversions.rb +22 -0
- data/lib/active_support/core_ext/time/zones.rb +12 -25
- data/lib/active_support/core_ext/time.rb +3 -0
- data/lib/active_support/core_ext/uri.rb +4 -23
- data/lib/active_support/core_ext.rb +4 -1
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/current_attributes.rb +226 -0
- data/lib/active_support/dependencies/autoload.rb +2 -0
- data/lib/active_support/dependencies/interlock.rb +12 -18
- data/lib/active_support/dependencies/require_dependency.rb +28 -0
- data/lib/active_support/dependencies.rb +59 -715
- data/lib/active_support/deprecation/behaviors.rb +48 -13
- data/lib/active_support/deprecation/constant_accessor.rb +4 -2
- data/lib/active_support/deprecation/disallowed.rb +56 -0
- data/lib/active_support/deprecation/instance_delegator.rb +2 -1
- data/lib/active_support/deprecation/method_wrappers.rb +29 -21
- data/lib/active_support/deprecation/proxy_wrappers.rb +34 -8
- data/lib/active_support/deprecation/reporting.rb +54 -9
- data/lib/active_support/deprecation.rb +10 -3
- data/lib/active_support/descendants_tracker.rb +192 -34
- data/lib/active_support/digest.rb +22 -0
- data/lib/active_support/duration/iso8601_parser.rb +9 -9
- data/lib/active_support/duration/iso8601_serializer.rb +29 -15
- data/lib/active_support/duration.rb +158 -72
- data/lib/active_support/encrypted_configuration.rb +56 -0
- data/lib/active_support/encrypted_file.rb +129 -0
- data/lib/active_support/environment_inquirer.rb +20 -0
- data/lib/active_support/error_reporter.rb +117 -0
- data/lib/active_support/evented_file_update_checker.rb +87 -122
- data/lib/active_support/execution_context/test_helper.rb +13 -0
- data/lib/active_support/execution_context.rb +53 -0
- data/lib/active_support/execution_wrapper.rb +46 -21
- data/lib/active_support/executor/test_helper.rb +7 -0
- data/lib/active_support/executor.rb +2 -0
- data/lib/active_support/file_update_checker.rb +2 -1
- data/lib/active_support/fork_tracker.rb +71 -0
- data/lib/active_support/gem_version.rb +7 -5
- data/lib/active_support/gzip.rb +2 -0
- data/lib/active_support/hash_with_indifferent_access.rb +126 -42
- data/lib/active_support/html_safe_translation.rb +43 -0
- data/lib/active_support/i18n.rb +5 -1
- data/lib/active_support/i18n_railtie.rb +19 -14
- data/lib/active_support/inflections.rb +2 -0
- data/lib/active_support/inflector/inflections.rb +41 -14
- data/lib/active_support/inflector/methods.rb +73 -87
- data/lib/active_support/inflector/transliterate.rb +56 -18
- data/lib/active_support/inflector.rb +2 -0
- data/lib/active_support/isolated_execution_state.rb +72 -0
- data/lib/active_support/json/decoding.rb +27 -26
- data/lib/active_support/json/encoding.rb +16 -6
- data/lib/active_support/json.rb +2 -0
- data/lib/active_support/key_generator.rb +25 -38
- data/lib/active_support/lazy_load_hooks.rb +35 -6
- data/lib/active_support/locale/en.rb +33 -0
- data/lib/active_support/locale/en.yml +8 -4
- data/lib/active_support/log_subscriber/test_helper.rb +4 -2
- data/lib/active_support/log_subscriber.rb +54 -13
- data/lib/active_support/logger.rb +4 -17
- data/lib/active_support/logger_silence.rb +13 -20
- data/lib/active_support/logger_thread_safe_level.rb +48 -10
- data/lib/active_support/message_encryptor.rb +111 -37
- data/lib/active_support/message_verifier.rb +124 -21
- 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 +19 -76
- data/lib/active_support/multibyte/unicode.rb +9 -331
- data/lib/active_support/multibyte.rb +3 -1
- data/lib/active_support/notifications/fanout.rb +165 -37
- data/lib/active_support/notifications/instrumenter.rb +92 -11
- data/lib/active_support/notifications.rb +96 -30
- data/lib/active_support/number_helper/number_converter.rb +8 -9
- data/lib/active_support/number_helper/number_to_currency_converter.rb +14 -12
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +6 -3
- data/lib/active_support/number_helper/number_to_human_converter.rb +6 -3
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +7 -4
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +6 -3
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +14 -27
- data/lib/active_support/number_helper/rounding_helper.rb +16 -34
- data/lib/active_support/number_helper.rb +38 -12
- data/lib/active_support/option_merger.rb +19 -6
- data/lib/active_support/ordered_hash.rb +4 -2
- data/lib/active_support/ordered_options.rb +18 -6
- data/lib/active_support/parameter_filter.rb +138 -0
- data/lib/active_support/per_thread_registry.rb +8 -1
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/rails.rb +3 -10
- data/lib/active_support/railtie.rb +112 -11
- data/lib/active_support/reloader.rb +12 -11
- data/lib/active_support/rescuable.rb +19 -18
- data/lib/active_support/ruby_features.rb +7 -0
- 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 +4 -3
- data/lib/active_support/subscriber.rb +81 -42
- data/lib/active_support/tagged_logging.rb +45 -9
- data/lib/active_support/test_case.rb +86 -2
- data/lib/active_support/testing/assertions.rb +89 -21
- data/lib/active_support/testing/autorun.rb +2 -0
- data/lib/active_support/testing/constant_lookup.rb +2 -0
- data/lib/active_support/testing/declarative.rb +2 -0
- data/lib/active_support/testing/deprecation.rb +54 -2
- data/lib/active_support/testing/file_fixtures.rb +4 -0
- data/lib/active_support/testing/isolation.rb +6 -4
- data/lib/active_support/testing/method_call_assertions.rb +34 -5
- data/lib/active_support/testing/parallelization/server.rb +82 -0
- data/lib/active_support/testing/parallelization/worker.rb +103 -0
- data/lib/active_support/testing/parallelization.rb +55 -0
- data/lib/active_support/testing/parallelize_executor.rb +76 -0
- data/lib/active_support/testing/setup_and_teardown.rb +12 -7
- data/lib/active_support/testing/stream.rb +6 -7
- data/lib/active_support/testing/tagged_logging.rb +3 -1
- data/lib/active_support/testing/time_helpers.rb +91 -15
- data/lib/active_support/time.rb +2 -0
- data/lib/active_support/time_with_zone.rb +168 -56
- data/lib/active_support/values/time_zone.rb +85 -37
- data/lib/active_support/version.rb +3 -1
- data/lib/active_support/xml_mini/jdom.rb +6 -5
- data/lib/active_support/xml_mini/libxml.rb +9 -7
- data/lib/active_support/xml_mini/libxmlsax.rb +7 -5
- data/lib/active_support/xml_mini/nokogiri.rb +8 -6
- data/lib/active_support/xml_mini/nokogirisax.rb +6 -4
- data/lib/active_support/xml_mini/rexml.rb +13 -4
- data/lib/active_support/xml_mini.rb +10 -15
- data/lib/active_support.rb +30 -9
- metadata +76 -35
- data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
- data/lib/active_support/core_ext/hash/compact.rb +0 -27
- data/lib/active_support/core_ext/hash/transform_values.rb +0 -30
- data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
- data/lib/active_support/core_ext/marshal.rb +0 -22
- 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/values/unicode_tables.dat +0 -0
@@ -1,57 +1,103 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveSupport
|
4
|
+
module EnumerableCoreExt # :nodoc:
|
5
|
+
module Constants
|
6
|
+
private
|
7
|
+
def const_missing(name)
|
8
|
+
if name == :SoleItemExpectedError
|
9
|
+
::ActiveSupport::EnumerableCoreExt::SoleItemExpectedError
|
10
|
+
else
|
11
|
+
super
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
1
18
|
module Enumerable
|
2
|
-
#
|
19
|
+
# Error generated by +sole+ when called on an enumerable that doesn't have
|
20
|
+
# exactly one item.
|
21
|
+
class SoleItemExpectedError < StandardError; end
|
22
|
+
|
23
|
+
# HACK: For performance reasons, Enumerable shouldn't have any constants of its own.
|
24
|
+
# So we move SoleItemExpectedError into ActiveSupport::EnumerableCoreExt.
|
25
|
+
ActiveSupport::EnumerableCoreExt::SoleItemExpectedError = remove_const(:SoleItemExpectedError)
|
26
|
+
singleton_class.prepend(ActiveSupport::EnumerableCoreExt::Constants)
|
27
|
+
|
28
|
+
# Enumerable#sum was added in Ruby 2.4, but it only works with Numeric elements
|
3
29
|
# when we omit an identity.
|
30
|
+
|
31
|
+
# :stopdoc:
|
32
|
+
|
33
|
+
# We can't use Refinements here because Refinements with Module which will be prepended
|
34
|
+
# doesn't work well https://bugs.ruby-lang.org/issues/13446
|
35
|
+
alias :_original_sum_with_required_identity :sum
|
36
|
+
private :_original_sum_with_required_identity
|
37
|
+
|
38
|
+
# :startdoc:
|
39
|
+
|
40
|
+
# Calculates the minimum from the extracted elements.
|
4
41
|
#
|
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
|
-
|
42
|
+
# payments = [Payment.new(5), Payment.new(15), Payment.new(10)]
|
43
|
+
# payments.minimum(:price) # => 5
|
44
|
+
def minimum(key)
|
45
|
+
map(&key).min
|
46
|
+
end
|
47
|
+
|
48
|
+
# Calculates the maximum from the extracted elements.
|
49
|
+
#
|
50
|
+
# payments = [Payment.new(5), Payment.new(15), Payment.new(10)]
|
51
|
+
# payments.maximum(:price) # => 15
|
52
|
+
def maximum(key)
|
53
|
+
map(&key).max
|
54
|
+
end
|
55
|
+
|
56
|
+
# Calculates a sum from the elements.
|
57
|
+
#
|
58
|
+
# payments.sum { |p| p.price * p.tax_rate }
|
59
|
+
# payments.sum(&:price)
|
60
|
+
#
|
61
|
+
# The latter is a shortcut for:
|
62
|
+
#
|
63
|
+
# payments.inject(0) { |sum, p| sum + p.price }
|
64
|
+
#
|
65
|
+
# It can also calculate the sum without the use of a block.
|
66
|
+
#
|
67
|
+
# [5, 15, 10].sum # => 30
|
68
|
+
# ['foo', 'bar'].sum('') # => "foobar"
|
69
|
+
# [[1, 2], [3, 1, 5]].sum([]) # => [1, 2, 3, 1, 5]
|
70
|
+
#
|
71
|
+
# The default sum of an empty list is zero. You can override this default:
|
72
|
+
#
|
73
|
+
# [].sum(Payment.new(0)) { |i| i.amount } # => Payment.new(0)
|
74
|
+
def sum(identity = nil, &block)
|
75
|
+
if identity
|
76
|
+
_original_sum_with_required_identity(identity, &block)
|
77
|
+
elsif block_given?
|
78
|
+
map(&block).sum
|
79
|
+
# we check `first(1) == []` to check if we have an
|
80
|
+
# empty Enumerable; checking `empty?` would return
|
81
|
+
# true for `[nil]`, which we want to deprecate to
|
82
|
+
# keep consistent with Ruby
|
83
|
+
elsif first.is_a?(Numeric) || first(1) == []
|
84
|
+
identity ||= 0
|
85
|
+
_original_sum_with_required_identity(identity, &block)
|
86
|
+
else
|
87
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
88
|
+
Rails 7.0 has deprecated Enumerable.sum in favor of Ruby's native implementation available since 2.4.
|
89
|
+
Sum of non-numeric elements requires an initial argument.
|
90
|
+
MSG
|
91
|
+
inject(:+) || 0
|
48
92
|
end
|
49
93
|
end
|
50
94
|
|
51
|
-
# Convert an enumerable to a hash
|
95
|
+
# Convert an enumerable to a hash, using the block result as the key and the
|
96
|
+
# element as the value.
|
52
97
|
#
|
53
98
|
# people.index_by(&:login)
|
54
99
|
# # => { "nextangle" => <Person ...>, "chade-" => <Person ...>, ...}
|
100
|
+
#
|
55
101
|
# people.index_by { |person| "#{person.first_name} #{person.last_name}" }
|
56
102
|
# # => { "Chade- Fowlersburg-e" => <Person ...>, "David Heinemeier Hansson" => <Person ...>, ...}
|
57
103
|
def index_by
|
@@ -64,6 +110,33 @@ module Enumerable
|
|
64
110
|
end
|
65
111
|
end
|
66
112
|
|
113
|
+
# Convert an enumerable to a hash, using the element as the key and the block
|
114
|
+
# result as the value.
|
115
|
+
#
|
116
|
+
# post = Post.new(title: "hey there", body: "what's up?")
|
117
|
+
#
|
118
|
+
# %i( title body ).index_with { |attr_name| post.public_send(attr_name) }
|
119
|
+
# # => { title: "hey there", body: "what's up?" }
|
120
|
+
#
|
121
|
+
# If an argument is passed instead of a block, it will be used as the value
|
122
|
+
# for all elements:
|
123
|
+
#
|
124
|
+
# %i( created_at updated_at ).index_with(Time.now)
|
125
|
+
# # => { created_at: 2020-03-09 22:31:47, updated_at: 2020-03-09 22:31:47 }
|
126
|
+
def index_with(default = (no_default = true))
|
127
|
+
if block_given?
|
128
|
+
result = {}
|
129
|
+
each { |elem| result[elem] = yield(elem) }
|
130
|
+
result
|
131
|
+
elsif no_default
|
132
|
+
to_enum(:index_with) { size if respond_to?(:size) }
|
133
|
+
else
|
134
|
+
result = {}
|
135
|
+
each { |elem| result[elem] = default }
|
136
|
+
result
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
67
140
|
# Returns +true+ if the enumerable has more than 1 element. Functionally
|
68
141
|
# equivalent to <tt>enum.to_a.size > 1</tt>. Can be called with a block too,
|
69
142
|
# much like any?, so <tt>people.many? { |p| p.age > 26 }</tt> returns +true+
|
@@ -80,24 +153,40 @@ module Enumerable
|
|
80
153
|
end
|
81
154
|
end
|
82
155
|
|
156
|
+
# Returns a new array that includes the passed elements.
|
157
|
+
#
|
158
|
+
# [ 1, 2, 3 ].including(4, 5)
|
159
|
+
# # => [ 1, 2, 3, 4, 5 ]
|
160
|
+
#
|
161
|
+
# ["David", "Rafael"].including %w[ Aaron Todd ]
|
162
|
+
# # => ["David", "Rafael", "Aaron", "Todd"]
|
163
|
+
def including(*elements)
|
164
|
+
to_a.including(*elements)
|
165
|
+
end
|
166
|
+
|
83
167
|
# The negative of the <tt>Enumerable#include?</tt>. Returns +true+ if the
|
84
168
|
# collection does not include the object.
|
85
169
|
def exclude?(object)
|
86
170
|
!include?(object)
|
87
171
|
end
|
88
172
|
|
89
|
-
# Returns a copy of the enumerable
|
173
|
+
# Returns a copy of the enumerable excluding the specified elements.
|
174
|
+
#
|
175
|
+
# ["David", "Rafael", "Aaron", "Todd"].excluding "Aaron", "Todd"
|
176
|
+
# # => ["David", "Rafael"]
|
90
177
|
#
|
91
|
-
# ["David", "Rafael", "Aaron", "Todd"].
|
178
|
+
# ["David", "Rafael", "Aaron", "Todd"].excluding %w[ Aaron Todd ]
|
92
179
|
# # => ["David", "Rafael"]
|
93
180
|
#
|
94
|
-
# {foo: 1, bar: 2, baz: 3}.
|
181
|
+
# {foo: 1, bar: 2, baz: 3}.excluding :bar
|
95
182
|
# # => {foo: 1, baz: 3}
|
96
|
-
def
|
183
|
+
def excluding(*elements)
|
184
|
+
elements.flatten!(1)
|
97
185
|
reject { |element| elements.include?(element) }
|
98
186
|
end
|
187
|
+
alias :without :excluding
|
99
188
|
|
100
|
-
#
|
189
|
+
# Extract the given key from each element in the enumerable.
|
101
190
|
#
|
102
191
|
# [{ name: "David" }, { name: "Rafael" }, { name: "Aaron" }].pluck(:name)
|
103
192
|
# # => ["David", "Rafael", "Aaron"]
|
@@ -108,12 +197,91 @@ module Enumerable
|
|
108
197
|
if keys.many?
|
109
198
|
map { |element| keys.map { |key| element[key] } }
|
110
199
|
else
|
111
|
-
|
200
|
+
key = keys.first
|
201
|
+
map { |element| element[key] }
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
# Extract the given key from the first element in the enumerable.
|
206
|
+
#
|
207
|
+
# [{ name: "David" }, { name: "Rafael" }, { name: "Aaron" }].pick(:name)
|
208
|
+
# # => "David"
|
209
|
+
#
|
210
|
+
# [{ id: 1, name: "David" }, { id: 2, name: "Rafael" }].pick(:id, :name)
|
211
|
+
# # => [1, "David"]
|
212
|
+
def pick(*keys)
|
213
|
+
return if none?
|
214
|
+
|
215
|
+
if keys.many?
|
216
|
+
keys.map { |key| first[key] }
|
217
|
+
else
|
218
|
+
first[keys.first]
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
# Returns a new +Array+ without the blank items.
|
223
|
+
# Uses Object#blank? for determining if an item is blank.
|
224
|
+
#
|
225
|
+
# [1, "", nil, 2, " ", [], {}, false, true].compact_blank
|
226
|
+
# # => [1, 2, true]
|
227
|
+
#
|
228
|
+
# Set.new([nil, "", 1, 2])
|
229
|
+
# # => [2, 1] (or [1, 2])
|
230
|
+
#
|
231
|
+
# When called on a +Hash+, returns a new +Hash+ without the blank values.
|
232
|
+
#
|
233
|
+
# { a: "", b: 1, c: nil, d: [], e: false, f: true }.compact_blank
|
234
|
+
# # => { b: 1, f: true }
|
235
|
+
def compact_blank
|
236
|
+
reject(&:blank?)
|
237
|
+
end
|
238
|
+
|
239
|
+
# Returns a new +Array+ where the order has been set to that provided in the +series+, based on the +key+ of the
|
240
|
+
# objects in the original enumerable.
|
241
|
+
#
|
242
|
+
# [ Person.find(5), Person.find(3), Person.find(1) ].in_order_of(:id, [ 1, 5, 3 ])
|
243
|
+
# # => [ Person.find(1), Person.find(5), Person.find(3) ]
|
244
|
+
#
|
245
|
+
# If the +series+ include keys that have no corresponding element in the Enumerable, these are ignored.
|
246
|
+
# If the Enumerable has additional elements that aren't named in the +series+, these are not included in the result.
|
247
|
+
def in_order_of(key, series)
|
248
|
+
index_by(&key).values_at(*series).compact
|
249
|
+
end
|
250
|
+
|
251
|
+
# Returns the sole item in the enumerable. If there are no items, or more
|
252
|
+
# than one item, raises +Enumerable::SoleItemExpectedError+.
|
253
|
+
#
|
254
|
+
# ["x"].sole # => "x"
|
255
|
+
# Set.new.sole # => Enumerable::SoleItemExpectedError: no item found
|
256
|
+
# { a: 1, b: 2 }.sole # => Enumerable::SoleItemExpectedError: multiple items found
|
257
|
+
def sole
|
258
|
+
case count
|
259
|
+
when 1 then return first # rubocop:disable Style/RedundantReturn
|
260
|
+
when 0 then raise ActiveSupport::EnumerableCoreExt::SoleItemExpectedError, "no item found"
|
261
|
+
when 2.. then raise ActiveSupport::EnumerableCoreExt::SoleItemExpectedError, "multiple items found"
|
112
262
|
end
|
113
263
|
end
|
114
264
|
end
|
115
265
|
|
116
|
-
class
|
266
|
+
class Hash
|
267
|
+
# Hash#reject has its own definition, so this needs one too.
|
268
|
+
def compact_blank # :nodoc:
|
269
|
+
reject { |_k, v| v.blank? }
|
270
|
+
end
|
271
|
+
|
272
|
+
# Removes all blank values from the +Hash+ in place and returns self.
|
273
|
+
# Uses Object#blank? for determining if a value is blank.
|
274
|
+
#
|
275
|
+
# h = { a: "", b: 1, c: nil, d: [], e: false, f: true }
|
276
|
+
# h.compact_blank!
|
277
|
+
# # => { b: 1, f: true }
|
278
|
+
def compact_blank!
|
279
|
+
# use delete_if rather than reject! because it always returns self even if nothing changed
|
280
|
+
delete_if { |_k, v| v.blank? }
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
class Range # :nodoc:
|
117
285
|
# Optimize range sum to use arithmetic progression if a block is not given and
|
118
286
|
# we have a range of numeric values.
|
119
287
|
def sum(identity = nil)
|
@@ -131,27 +299,31 @@ class Range #:nodoc:
|
|
131
299
|
end
|
132
300
|
end
|
133
301
|
|
134
|
-
#
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
# Using Refinements here in order not to expose our internal method
|
141
|
-
using Module.new {
|
142
|
-
refine Array do
|
143
|
-
alias :orig_sum :sum
|
144
|
-
end
|
145
|
-
}
|
302
|
+
# Using Refinements here in order not to expose our internal method
|
303
|
+
using Module.new {
|
304
|
+
refine Array do
|
305
|
+
alias :orig_sum :sum
|
306
|
+
end
|
307
|
+
}
|
146
308
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
end
|
309
|
+
class Array # :nodoc:
|
310
|
+
def sum(init = nil, &block)
|
311
|
+
if init.is_a?(Numeric) || first.is_a?(Numeric)
|
312
|
+
init ||= 0
|
313
|
+
orig_sum(init, &block)
|
314
|
+
else
|
315
|
+
super
|
155
316
|
end
|
156
317
|
end
|
318
|
+
|
319
|
+
# Removes all blank elements from the +Array+ in place and returns self.
|
320
|
+
# Uses Object#blank? for determining if an item is blank.
|
321
|
+
#
|
322
|
+
# a = [1, "", nil, 2, " ", [], {}, false, true]
|
323
|
+
# a.compact_blank!
|
324
|
+
# # => [1, 2, true]
|
325
|
+
def compact_blank!
|
326
|
+
# use delete_if rather than reject! because it always returns self even if nothing changed
|
327
|
+
delete_if(&:blank?)
|
328
|
+
end
|
157
329
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "fileutils"
|
2
4
|
|
3
5
|
class File
|
@@ -27,7 +29,7 @@ class File
|
|
27
29
|
old_stat = if exist?(file_name)
|
28
30
|
# Get original file permissions
|
29
31
|
stat(file_name)
|
30
|
-
|
32
|
+
else
|
31
33
|
# If not possible, probe which are the default permissions in the
|
32
34
|
# destination directory.
|
33
35
|
probe_stat_in(dirname(file_name))
|
@@ -51,7 +53,7 @@ class File
|
|
51
53
|
end
|
52
54
|
|
53
55
|
# Private utility method.
|
54
|
-
def self.probe_stat_in(dir)
|
56
|
+
def self.probe_stat_in(dir) # :nodoc:
|
55
57
|
basename = [
|
56
58
|
".permissions_check",
|
57
59
|
Thread.current.object_id,
|
@@ -62,6 +64,8 @@ class File
|
|
62
64
|
file_name = join(dir, basename)
|
63
65
|
FileUtils.touch(file_name)
|
64
66
|
stat(file_name)
|
67
|
+
rescue Errno::ENOENT
|
68
|
+
file_name = nil
|
65
69
|
ensure
|
66
70
|
FileUtils.rm_f(file_name) if file_name
|
67
71
|
end
|
@@ -1,8 +1,9 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
3
|
require "active_support/core_ext/object/blank"
|
4
4
|
require "active_support/core_ext/object/to_param"
|
5
5
|
require "active_support/core_ext/object/to_query"
|
6
|
+
require "active_support/core_ext/object/try"
|
6
7
|
require "active_support/core_ext/array/wrap"
|
7
8
|
require "active_support/core_ext/hash/reverse_merge"
|
8
9
|
require "active_support/core_ext/string/inflections"
|
@@ -71,7 +72,7 @@ class Hash
|
|
71
72
|
# configure your own builder with the <tt>:builder</tt> option. The method also accepts
|
72
73
|
# options like <tt>:dasherize</tt> and friends, they are forwarded to the builder.
|
73
74
|
def to_xml(options = {})
|
74
|
-
require "active_support/builder" unless defined?(Builder)
|
75
|
+
require "active_support/builder" unless defined?(Builder::XmlMarkup)
|
75
76
|
|
76
77
|
options = options.dup
|
77
78
|
options[:indent] ||= 2
|
@@ -163,7 +164,7 @@ module ActiveSupport
|
|
163
164
|
Hash[params.map { |k, v| [k.to_s.tr("-", "_"), normalize_keys(v)] } ]
|
164
165
|
when Array
|
165
166
|
params.map { |v| normalize_keys(v) }
|
166
|
-
|
167
|
+
else
|
167
168
|
params
|
168
169
|
end
|
169
170
|
end
|
@@ -176,7 +177,7 @@ module ActiveSupport
|
|
176
177
|
process_array(value)
|
177
178
|
when String
|
178
179
|
value
|
179
|
-
|
180
|
+
else
|
180
181
|
raise "can't typecast #{value.class.name} - #{value.inspect}"
|
181
182
|
end
|
182
183
|
end
|
@@ -206,7 +207,7 @@ module ActiveSupport
|
|
206
207
|
elsif become_empty_string?(value)
|
207
208
|
""
|
208
209
|
elsif become_hash?(value)
|
209
|
-
xml_value =
|
210
|
+
xml_value = value.transform_values { |v| deep_to_h(v) }
|
210
211
|
|
211
212
|
# Turn { files: { file: #<StringIO> } } into { files: #<StringIO> } so it is compatible with
|
212
213
|
# how multipart uploaded files from HTML appear
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Hash
|
2
4
|
# Returns a new hash with +self+ and +other_hash+ merged recursively.
|
3
5
|
#
|
@@ -19,20 +21,14 @@ class Hash
|
|
19
21
|
|
20
22
|
# Same as +deep_merge+, but modifies +self+.
|
21
23
|
def deep_merge!(other_hash, &block)
|
22
|
-
other_hash
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
24
|
+
merge!(other_hash) do |key, this_val, other_val|
|
25
|
+
if this_val.is_a?(Hash) && other_val.is_a?(Hash)
|
26
|
+
this_val.deep_merge(other_val, &block)
|
27
|
+
elsif block_given?
|
28
|
+
block.call(key, this_val, other_val)
|
27
29
|
else
|
28
|
-
|
29
|
-
block.call(current_key, this_value, other_value)
|
30
|
-
else
|
31
|
-
other_value
|
32
|
-
end
|
30
|
+
other_val
|
33
31
|
end
|
34
32
|
end
|
35
|
-
|
36
|
-
self
|
37
33
|
end
|
38
34
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Hash
|
4
|
+
# Returns a new hash with all values converted by the block operation.
|
5
|
+
# This includes the values from the root hash and from all
|
6
|
+
# nested hashes and arrays.
|
7
|
+
#
|
8
|
+
# hash = { person: { name: 'Rob', age: '28' } }
|
9
|
+
#
|
10
|
+
# hash.deep_transform_values{ |value| value.to_s.upcase }
|
11
|
+
# # => {person: {name: "ROB", age: "28"}}
|
12
|
+
def deep_transform_values(&block)
|
13
|
+
_deep_transform_values_in_object(self, &block)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Destructively converts all values by using the block operation.
|
17
|
+
# This includes the values from the root hash and from all
|
18
|
+
# nested hashes and arrays.
|
19
|
+
def deep_transform_values!(&block)
|
20
|
+
_deep_transform_values_in_object!(self, &block)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
# Support methods for deep transforming nested hashes and arrays.
|
25
|
+
def _deep_transform_values_in_object(object, &block)
|
26
|
+
case object
|
27
|
+
when Hash
|
28
|
+
object.transform_values { |value| _deep_transform_values_in_object(value, &block) }
|
29
|
+
when Array
|
30
|
+
object.map { |e| _deep_transform_values_in_object(e, &block) }
|
31
|
+
else
|
32
|
+
yield(object)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def _deep_transform_values_in_object!(object, &block)
|
37
|
+
case object
|
38
|
+
when Hash
|
39
|
+
object.transform_values! { |value| _deep_transform_values_in_object!(value, &block) }
|
40
|
+
when Array
|
41
|
+
object.map! { |e| _deep_transform_values_in_object!(e, &block) }
|
42
|
+
else
|
43
|
+
yield(object)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Hash
|
2
4
|
# Returns a hash that includes everything except given keys.
|
3
5
|
# hash = { a: true, b: false, c: nil }
|
@@ -8,8 +10,8 @@ class Hash
|
|
8
10
|
# This is useful for limiting a set of parameters to everything but a few known toggles:
|
9
11
|
# @person.update(params[:person].except(:admin))
|
10
12
|
def except(*keys)
|
11
|
-
|
12
|
-
end
|
13
|
+
slice(*self.keys - keys)
|
14
|
+
end unless method_defined?(:except)
|
13
15
|
|
14
16
|
# Removes the given keys from hash and returns it.
|
15
17
|
# hash = { a: true, b: false, c: nil }
|
@@ -1,7 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/hash_with_indifferent_access"
|
2
4
|
|
3
5
|
class Hash
|
4
|
-
# Returns an
|
6
|
+
# Returns an ActiveSupport::HashWithIndifferentAccess out of its receiver:
|
5
7
|
#
|
6
8
|
# { a: 1 }.with_indifferent_access['a'] # => 1
|
7
9
|
def with_indifferent_access
|
@@ -11,8 +13,8 @@ class Hash
|
|
11
13
|
# Called when object is nested under an object that receives
|
12
14
|
# #with_indifferent_access. This method will be called on the current object
|
13
15
|
# by the enclosing object and is aliased to #with_indifferent_access by
|
14
|
-
# default. Subclasses of Hash may
|
15
|
-
# converting to an
|
16
|
+
# default. Subclasses of Hash may override this method to return +self+ if
|
17
|
+
# converting to an ActiveSupport::HashWithIndifferentAccess would not be
|
16
18
|
# desirable.
|
17
19
|
#
|
18
20
|
# b = { b: 1 }
|
@@ -1,33 +1,6 @@
|
|
1
|
-
|
2
|
-
# Returns a new hash with all keys converted using the +block+ operation.
|
3
|
-
#
|
4
|
-
# hash = { name: 'Rob', age: '28' }
|
5
|
-
#
|
6
|
-
# hash.transform_keys { |key| key.to_s.upcase } # => {"NAME"=>"Rob", "AGE"=>"28"}
|
7
|
-
#
|
8
|
-
# If you do not provide a +block+, it will return an Enumerator
|
9
|
-
# for chaining with other methods:
|
10
|
-
#
|
11
|
-
# hash.transform_keys.with_index { |k, i| [k, i].join } # => {"name0"=>"Rob", "age1"=>"28"}
|
12
|
-
def transform_keys
|
13
|
-
return enum_for(:transform_keys) { size } unless block_given?
|
14
|
-
result = {}
|
15
|
-
each_key do |key|
|
16
|
-
result[yield(key)] = self[key]
|
17
|
-
end
|
18
|
-
result
|
19
|
-
end unless method_defined? :transform_keys
|
20
|
-
|
21
|
-
# Destructively converts all keys using the +block+ operations.
|
22
|
-
# Same as +transform_keys+ but modifies +self+.
|
23
|
-
def transform_keys!
|
24
|
-
return enum_for(:transform_keys!) { size } unless block_given?
|
25
|
-
keys.each do |key|
|
26
|
-
self[yield(key)] = delete(key)
|
27
|
-
end
|
28
|
-
self
|
29
|
-
end unless method_defined? :transform_keys!
|
1
|
+
# frozen_string_literal: true
|
30
2
|
|
3
|
+
class Hash
|
31
4
|
# Returns a new hash with all keys converted to strings.
|
32
5
|
#
|
33
6
|
# hash = { name: 'Rob', age: '28' }
|
@@ -139,11 +112,11 @@ class Hash
|
|
139
112
|
end
|
140
113
|
|
141
114
|
private
|
142
|
-
#
|
115
|
+
# Support methods for deep transforming nested hashes and arrays.
|
143
116
|
def _deep_transform_keys_in_object(object, &block)
|
144
117
|
case object
|
145
118
|
when Hash
|
146
|
-
object.each_with_object(
|
119
|
+
object.each_with_object(self.class.new) do |(key, value), result|
|
147
120
|
result[yield(key)] = _deep_transform_keys_in_object(value, &block)
|
148
121
|
end
|
149
122
|
when Array
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Hash
|
2
4
|
# Merges the caller into +other_hash+. For example,
|
3
5
|
#
|
@@ -12,11 +14,12 @@ class Hash
|
|
12
14
|
def reverse_merge(other_hash)
|
13
15
|
other_hash.merge(self)
|
14
16
|
end
|
17
|
+
alias_method :with_defaults, :reverse_merge
|
15
18
|
|
16
19
|
# Destructive +reverse_merge+.
|
17
20
|
def reverse_merge!(other_hash)
|
18
|
-
|
19
|
-
merge!(other_hash) { |key, left, right| left }
|
21
|
+
replace(reverse_merge(other_hash))
|
20
22
|
end
|
21
23
|
alias_method :reverse_update, :reverse_merge!
|
24
|
+
alias_method :with_defaults!, :reverse_merge!
|
22
25
|
end
|