aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/lib
diff options
context:
space:
mode:
Diffstat (limited to 'activesupport/lib')
-rw-r--r--activesupport/lib/active_support.rb13
-rw-r--r--activesupport/lib/active_support/all.rb6
-rw-r--r--activesupport/lib/active_support/array_inquirer.rb2
-rw-r--r--activesupport/lib/active_support/backtrace_cleaner.rb2
-rw-r--r--activesupport/lib/active_support/benchmarkable.rb6
-rw-r--r--activesupport/lib/active_support/builder.rb2
-rw-r--r--activesupport/lib/active_support/cache.rb137
-rw-r--r--activesupport/lib/active_support/cache/file_store.rb10
-rw-r--r--activesupport/lib/active_support/cache/mem_cache_store.rb16
-rw-r--r--activesupport/lib/active_support/cache/memory_store.rb4
-rw-r--r--activesupport/lib/active_support/cache/null_store.rb2
-rw-r--r--activesupport/lib/active_support/cache/strategy/local_cache.rb23
-rw-r--r--activesupport/lib/active_support/cache/strategy/local_cache_middleware.rb10
-rw-r--r--activesupport/lib/active_support/callbacks.rb30
-rw-r--r--activesupport/lib/active_support/concern.rb2
-rw-r--r--activesupport/lib/active_support/concurrency/share_lock.rb2
-rw-r--r--activesupport/lib/active_support/configurable.rb10
-rw-r--r--activesupport/lib/active_support/core_ext.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/array.rb16
-rw-r--r--activesupport/lib/active_support/core_ext/array/access.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/array/conversions.rb14
-rw-r--r--activesupport/lib/active_support/core_ext/array/extract_options.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/array/grouping.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/array/inquiry.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/array/prepend_and_append.rb6
-rw-r--r--activesupport/lib/active_support/core_ext/array/wrap.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/benchmark.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/big_decimal.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/big_decimal/conversions.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/class.rb6
-rw-r--r--activesupport/lib/active_support/core_ext/class/attribute.rb21
-rw-r--r--activesupport/lib/active_support/core_ext/class/attribute_accessors.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/class/subclasses.rb6
-rw-r--r--activesupport/lib/active_support/core_ext/date.rb12
-rw-r--r--activesupport/lib/active_support/core_ext/date/acts_like.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/date/blank.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/date/calculations.rb12
-rw-r--r--activesupport/lib/active_support/core_ext/date/conversions.rb11
-rw-r--r--activesupport/lib/active_support/core_ext/date/zones.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/date_and_time/calculations.rb20
-rw-r--r--activesupport/lib/active_support/core_ext/date_and_time/compatibility.rb14
-rw-r--r--activesupport/lib/active_support/core_ext/date_and_time/zones.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/date_time.rb12
-rw-r--r--activesupport/lib/active_support/core_ext/date_time/acts_like.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/date_time/blank.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/date_time/calculations.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/date_time/compatibility.rb17
-rw-r--r--activesupport/lib/active_support/core_ext/date_time/conversions.rb10
-rw-r--r--activesupport/lib/active_support/core_ext/digest/uuid.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/enumerable.rb70
-rw-r--r--activesupport/lib/active_support/core_ext/file.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/file/atomic.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/hash.rb20
-rw-r--r--activesupport/lib/active_support/core_ext/hash/compact.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/hash/conversions.rb20
-rw-r--r--activesupport/lib/active_support/core_ext/hash/deep_merge.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/hash/except.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/hash/indifferent_access.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/hash/keys.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/hash/reverse_merge.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/hash/slice.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/hash/transform_values.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/integer.rb8
-rw-r--r--activesupport/lib/active_support/core_ext/integer/inflections.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/integer/multiple.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/integer/time.rb6
-rw-r--r--activesupport/lib/active_support/core_ext/kernel.rb10
-rw-r--r--activesupport/lib/active_support/core_ext/kernel/agnostics.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/kernel/concern.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/kernel/reporting.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/kernel/singleton_class.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/load_error.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/marshal.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/module.rb24
-rw-r--r--activesupport/lib/active_support/core_ext/module/aliasing.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/module/anonymous.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/module/attr_internal.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/module/attribute_accessors.rb49
-rw-r--r--activesupport/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb6
-rw-r--r--activesupport/lib/active_support/core_ext/module/concerning.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/module/delegation.rb50
-rw-r--r--activesupport/lib/active_support/core_ext/module/deprecation.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/module/introspection.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/module/reachable.rb6
-rw-r--r--activesupport/lib/active_support/core_ext/module/remove_method.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/name_error.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/numeric.rb10
-rw-r--r--activesupport/lib/active_support/core_ext/numeric/bytes.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/numeric/conversions.rb8
-rw-r--r--activesupport/lib/active_support/core_ext/numeric/inquiry.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/numeric/time.rb12
-rw-r--r--activesupport/lib/active_support/core_ext/object.rb26
-rw-r--r--activesupport/lib/active_support/core_ext/object/acts_like.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/object/blank.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/object/conversions.rb10
-rw-r--r--activesupport/lib/active_support/core_ext/object/deep_dup.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/object/duplicable.rb40
-rw-r--r--activesupport/lib/active_support/core_ext/object/inclusion.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/object/instance_variables.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/object/json.rb16
-rw-r--r--activesupport/lib/active_support/core_ext/object/to_param.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/object/to_query.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/object/try.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/object/with_options.rb15
-rw-r--r--activesupport/lib/active_support/core_ext/range.rb10
-rw-r--r--activesupport/lib/active_support/core_ext/range/conversions.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/range/each.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/range/include_range.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/range/overlaps.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/regexp.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/securerandom.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/string.rb28
-rw-r--r--activesupport/lib/active_support/core_ext/string/access.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/string/behavior.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/string/conversions.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/string/exclude.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/string/filters.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/string/indent.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/string/inflections.rb38
-rw-r--r--activesupport/lib/active_support/core_ext/string/inquiry.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/string/multibyte.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/string/output_safety.rb6
-rw-r--r--activesupport/lib/active_support/core_ext/string/starts_ends_with.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/string/strip.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/string/zones.rb6
-rw-r--r--activesupport/lib/active_support/core_ext/time.rb12
-rw-r--r--activesupport/lib/active_support/core_ext/time/acts_like.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/time/calculations.rb50
-rw-r--r--activesupport/lib/active_support/core_ext/time/compatibility.rb15
-rw-r--r--activesupport/lib/active_support/core_ext/time/conversions.rb6
-rw-r--r--activesupport/lib/active_support/core_ext/time/zones.rb8
-rw-r--r--activesupport/lib/active_support/core_ext/uri.rb2
-rw-r--r--activesupport/lib/active_support/current_attributes.rb195
-rw-r--r--activesupport/lib/active_support/dependencies.rb57
-rw-r--r--activesupport/lib/active_support/dependencies/autoload.rb4
-rw-r--r--activesupport/lib/active_support/dependencies/interlock.rb4
-rw-r--r--activesupport/lib/active_support/deprecation.rb19
-rw-r--r--activesupport/lib/active_support/deprecation/behaviors.rb35
-rw-r--r--activesupport/lib/active_support/deprecation/constant_accessor.rb52
-rw-r--r--activesupport/lib/active_support/deprecation/instance_delegator.rb6
-rw-r--r--activesupport/lib/active_support/deprecation/method_wrappers.rb6
-rw-r--r--activesupport/lib/active_support/deprecation/proxy_wrappers.rb6
-rw-r--r--activesupport/lib/active_support/deprecation/reporting.rb6
-rw-r--r--activesupport/lib/active_support/descendants_tracker.rb2
-rw-r--r--activesupport/lib/active_support/duration.rb137
-rw-r--r--activesupport/lib/active_support/duration/iso8601_parser.rb4
-rw-r--r--activesupport/lib/active_support/duration/iso8601_serializer.rb10
-rw-r--r--activesupport/lib/active_support/evented_file_update_checker.rb7
-rw-r--r--activesupport/lib/active_support/execution_wrapper.rb4
-rw-r--r--activesupport/lib/active_support/executor.rb4
-rw-r--r--activesupport/lib/active_support/file_update_checker.rb4
-rw-r--r--activesupport/lib/active_support/gem_version.rb6
-rw-r--r--activesupport/lib/active_support/gzip.rb2
-rw-r--r--activesupport/lib/active_support/hash_with_indifferent_access.rb21
-rw-r--r--activesupport/lib/active_support/i18n.rb12
-rw-r--r--activesupport/lib/active_support/i18n_railtie.rb14
-rw-r--r--activesupport/lib/active_support/inflections.rb4
-rw-r--r--activesupport/lib/active_support/inflector.rb12
-rw-r--r--activesupport/lib/active_support/inflector/inflections.rb8
-rw-r--r--activesupport/lib/active_support/inflector/methods.rb61
-rw-r--r--activesupport/lib/active_support/inflector/transliterate.rb13
-rw-r--r--activesupport/lib/active_support/json.rb6
-rw-r--r--activesupport/lib/active_support/json/decoding.rb6
-rw-r--r--activesupport/lib/active_support/json/encoding.rb6
-rw-r--r--activesupport/lib/active_support/key_generator.rb2
-rw-r--r--activesupport/lib/active_support/lazy_load_hooks.rb2
-rw-r--r--activesupport/lib/active_support/log_subscriber.rb17
-rw-r--r--activesupport/lib/active_support/log_subscriber/test_helper.rb8
-rw-r--r--activesupport/lib/active_support/logger.rb6
-rw-r--r--activesupport/lib/active_support/logger_silence.rb9
-rw-r--r--activesupport/lib/active_support/logger_thread_safe_level.rb4
-rw-r--r--activesupport/lib/active_support/message_encryptor.rb46
-rw-r--r--activesupport/lib/active_support/message_verifier.rb6
-rw-r--r--activesupport/lib/active_support/multibyte.rb2
-rw-r--r--activesupport/lib/active_support/multibyte/chars.rb12
-rw-r--r--activesupport/lib/active_support/multibyte/unicode.rb4
-rw-r--r--activesupport/lib/active_support/notifications.rb10
-rw-r--r--activesupport/lib/active_support/notifications/fanout.rb2
-rw-r--r--activesupport/lib/active_support/notifications/instrumenter.rb2
-rw-r--r--activesupport/lib/active_support/number_helper.rb3
-rw-r--r--activesupport/lib/active_support/number_helper/number_converter.rb12
-rw-r--r--activesupport/lib/active_support/number_helper/number_to_currency_converter.rb4
-rw-r--r--activesupport/lib/active_support/number_helper/number_to_delimited_converter.rb2
-rw-r--r--activesupport/lib/active_support/number_helper/number_to_human_converter.rb8
-rw-r--r--activesupport/lib/active_support/number_helper/number_to_human_size_converter.rb2
-rw-r--r--activesupport/lib/active_support/number_helper/number_to_percentage_converter.rb2
-rw-r--r--activesupport/lib/active_support/number_helper/number_to_phone_converter.rb4
-rw-r--r--activesupport/lib/active_support/number_helper/number_to_rounded_converter.rb34
-rw-r--r--activesupport/lib/active_support/number_helper/rounding_helper.rb66
-rw-r--r--activesupport/lib/active_support/option_merger.rb4
-rw-r--r--activesupport/lib/active_support/ordered_hash.rb2
-rw-r--r--activesupport/lib/active_support/ordered_options.rb4
-rw-r--r--activesupport/lib/active_support/per_thread_registry.rb4
-rw-r--r--activesupport/lib/active_support/proxy_object.rb2
-rw-r--r--activesupport/lib/active_support/rails.rb16
-rw-r--r--activesupport/lib/active_support/railtie.rb30
-rw-r--r--activesupport/lib/active_support/reloader.rb11
-rw-r--r--activesupport/lib/active_support/rescuable.rb21
-rw-r--r--activesupport/lib/active_support/security_utils.rb2
-rw-r--r--activesupport/lib/active_support/string_inquirer.rb2
-rw-r--r--activesupport/lib/active_support/subscriber.rb6
-rw-r--r--activesupport/lib/active_support/tagged_logging.rb8
-rw-r--r--activesupport/lib/active_support/test_case.rb22
-rw-r--r--activesupport/lib/active_support/testing/assertions.rb4
-rw-r--r--activesupport/lib/active_support/testing/autorun.rb6
-rw-r--r--activesupport/lib/active_support/testing/constant_lookup.rb6
-rw-r--r--activesupport/lib/active_support/testing/declarative.rb2
-rw-r--r--activesupport/lib/active_support/testing/deprecation.rb6
-rw-r--r--activesupport/lib/active_support/testing/file_fixtures.rb2
-rw-r--r--activesupport/lib/active_support/testing/isolation.rb2
-rw-r--r--activesupport/lib/active_support/testing/method_call_assertions.rb2
-rw-r--r--activesupport/lib/active_support/testing/setup_and_teardown.rb6
-rw-r--r--activesupport/lib/active_support/testing/stream.rb2
-rw-r--r--activesupport/lib/active_support/testing/tagged_logging.rb2
-rw-r--r--activesupport/lib/active_support/testing/time_helpers.rb27
-rw-r--r--activesupport/lib/active_support/time.rb16
-rw-r--r--activesupport/lib/active_support/time_with_zone.rb59
-rw-r--r--activesupport/lib/active_support/values/time_zone.rb28
-rw-r--r--activesupport/lib/active_support/version.rb2
-rw-r--r--activesupport/lib/active_support/xml_mini.rb10
-rw-r--r--activesupport/lib/active_support/xml_mini/jdom.rb4
-rw-r--r--activesupport/lib/active_support/xml_mini/libxml.rb10
-rw-r--r--activesupport/lib/active_support/xml_mini/libxmlsax.rb13
-rw-r--r--activesupport/lib/active_support/xml_mini/nokogiri.rb10
-rw-r--r--activesupport/lib/active_support/xml_mini/nokogirisax.rb10
-rw-r--r--activesupport/lib/active_support/xml_mini/rexml.rb8
226 files changed, 1865 insertions, 733 deletions
diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb
index 03e3ce821a..79b12f36b9 100644
--- a/activesupport/lib/active_support.rb
+++ b/activesupport/lib/active_support.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
#--
# Copyright (c) 2005-2017 David Heinemeier Hansson
#
@@ -22,16 +24,17 @@
#++
require "securerandom"
-require "active_support/dependencies/autoload"
-require "active_support/version"
-require "active_support/logger"
-require "active_support/lazy_load_hooks"
-require "active_support/core_ext/date_and_time/compatibility"
+require_relative "active_support/dependencies/autoload"
+require_relative "active_support/version"
+require_relative "active_support/logger"
+require_relative "active_support/lazy_load_hooks"
+require_relative "active_support/core_ext/date_and_time/compatibility"
module ActiveSupport
extend ActiveSupport::Autoload
autoload :Concern
+ autoload :CurrentAttributes
autoload :Dependencies
autoload :DescendantsTracker
autoload :ExecutionWrapper
diff --git a/activesupport/lib/active_support/all.rb b/activesupport/lib/active_support/all.rb
index 72a23075af..6638b25419 100644
--- a/activesupport/lib/active_support/all.rb
+++ b/activesupport/lib/active_support/all.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support"
-require "active_support/time"
-require "active_support/core_ext"
+require_relative "time"
+require_relative "core_ext"
diff --git a/activesupport/lib/active_support/array_inquirer.rb b/activesupport/lib/active_support/array_inquirer.rb
index befa1746c6..b2b9e9c0b7 100644
--- a/activesupport/lib/active_support/array_inquirer.rb
+++ b/activesupport/lib/active_support/array_inquirer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActiveSupport
# Wrapping an array in an +ArrayInquirer+ gives a friendlier way to check
# its string-like contents:
diff --git a/activesupport/lib/active_support/backtrace_cleaner.rb b/activesupport/lib/active_support/backtrace_cleaner.rb
index e47c90597f..16dd733ddb 100644
--- a/activesupport/lib/active_support/backtrace_cleaner.rb
+++ b/activesupport/lib/active_support/backtrace_cleaner.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActiveSupport
# Backtraces often include many lines that are not relevant for the context
# under review. This makes it hard to find the signal amongst the backtrace
diff --git a/activesupport/lib/active_support/benchmarkable.rb b/activesupport/lib/active_support/benchmarkable.rb
index 70493c8da7..5573f6750e 100644
--- a/activesupport/lib/active_support/benchmarkable.rb
+++ b/activesupport/lib/active_support/benchmarkable.rb
@@ -1,5 +1,7 @@
-require "active_support/core_ext/benchmark"
-require "active_support/core_ext/hash/keys"
+# frozen_string_literal: true
+
+require_relative "core_ext/benchmark"
+require_relative "core_ext/hash/keys"
module ActiveSupport
module Benchmarkable
diff --git a/activesupport/lib/active_support/builder.rb b/activesupport/lib/active_support/builder.rb
index 0f010c5d96..3fa7e6b26d 100644
--- a/activesupport/lib/active_support/builder.rb
+++ b/activesupport/lib/active_support/builder.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
begin
require "builder"
rescue LoadError => e
diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb
index 4d8c2046e8..49d8965cb1 100644
--- a/activesupport/lib/active_support/cache.rb
+++ b/activesupport/lib/active_support/cache.rb
@@ -1,11 +1,13 @@
+# frozen_string_literal: true
+
require "zlib"
-require "active_support/core_ext/array/extract_options"
-require "active_support/core_ext/array/wrap"
-require "active_support/core_ext/module/attribute_accessors"
-require "active_support/core_ext/numeric/bytes"
-require "active_support/core_ext/numeric/time"
-require "active_support/core_ext/object/to_param"
-require "active_support/core_ext/string/inflections"
+require_relative "core_ext/array/extract_options"
+require_relative "core_ext/array/wrap"
+require_relative "core_ext/module/attribute_accessors"
+require_relative "core_ext/numeric/bytes"
+require_relative "core_ext/numeric/time"
+require_relative "core_ext/object/to_param"
+require_relative "core_ext/string/inflections"
module ActiveSupport
# See ActiveSupport::Cache::Store for documentation.
@@ -75,7 +77,7 @@ module ActiveSupport
#
# The +key+ argument can also respond to +cache_key+ or +to_param+.
def expand_cache_key(key, namespace = nil)
- expanded_cache_key = namespace ? "#{namespace}/" : ""
+ expanded_cache_key = (namespace ? "#{namespace}/" : "").dup
if prefix = ENV["RAILS_CACHE_ID"] || ENV["RAILS_APP_VERSION"]
expanded_cache_key << "#{prefix}/"
@@ -88,16 +90,19 @@ module ActiveSupport
private
def retrieve_cache_key(key)
case
- when key.respond_to?(:cache_key) then key.cache_key
- when key.is_a?(Array) then key.map { |element| retrieve_cache_key(element) }.to_param
- when key.respond_to?(:to_a) then retrieve_cache_key(key.to_a)
- else key.to_param
+ when key.respond_to?(:cache_key_with_version) then key.cache_key_with_version
+ when key.respond_to?(:cache_key) then key.cache_key
+ when key.is_a?(Array) then key.map { |element| retrieve_cache_key(element) }.to_param
+ when key.respond_to?(:to_a) then retrieve_cache_key(key.to_a)
+ else key.to_param
end.to_s
end
# Obtains the specified cache store class, given the name of the +store+.
# Raises an error when the store class cannot be found.
def retrieve_store_class(store)
+ # require_relative cannot be used here because the class might be
+ # provided by another gem, like redis-activesupport for example.
require "active_support/cache/#{store}"
rescue LoadError => e
raise "Could not find cache store adapter for #{store} (#{e})"
@@ -219,6 +224,10 @@ module ActiveSupport
# cache = ActiveSupport::Cache::MemoryStore.new(expires_in: 5.minutes)
# cache.write(key, value, expires_in: 1.minute) # Set a lower value for one entry
#
+ # Setting <tt>:version</tt> verifies the cache stored under <tt>name</tt>
+ # is of the same version. nil is returned on mismatches despite contents.
+ # This feature is used to support recyclable cache keys.
+ #
# Setting <tt>:race_condition_ttl</tt> is very useful in situations where
# a cache entry is used very frequently and is under heavy load. If a
# cache expires and due to heavy load several different processes will try
@@ -287,6 +296,7 @@ module ActiveSupport
instrument(:read, name, options) do |payload|
cached_entry = read_entry(key, options) unless options[:force]
entry = handle_expired_entry(cached_entry, key, options)
+ entry = nil if entry && entry.mismatched?(normalize_version(name, options))
payload[:super_operation] = :fetch if payload
payload[:hit] = !!entry if payload
end
@@ -303,21 +313,30 @@ module ActiveSupport
end
end
- # Fetches data from the cache, using the given key. If there is data in
+ # Reads data from the cache, using the given key. If there is data in
# the cache with the given key, then that data is returned. Otherwise,
# +nil+ is returned.
#
+ # Note, if data was written with the <tt>:expires_in<tt> or <tt>:version</tt> options,
+ # both of these conditions are applied before the data is returned.
+ #
# Options are passed to the underlying cache implementation.
def read(name, options = nil)
options = merged_options(options)
- key = normalize_key(name, options)
+ key = normalize_key(name, options)
+ version = normalize_version(name, options)
+
instrument(:read, name, options) do |payload|
entry = read_entry(key, options)
+
if entry
if entry.expired?
delete_entry(key, options)
payload[:hit] = false if payload
nil
+ elsif entry.mismatched?(version)
+ payload[:hit] = false if payload
+ nil
else
payload[:hit] = true if payload
entry.value
@@ -341,11 +360,15 @@ module ActiveSupport
results = {}
names.each do |name|
- key = normalize_key(name, options)
- entry = read_entry(key, options)
+ key = normalize_key(name, options)
+ version = normalize_version(name, options)
+ entry = read_entry(key, options)
+
if entry
if entry.expired?
delete_entry(key, options)
+ elsif entry.mismatched?(version)
+ # Skip mismatched versions
else
results[name] = entry.value
end
@@ -354,6 +377,19 @@ module ActiveSupport
results
end
+ # Cache Storage API to write multiple values at once.
+ def write_multi(hash, options = nil)
+ options = merged_options(options)
+
+ instrument :write_multi, hash, options do |payload|
+ entries = hash.each_with_object({}) do |(name, value), memo|
+ memo[normalize_key(name, options)] = Entry.new(value, options.merge(version: normalize_version(name, options)))
+ end
+
+ write_multi_entries entries, options
+ end
+ end
+
# Fetches data from the cache, using the given keys. If there is data in
# the cache with the given keys, then that data is returned. Otherwise,
# the supplied block is called for each key for which there was no data,
@@ -378,14 +414,15 @@ module ActiveSupport
options = names.extract_options!
options = merged_options(options)
- results = read_multi(*names, options)
- names.each_with_object({}) do |name, memo|
- memo[name] = results.fetch(name) do
- value = yield name
- write(name, value, options)
- value
+ read_multi(*names, options).tap do |results|
+ writes = {}
+
+ (names - results.keys).each do |name|
+ results[name] = writes[name] = yield(name)
end
+
+ write_multi writes, options
end
end
@@ -396,7 +433,7 @@ module ActiveSupport
options = merged_options(options)
instrument(:write, name, options) do
- entry = Entry.new(value, options)
+ entry = Entry.new(value, options.merge(version: normalize_version(name, options)))
write_entry(normalize_key(name, options), entry, options)
end
end
@@ -420,7 +457,7 @@ module ActiveSupport
instrument(:exist?, name) do
entry = read_entry(normalize_key(name, options), options)
- (entry && !entry.expired?) || false
+ (entry && !entry.expired? && !entry.mismatched?(normalize_version(name, options))) || false
end
end
@@ -466,7 +503,7 @@ module ActiveSupport
# The options hash is passed to the underlying cache implementation.
#
# All implementations may not support this method.
- def clear
+ def clear(options = nil)
raise NotImplementedError.new("#{self.class.name} does not support clear")
end
@@ -502,6 +539,14 @@ module ActiveSupport
raise NotImplementedError.new
end
+ # Writes multiple entries to the cache implementation. Subclasses MAY
+ # implement this method.
+ def write_multi_entries(hash, options)
+ hash.each do |key, entry|
+ write_entry key, entry, options
+ end
+ end
+
# Deletes an entry from the cache implementation. Subclasses must
# implement this method.
def delete_entry(key, options)
@@ -517,6 +562,16 @@ module ActiveSupport
end
end
+ # Prefixes a key with the namespace. Namespace and key will be delimited
+ # with a colon.
+ def normalize_key(key, options)
+ key = expanded_key(key)
+ namespace = options[:namespace] if options
+ prefix = namespace.is_a?(Proc) ? namespace.call : namespace
+ key = "#{prefix}:#{key}" if prefix
+ key
+ end
+
# Expands key to be a consistent string value. Invokes +cache_key+ if
# object responds to +cache_key+. Otherwise, +to_param+ method will be
# called. If the key is a Hash, then keys will be sorted alphabetically.
@@ -537,14 +592,16 @@ module ActiveSupport
key.to_param
end
- # Prefixes a key with the namespace. Namespace and key will be delimited
- # with a colon.
- def normalize_key(key, options)
- key = expanded_key(key)
- namespace = options[:namespace] if options
- prefix = namespace.is_a?(Proc) ? namespace.call : namespace
- key = "#{prefix}:#{key}" if prefix
- key
+ def normalize_version(key, options = nil)
+ (options && options[:version].try(:to_param)) || expanded_version(key)
+ end
+
+ def expanded_version(key)
+ case
+ when key.respond_to?(:cache_version) then key.cache_version.to_param
+ when key.is_a?(Array) then key.map { |element| expanded_version(element) }.compact.to_param
+ when key.respond_to?(:to_a) then expanded_version(key.to_a)
+ end
end
def instrument(operation, key, options = nil)
@@ -591,13 +648,16 @@ module ActiveSupport
end
end
- # This class is used to represent cache entries. Cache entries have a value and an optional
- # expiration time. The expiration time is used to support the :race_condition_ttl option
- # on the cache.
+ # This class is used to represent cache entries. Cache entries have a value, an optional
+ # expiration time, and an optional version. The expiration time is used to support the :race_condition_ttl option
+ # on the cache. The version is used to support the :version option on the cache for rejecting
+ # mismatches.
#
# Since cache entries in most instances will be serialized, the internals of this class are highly optimized
# using short instance variable names that are lazily defined.
class Entry # :nodoc:
+ attr_reader :version
+
DEFAULT_COMPRESS_LIMIT = 16.kilobytes
# Creates a new cache entry for the specified value. Options supported are
@@ -610,6 +670,7 @@ module ActiveSupport
@value = value
end
+ @version = options[:version]
@created_at = Time.now.to_f
@expires_in = options[:expires_in]
@expires_in = @expires_in.to_f if @expires_in
@@ -619,6 +680,10 @@ module ActiveSupport
compressed? ? uncompress(@value) : @value
end
+ def mismatched?(version)
+ @version && version && @version != version
+ end
+
# Checks if the entry is expired. The +expires_in+ parameter can override
# the value set when the entry was created.
def expired?
diff --git a/activesupport/lib/active_support/cache/file_store.rb b/activesupport/lib/active_support/cache/file_store.rb
index d5c8585816..28df2c066e 100644
--- a/activesupport/lib/active_support/cache/file_store.rb
+++ b/activesupport/lib/active_support/cache/file_store.rb
@@ -1,6 +1,8 @@
-require "active_support/core_ext/marshal"
-require "active_support/core_ext/file/atomic"
-require "active_support/core_ext/string/conversions"
+# frozen_string_literal: true
+
+require_relative "../core_ext/marshal"
+require_relative "../core_ext/file/atomic"
+require_relative "../core_ext/string/conversions"
require "uri/common"
module ActiveSupport
@@ -27,7 +29,7 @@ module ActiveSupport
# Deletes all items from the cache. In this case it deletes all the entries in the specified
# file store directory except for .keep or .gitkeep. Be careful which directory is specified in your
# config file when using +FileStore+ because everything in that directory will be deleted.
- def clear
+ def clear(options = nil)
root_dirs = exclude_from(cache_path, EXCLUDED_DIRS + GITKEEP_FILES)
FileUtils.rm_r(root_dirs.collect { |f| File.join(cache_path, f) })
rescue Errno::ENOENT
diff --git a/activesupport/lib/active_support/cache/mem_cache_store.rb b/activesupport/lib/active_support/cache/mem_cache_store.rb
index 5eee04a34e..73924aaaf9 100644
--- a/activesupport/lib/active_support/cache/mem_cache_store.rb
+++ b/activesupport/lib/active_support/cache/mem_cache_store.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
begin
require "dalli"
rescue LoadError => e
@@ -6,8 +8,8 @@ rescue LoadError => e
end
require "digest/md5"
-require "active_support/core_ext/marshal"
-require "active_support/core_ext/array/extract_options"
+require_relative "../core_ext/marshal"
+require_relative "../core_ext/array/extract_options"
module ActiveSupport
module Cache
@@ -97,12 +99,18 @@ module ActiveSupport
options = merged_options(options)
keys_to_names = Hash[names.map { |name| [normalize_key(name, options), name] }]
+
raw_values = @data.get_multi(keys_to_names.keys)
values = {}
+
raw_values.each do |key, value|
entry = deserialize_entry(value)
- values[keys_to_names[key]] = entry.value unless entry.expired?
+
+ unless entry.expired? || entry.mismatched?(normalize_version(keys_to_names[key], options))
+ values[keys_to_names[key]] = entry.value
+ end
end
+
values
end
@@ -156,7 +164,7 @@ module ActiveSupport
expires_in = options[:expires_in].to_i
if expires_in > 0 && !options[:raw]
# Set the memcache expire a few minutes in the future to support race condition ttls on read
- expires_in += 300
+ expires_in += 5.minutes
end
rescue_error_with false do
@data.send(method, key, value, expires_in, options)
diff --git a/activesupport/lib/active_support/cache/memory_store.rb b/activesupport/lib/active_support/cache/memory_store.rb
index fea072d91c..564ac17241 100644
--- a/activesupport/lib/active_support/cache/memory_store.rb
+++ b/activesupport/lib/active_support/cache/memory_store.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "monitor"
module ActiveSupport
@@ -28,6 +30,7 @@ module ActiveSupport
@pruning = false
end
+ # Delete all data stored in a given cache store.
def clear(options = nil)
synchronize do
@data.clear
@@ -83,6 +86,7 @@ module ActiveSupport
modify_value(name, -amount, options)
end
+ # Deletes cache entries if the cache key matches a given pattern.
def delete_matched(matcher, options = nil)
options = merged_options(options)
instrument(:delete_matched, matcher.inspect) do
diff --git a/activesupport/lib/active_support/cache/null_store.rb b/activesupport/lib/active_support/cache/null_store.rb
index 550659fc56..1a5983db43 100644
--- a/activesupport/lib/active_support/cache/null_store.rb
+++ b/activesupport/lib/active_support/cache/null_store.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActiveSupport
module Cache
# A cache store implementation which doesn't actually store anything. Useful in
diff --git a/activesupport/lib/active_support/cache/strategy/local_cache.rb b/activesupport/lib/active_support/cache/strategy/local_cache.rb
index 672eb2bb80..a3eef1190a 100644
--- a/activesupport/lib/active_support/cache/strategy/local_cache.rb
+++ b/activesupport/lib/active_support/cache/strategy/local_cache.rb
@@ -1,6 +1,8 @@
-require "active_support/core_ext/object/duplicable"
-require "active_support/core_ext/string/inflections"
-require "active_support/per_thread_registry"
+# frozen_string_literal: true
+
+require_relative "../../core_ext/object/duplicable"
+require_relative "../../core_ext/string/inflections"
+require_relative "../../per_thread_registry"
module ActiveSupport
module Cache
@@ -44,7 +46,7 @@ module ActiveSupport
yield
end
- def clear
+ def clear(options = nil)
@data.clear
end
@@ -79,15 +81,15 @@ module ActiveSupport
local_cache_key)
end
- def clear # :nodoc:
+ def clear(options = nil) # :nodoc:
return super unless cache = local_cache
- cache.clear
+ cache.clear(options)
super
end
def cleanup(options = nil) # :nodoc:
return super unless cache = local_cache
- cache.clear(options)
+ cache.clear
super
end
@@ -115,7 +117,12 @@ module ActiveSupport
end
def write_entry(key, entry, options)
- local_cache.write_entry(key, entry, options) if local_cache
+ if options[:unless_exist]
+ local_cache.delete_entry(key, options) if local_cache
+ else
+ local_cache.write_entry(key, entry, options) if local_cache
+ end
+
super
end
diff --git a/activesupport/lib/active_support/cache/strategy/local_cache_middleware.rb b/activesupport/lib/active_support/cache/strategy/local_cache_middleware.rb
index 174cb72b1e..62542bdb22 100644
--- a/activesupport/lib/active_support/cache/strategy/local_cache_middleware.rb
+++ b/activesupport/lib/active_support/cache/strategy/local_cache_middleware.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rack/body_proxy"
require "rack/utils"
@@ -28,13 +30,13 @@ module ActiveSupport
response[2] = ::Rack::BodyProxy.new(response[2]) do
LocalCacheRegistry.set_cache_for(local_cache_key, nil)
end
+ cleanup_on_body_close = true
response
rescue Rack::Utils::InvalidParameterError
- LocalCacheRegistry.set_cache_for(local_cache_key, nil)
[400, {}, []]
- rescue Exception
- LocalCacheRegistry.set_cache_for(local_cache_key, nil)
- raise
+ ensure
+ LocalCacheRegistry.set_cache_for(local_cache_key, nil) unless
+ cleanup_on_body_close
end
end
end
diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb
index ea71569ca8..e1cbfc945c 100644
--- a/activesupport/lib/active_support/callbacks.rb
+++ b/activesupport/lib/active_support/callbacks.rb
@@ -1,11 +1,13 @@
-require "active_support/concern"
-require "active_support/descendants_tracker"
-require "active_support/core_ext/array/extract_options"
-require "active_support/core_ext/class/attribute"
-require "active_support/core_ext/kernel/reporting"
-require "active_support/core_ext/kernel/singleton_class"
-require "active_support/core_ext/string/filters"
-require "active_support/deprecation"
+# frozen_string_literal: true
+
+require_relative "concern"
+require_relative "descendants_tracker"
+require_relative "core_ext/array/extract_options"
+require_relative "core_ext/class/attribute"
+require_relative "core_ext/kernel/reporting"
+require_relative "core_ext/kernel/singleton_class"
+require_relative "core_ext/string/filters"
+require_relative "deprecation"
require "thread"
module ActiveSupport
@@ -62,8 +64,7 @@ module ActiveSupport
included do
extend ActiveSupport::DescendantsTracker
- class_attribute :__callbacks, instance_writer: false
- self.__callbacks ||= {}
+ class_attribute :__callbacks, instance_writer: false, default: {}
end
CALLBACK_FILTER_TYPES = [:before, :after, :around]
@@ -512,7 +513,6 @@ module ActiveSupport
end
end
- # An Array with a compile method.
class CallbackChain #:nodoc:#
include Enumerable
@@ -598,7 +598,7 @@ module ActiveSupport
Proc.new do |target, result_lambda|
terminate = true
catch(:abort) do
- result_lambda.call if result_lambda.is_a?(Proc)
+ result_lambda.call
terminate = false
end
terminate
@@ -664,8 +664,10 @@ module ActiveSupport
if options[:if].is_a?(String) || options[:unless].is_a?(String)
ActiveSupport::Deprecation.warn(<<-MSG.squish)
- Passing string to :if and :unless conditional options is deprecated
- and will be removed in Rails 5.2 without replacement.
+ Passing string to be evaluated in :if and :unless conditional
+ options is deprecated and will be removed in Rails 5.2 without
+ replacement. Pass a symbol for an instance method, or a lambda,
+ proc or block, instead.
MSG
end
diff --git a/activesupport/lib/active_support/concern.rb b/activesupport/lib/active_support/concern.rb
index 0403eb70ca..32b5ca986b 100644
--- a/activesupport/lib/active_support/concern.rb
+++ b/activesupport/lib/active_support/concern.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActiveSupport
# A typical module looks like this:
#
diff --git a/activesupport/lib/active_support/concurrency/share_lock.rb b/activesupport/lib/active_support/concurrency/share_lock.rb
index 4318523b07..f18ccf1c88 100644
--- a/activesupport/lib/active_support/concurrency/share_lock.rb
+++ b/activesupport/lib/active_support/concurrency/share_lock.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "thread"
require "monitor"
diff --git a/activesupport/lib/active_support/configurable.rb b/activesupport/lib/active_support/configurable.rb
index f72a893bcc..8e8e27b4ec 100644
--- a/activesupport/lib/active_support/configurable.rb
+++ b/activesupport/lib/active_support/configurable.rb
@@ -1,7 +1,9 @@
-require "active_support/concern"
-require "active_support/ordered_options"
-require "active_support/core_ext/array/extract_options"
-require "active_support/core_ext/regexp"
+# frozen_string_literal: true
+
+require_relative "concern"
+require_relative "ordered_options"
+require_relative "core_ext/array/extract_options"
+require_relative "core_ext/regexp"
module ActiveSupport
# Configurable provides a <tt>config</tt> method to store and retrieve
diff --git a/activesupport/lib/active_support/core_ext.rb b/activesupport/lib/active_support/core_ext.rb
index f397f658f3..f590605d84 100644
--- a/activesupport/lib/active_support/core_ext.rb
+++ b/activesupport/lib/active_support/core_ext.rb
@@ -1,3 +1,5 @@
-(Dir["#{File.dirname(__FILE__)}/core_ext/*.rb"]).each do |path|
+# frozen_string_literal: true
+
+Dir.glob(File.expand_path("core_ext/*.rb", __dir__)).each do |path|
require path
end
diff --git a/activesupport/lib/active_support/core_ext/array.rb b/activesupport/lib/active_support/core_ext/array.rb
index e908386a1c..fdc209ef68 100644
--- a/activesupport/lib/active_support/core_ext/array.rb
+++ b/activesupport/lib/active_support/core_ext/array.rb
@@ -1,7 +1,9 @@
-require "active_support/core_ext/array/wrap"
-require "active_support/core_ext/array/access"
-require "active_support/core_ext/array/conversions"
-require "active_support/core_ext/array/extract_options"
-require "active_support/core_ext/array/grouping"
-require "active_support/core_ext/array/prepend_and_append"
-require "active_support/core_ext/array/inquiry"
+# frozen_string_literal: true
+
+require_relative "array/wrap"
+require_relative "array/access"
+require_relative "array/conversions"
+require_relative "array/extract_options"
+require_relative "array/grouping"
+require_relative "array/prepend_and_append"
+require_relative "array/inquiry"
diff --git a/activesupport/lib/active_support/core_ext/array/access.rb b/activesupport/lib/active_support/core_ext/array/access.rb
index fca33c9d69..d67f99df0e 100644
--- a/activesupport/lib/active_support/core_ext/array/access.rb
+++ b/activesupport/lib/active_support/core_ext/array/access.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Array
# Returns the tail of the array from +position+.
#
diff --git a/activesupport/lib/active_support/core_ext/array/conversions.rb b/activesupport/lib/active_support/core_ext/array/conversions.rb
index cac15e1100..6e17a81f0f 100644
--- a/activesupport/lib/active_support/core_ext/array/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/array/conversions.rb
@@ -1,8 +1,10 @@
-require "active_support/xml_mini"
-require "active_support/core_ext/hash/keys"
-require "active_support/core_ext/string/inflections"
-require "active_support/core_ext/object/to_param"
-require "active_support/core_ext/object/to_query"
+# frozen_string_literal: true
+
+require_relative "../../xml_mini"
+require_relative "../hash/keys"
+require_relative "../string/inflections"
+require_relative "../object/to_param"
+require_relative "../object/to_query"
class Array
# Converts the array to a comma-separated sentence where the last element is
@@ -179,7 +181,7 @@ class Array
# </messages>
#
def to_xml(options = {})
- require "active_support/builder" unless defined?(Builder)
+ require_relative "../../builder" unless defined?(Builder)
options = options.dup
options[:indent] ||= 2
diff --git a/activesupport/lib/active_support/core_ext/array/extract_options.rb b/activesupport/lib/active_support/core_ext/array/extract_options.rb
index 9008a0df2a..8c7cb2e780 100644
--- a/activesupport/lib/active_support/core_ext/array/extract_options.rb
+++ b/activesupport/lib/active_support/core_ext/array/extract_options.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Hash
# By default, only instances of Hash itself are extractable.
# Subclasses of Hash may implement this method and return
diff --git a/activesupport/lib/active_support/core_ext/array/grouping.rb b/activesupport/lib/active_support/core_ext/array/grouping.rb
index 0d798e5c4e..67e760bc4b 100644
--- a/activesupport/lib/active_support/core_ext/array/grouping.rb
+++ b/activesupport/lib/active_support/core_ext/array/grouping.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Array
# Splits or iterates over the array in groups of size +number+,
# padding any remaining slots with +fill_with+ unless it is +false+.
diff --git a/activesupport/lib/active_support/core_ext/array/inquiry.rb b/activesupport/lib/active_support/core_ext/array/inquiry.rb
index 66fa5fcd0c..4f4a9fa361 100644
--- a/activesupport/lib/active_support/core_ext/array/inquiry.rb
+++ b/activesupport/lib/active_support/core_ext/array/inquiry.rb
@@ -1,4 +1,6 @@
-require "active_support/array_inquirer"
+# frozen_string_literal: true
+
+require_relative "../../array_inquirer"
class Array
# Wraps the array in an +ArrayInquirer+ object, which gives a friendlier way
diff --git a/activesupport/lib/active_support/core_ext/array/prepend_and_append.rb b/activesupport/lib/active_support/core_ext/array/prepend_and_append.rb
index 16a6789f8d..661971d7cd 100644
--- a/activesupport/lib/active_support/core_ext/array/prepend_and_append.rb
+++ b/activesupport/lib/active_support/core_ext/array/prepend_and_append.rb
@@ -1,7 +1,9 @@
+# frozen_string_literal: true
+
class Array
# The human way of thinking about adding stuff to the end of a list is with append.
- alias_method :append, :<<
+ alias_method :append, :push unless [].respond_to?(:append)
# The human way of thinking about adding stuff to the beginning of a list is with prepend.
- alias_method :prepend, :unshift
+ alias_method :prepend, :unshift unless [].respond_to?(:prepend)
end
diff --git a/activesupport/lib/active_support/core_ext/array/wrap.rb b/activesupport/lib/active_support/core_ext/array/wrap.rb
index b611d34c27..d62f97edbf 100644
--- a/activesupport/lib/active_support/core_ext/array/wrap.rb
+++ b/activesupport/lib/active_support/core_ext/array/wrap.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Array
# Wraps its argument in an array unless it is already an array (or array-like).
#
diff --git a/activesupport/lib/active_support/core_ext/benchmark.rb b/activesupport/lib/active_support/core_ext/benchmark.rb
index 2300953860..641b58c8b8 100644
--- a/activesupport/lib/active_support/core_ext/benchmark.rb
+++ b/activesupport/lib/active_support/core_ext/benchmark.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "benchmark"
class << Benchmark
diff --git a/activesupport/lib/active_support/core_ext/big_decimal.rb b/activesupport/lib/active_support/core_ext/big_decimal.rb
index 7b4f87f10e..5568db689b 100644
--- a/activesupport/lib/active_support/core_ext/big_decimal.rb
+++ b/activesupport/lib/active_support/core_ext/big_decimal.rb
@@ -1 +1,3 @@
-require "active_support/core_ext/big_decimal/conversions"
+# frozen_string_literal: true
+
+require_relative "big_decimal/conversions"
diff --git a/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb b/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb
index decd4e1699..52bd229416 100644
--- a/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "bigdecimal"
require "bigdecimal/util"
diff --git a/activesupport/lib/active_support/core_ext/class.rb b/activesupport/lib/active_support/core_ext/class.rb
index 6a19e862d0..65e1d68399 100644
--- a/activesupport/lib/active_support/core_ext/class.rb
+++ b/activesupport/lib/active_support/core_ext/class.rb
@@ -1,2 +1,4 @@
-require "active_support/core_ext/class/attribute"
-require "active_support/core_ext/class/subclasses"
+# frozen_string_literal: true
+
+require_relative "class/attribute"
+require_relative "class/subclasses"
diff --git a/activesupport/lib/active_support/core_ext/class/attribute.rb b/activesupport/lib/active_support/core_ext/class/attribute.rb
index ba422f9071..a72dbc7bf0 100644
--- a/activesupport/lib/active_support/core_ext/class/attribute.rb
+++ b/activesupport/lib/active_support/core_ext/class/attribute.rb
@@ -1,6 +1,8 @@
-require "active_support/core_ext/kernel/singleton_class"
-require "active_support/core_ext/module/remove_method"
-require "active_support/core_ext/array/extract_options"
+# frozen_string_literal: true
+
+require_relative "../kernel/singleton_class"
+require_relative "../module/remove_method"
+require_relative "../array/extract_options"
class Class
# Declare a class-level attribute whose value is inheritable by subclasses.
@@ -68,11 +70,16 @@ class Class
# object.setting = false # => NoMethodError
#
# To opt out of both instance methods, pass <tt>instance_accessor: false</tt>.
+ #
+ # To set a default value for the attribute, pass <tt>default:</tt>, like so:
+ #
+ # class_attribute :settings, default: {}
def class_attribute(*attrs)
options = attrs.extract_options!
- instance_reader = options.fetch(:instance_accessor, true) && options.fetch(:instance_reader, true)
- instance_writer = options.fetch(:instance_accessor, true) && options.fetch(:instance_writer, true)
+ instance_reader = options.fetch(:instance_accessor, true) && options.fetch(:instance_reader, true)
+ instance_writer = options.fetch(:instance_accessor, true) && options.fetch(:instance_writer, true)
instance_predicate = options.fetch(:instance_predicate, true)
+ default_value = options.fetch(:default, nil)
attrs.each do |name|
remove_possible_singleton_method(name)
@@ -123,6 +130,10 @@ class Class
remove_possible_method "#{name}="
attr_writer name
end
+
+ unless default_value.nil?
+ self.send("#{name}=", default_value)
+ end
end
end
end
diff --git a/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb b/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb
index 0f767925ed..b4dbcc6698 100644
--- a/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb
+++ b/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb
@@ -1,4 +1,6 @@
+# frozen_string_literal: true
+
# cattr_* became mattr_* aliases in 7dfbd91b0780fbd6a1dd9bfbc176e10894871d2d,
# but we keep this around for libraries that directly require it knowing they
# want cattr_*. No need to deprecate.
-require "active_support/core_ext/module/attribute_accessors"
+require_relative "../module/attribute_accessors"
diff --git a/activesupport/lib/active_support/core_ext/class/subclasses.rb b/activesupport/lib/active_support/core_ext/class/subclasses.rb
index 62397d9508..4c910feb44 100644
--- a/activesupport/lib/active_support/core_ext/class/subclasses.rb
+++ b/activesupport/lib/active_support/core_ext/class/subclasses.rb
@@ -1,5 +1,7 @@
-require "active_support/core_ext/module/anonymous"
-require "active_support/core_ext/module/reachable"
+# frozen_string_literal: true
+
+require_relative "../module/anonymous"
+require_relative "../module/reachable"
class Class
begin
diff --git a/activesupport/lib/active_support/core_ext/date.rb b/activesupport/lib/active_support/core_ext/date.rb
index 4f66804da2..2a2ed5496f 100644
--- a/activesupport/lib/active_support/core_ext/date.rb
+++ b/activesupport/lib/active_support/core_ext/date.rb
@@ -1,5 +1,7 @@
-require "active_support/core_ext/date/acts_like"
-require "active_support/core_ext/date/blank"
-require "active_support/core_ext/date/calculations"
-require "active_support/core_ext/date/conversions"
-require "active_support/core_ext/date/zones"
+# frozen_string_literal: true
+
+require_relative "date/acts_like"
+require_relative "date/blank"
+require_relative "date/calculations"
+require_relative "date/conversions"
+require_relative "date/zones"
diff --git a/activesupport/lib/active_support/core_ext/date/acts_like.rb b/activesupport/lib/active_support/core_ext/date/acts_like.rb
index 46fe99ad47..81769129b5 100644
--- a/activesupport/lib/active_support/core_ext/date/acts_like.rb
+++ b/activesupport/lib/active_support/core_ext/date/acts_like.rb
@@ -1,4 +1,6 @@
-require "active_support/core_ext/object/acts_like"
+# frozen_string_literal: true
+
+require_relative "../object/acts_like"
class Date
# Duck-types as a Date-like class. See Object#acts_like?.
diff --git a/activesupport/lib/active_support/core_ext/date/blank.rb b/activesupport/lib/active_support/core_ext/date/blank.rb
index edd2847126..e6271c79b3 100644
--- a/activesupport/lib/active_support/core_ext/date/blank.rb
+++ b/activesupport/lib/active_support/core_ext/date/blank.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "date"
class Date #:nodoc:
diff --git a/activesupport/lib/active_support/core_ext/date/calculations.rb b/activesupport/lib/active_support/core_ext/date/calculations.rb
index d6f60cac04..1a19ee8b1e 100644
--- a/activesupport/lib/active_support/core_ext/date/calculations.rb
+++ b/activesupport/lib/active_support/core_ext/date/calculations.rb
@@ -1,9 +1,11 @@
+# frozen_string_literal: true
+
require "date"
-require "active_support/duration"
-require "active_support/core_ext/object/acts_like"
-require "active_support/core_ext/date/zones"
-require "active_support/core_ext/time/zones"
-require "active_support/core_ext/date_and_time/calculations"
+require_relative "../../duration"
+require_relative "../object/acts_like"
+require_relative "zones"
+require_relative "../time/zones"
+require_relative "../date_and_time/calculations"
class Date
include DateAndTime::Calculations
diff --git a/activesupport/lib/active_support/core_ext/date/conversions.rb b/activesupport/lib/active_support/core_ext/date/conversions.rb
index d553406dff..000d6f61ca 100644
--- a/activesupport/lib/active_support/core_ext/date/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/date/conversions.rb
@@ -1,7 +1,9 @@
+# frozen_string_literal: true
+
require "date"
-require "active_support/inflector/methods"
-require "active_support/core_ext/date/zones"
-require "active_support/core_ext/module/remove_method"
+require_relative "../../inflector/methods"
+require_relative "zones"
+require_relative "../module/remove_method"
class Date
DATE_FORMATS = {
@@ -79,6 +81,9 @@ class Date
# date.to_time(:local) # => 2007-11-10 00:00:00 0800
#
# date.to_time(:utc) # => 2007-11-10 00:00:00 UTC
+ #
+ # NOTE: The :local timezone is Ruby's *process* timezone, i.e. ENV['TZ'].
+ # If the *application's* timezone is needed, then use +in_time_zone+ instead.
def to_time(form = :local)
raise ArgumentError, "Expected :local or :utc, got #{form.inspect}." unless [:local, :utc].include?(form)
::Time.send(form, year, month, day)
diff --git a/activesupport/lib/active_support/core_ext/date/zones.rb b/activesupport/lib/active_support/core_ext/date/zones.rb
index da23fe4892..1aed070df0 100644
--- a/activesupport/lib/active_support/core_ext/date/zones.rb
+++ b/activesupport/lib/active_support/core_ext/date/zones.rb
@@ -1,5 +1,7 @@
+# frozen_string_literal: true
+
require "date"
-require "active_support/core_ext/date_and_time/zones"
+require_relative "../date_and_time/zones"
class Date
include DateAndTime::Zones
diff --git a/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb b/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb
index f2ba7fdda5..8546f7e57b 100644
--- a/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb
+++ b/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb
@@ -1,4 +1,6 @@
-require "active_support/core_ext/object/try"
+# frozen_string_literal: true
+
+require_relative "../object/try"
module DateAndTime
module Calculations
@@ -320,6 +322,22 @@ module DateAndTime
beginning_of_year..end_of_year
end
+ # Returns specific next occurring day of week
+ def next_occurring(day_of_week)
+ current_day_number = wday != 0 ? wday - 1 : 6
+ from_now = DAYS_INTO_WEEK.fetch(day_of_week) - current_day_number
+ from_now += 7 unless from_now > 0
+ since(from_now.days)
+ end
+
+ # Returns specific previous occurring day of week
+ def prev_occurring(day_of_week)
+ current_day_number = wday != 0 ? wday - 1 : 6
+ ago = current_day_number - DAYS_INTO_WEEK.fetch(day_of_week)
+ ago += 7 unless ago > 0
+ ago(ago.days)
+ end
+
private
def first_hour(date_or_time)
date_or_time.acts_like?(:time) ? date_or_time.beginning_of_day : date_or_time
diff --git a/activesupport/lib/active_support/core_ext/date_and_time/compatibility.rb b/activesupport/lib/active_support/core_ext/date_and_time/compatibility.rb
index db95ae0db5..5b3aabf6a5 100644
--- a/activesupport/lib/active_support/core_ext/date_and_time/compatibility.rb
+++ b/activesupport/lib/active_support/core_ext/date_and_time/compatibility.rb
@@ -1,4 +1,6 @@
-require "active_support/core_ext/module/attribute_accessors"
+# frozen_string_literal: true
+
+require_relative "../module/attribute_accessors"
module DateAndTime
module Compatibility
@@ -9,14 +11,6 @@ module DateAndTime
# of the receiver. For backwards compatibility we're overriding
# this behavior, but new apps will have an initializer that sets
# this to true, because the new behavior is preferred.
- mattr_accessor(:preserve_timezone, instance_writer: false) { false }
-
- def to_time
- if preserve_timezone
- @_to_time_with_instance_offset ||= getlocal(utc_offset)
- else
- @_to_time_with_system_offset ||= getlocal
- end
- end
+ mattr_accessor :preserve_timezone, instance_writer: false, default: false
end
end
diff --git a/activesupport/lib/active_support/core_ext/date_and_time/zones.rb b/activesupport/lib/active_support/core_ext/date_and_time/zones.rb
index edd724f1d0..894fd9b76d 100644
--- a/activesupport/lib/active_support/core_ext/date_and_time/zones.rb
+++ b/activesupport/lib/active_support/core_ext/date_and_time/zones.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module DateAndTime
module Zones
# Returns the simultaneous time in <tt>Time.zone</tt> if a zone is given or
diff --git a/activesupport/lib/active_support/core_ext/date_time.rb b/activesupport/lib/active_support/core_ext/date_time.rb
index 6fd498f864..b3d6773e4f 100644
--- a/activesupport/lib/active_support/core_ext/date_time.rb
+++ b/activesupport/lib/active_support/core_ext/date_time.rb
@@ -1,5 +1,7 @@
-require "active_support/core_ext/date_time/acts_like"
-require "active_support/core_ext/date_time/blank"
-require "active_support/core_ext/date_time/calculations"
-require "active_support/core_ext/date_time/compatibility"
-require "active_support/core_ext/date_time/conversions"
+# frozen_string_literal: true
+
+require_relative "date_time/acts_like"
+require_relative "date_time/blank"
+require_relative "date_time/calculations"
+require_relative "date_time/compatibility"
+require_relative "date_time/conversions"
diff --git a/activesupport/lib/active_support/core_ext/date_time/acts_like.rb b/activesupport/lib/active_support/core_ext/date_time/acts_like.rb
index 6f50f55a53..02acb5fe21 100644
--- a/activesupport/lib/active_support/core_ext/date_time/acts_like.rb
+++ b/activesupport/lib/active_support/core_ext/date_time/acts_like.rb
@@ -1,5 +1,7 @@
+# frozen_string_literal: true
+
require "date"
-require "active_support/core_ext/object/acts_like"
+require_relative "../object/acts_like"
class DateTime
# Duck-types as a Date-like class. See Object#acts_like?.
diff --git a/activesupport/lib/active_support/core_ext/date_time/blank.rb b/activesupport/lib/active_support/core_ext/date_time/blank.rb
index b475fd926d..a52c8bc150 100644
--- a/activesupport/lib/active_support/core_ext/date_time/blank.rb
+++ b/activesupport/lib/active_support/core_ext/date_time/blank.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "date"
class DateTime #:nodoc:
diff --git a/activesupport/lib/active_support/core_ext/date_time/calculations.rb b/activesupport/lib/active_support/core_ext/date_time/calculations.rb
index 7a9eb8c266..e61b23f842 100644
--- a/activesupport/lib/active_support/core_ext/date_time/calculations.rb
+++ b/activesupport/lib/active_support/core_ext/date_time/calculations.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "date"
class DateTime
diff --git a/activesupport/lib/active_support/core_ext/date_time/compatibility.rb b/activesupport/lib/active_support/core_ext/date_time/compatibility.rb
index 30bb7f4a60..71da7be8ca 100644
--- a/activesupport/lib/active_support/core_ext/date_time/compatibility.rb
+++ b/activesupport/lib/active_support/core_ext/date_time/compatibility.rb
@@ -1,5 +1,18 @@
-require "active_support/core_ext/date_and_time/compatibility"
+# frozen_string_literal: true
+
+require_relative "../date_and_time/compatibility"
+require_relative "../module/remove_method"
class DateTime
- prepend DateAndTime::Compatibility
+ include DateAndTime::Compatibility
+
+ remove_possible_method :to_time
+
+ # Either return an instance of `Time` with the same UTC offset
+ # as +self+ or an instance of `Time` representing the same time
+ # in the the local system timezone depending on the setting of
+ # on the setting of +ActiveSupport.to_time_preserves_timezone+.
+ def to_time
+ preserve_timezone ? getlocal(utc_offset) : getlocal
+ end
end
diff --git a/activesupport/lib/active_support/core_ext/date_time/conversions.rb b/activesupport/lib/active_support/core_ext/date_time/conversions.rb
index d9b3743858..e4c8f9898d 100644
--- a/activesupport/lib/active_support/core_ext/date_time/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/date_time/conversions.rb
@@ -1,8 +1,10 @@
+# frozen_string_literal: true
+
require "date"
-require "active_support/inflector/methods"
-require "active_support/core_ext/time/conversions"
-require "active_support/core_ext/date_time/calculations"
-require "active_support/values/time_zone"
+require_relative "../../inflector/methods"
+require_relative "../time/conversions"
+require_relative "calculations"
+require_relative "../../values/time_zone"
class DateTime
# Convert to a formatted string. See Time::DATE_FORMATS for predefined formats.
diff --git a/activesupport/lib/active_support/core_ext/digest/uuid.rb b/activesupport/lib/active_support/core_ext/digest/uuid.rb
index e6d60e3267..992e1081e4 100644
--- a/activesupport/lib/active_support/core_ext/digest/uuid.rb
+++ b/activesupport/lib/active_support/core_ext/digest/uuid.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "securerandom"
module Digest
diff --git a/activesupport/lib/active_support/core_ext/enumerable.rb b/activesupport/lib/active_support/core_ext/enumerable.rb
index 90d7d2947f..17733d955c 100644
--- a/activesupport/lib/active_support/core_ext/enumerable.rb
+++ b/activesupport/lib/active_support/core_ext/enumerable.rb
@@ -1,28 +1,52 @@
+# frozen_string_literal: true
+
module Enumerable
- # Calculates a sum from the elements.
- #
- # payments.sum { |p| p.price * p.tax_rate }
- # payments.sum(&:price)
- #
- # The latter is a shortcut for:
- #
- # payments.inject(0) { |sum, p| sum + p.price }
- #
- # It can also calculate the sum without the use of a block.
- #
- # [5, 15, 10].sum # => 30
- # ['foo', 'bar'].sum # => "foobar"
- # [[1, 2], [3, 1, 5]].sum # => [1, 2, 3, 1, 5]
- #
- # The default sum of an empty list is zero. You can override this default:
+ # Enumerable#sum was added in Ruby 2.4, but it only works with Numeric elements
+ # when we omit an identity.
#
- # [].sum(Payment.new(0)) { |i| i.amount } # => Payment.new(0)
- def sum(identity = nil, &block)
- if block_given?
- map(&block).sum(identity)
- else
- sum = identity ? inject(identity, :+) : inject(:+)
- sum || identity || 0
+ # We tried shimming it to attempt the fast native method, rescue TypeError,
+ # and fall back to the compatible implementation, but that's much slower than
+ # just calling the compat method in the first place.
+ if Enumerable.instance_methods(false).include?(:sum) && !((?a..?b).sum rescue false)
+ # We can't use Refinements here because Refinements with Module which will be prepended
+ # doesn't work well https://bugs.ruby-lang.org/issues/13446
+ alias :_original_sum_with_required_identity :sum
+ private :_original_sum_with_required_identity
+ # Calculates a sum from the elements.
+ #
+ # payments.sum { |p| p.price * p.tax_rate }
+ # payments.sum(&:price)
+ #
+ # The latter is a shortcut for:
+ #
+ # payments.inject(0) { |sum, p| sum + p.price }
+ #
+ # It can also calculate the sum without the use of a block.
+ #
+ # [5, 15, 10].sum # => 30
+ # ['foo', 'bar'].sum # => "foobar"
+ # [[1, 2], [3, 1, 5]].sum # => [1, 2, 3, 1, 5]
+ #
+ # The default sum of an empty list is zero. You can override this default:
+ #
+ # [].sum(Payment.new(0)) { |i| i.amount } # => Payment.new(0)
+ def sum(identity = nil, &block)
+ if identity
+ _original_sum_with_required_identity(identity, &block)
+ elsif block_given?
+ map(&block).sum(identity)
+ else
+ inject(:+) || 0
+ end
+ end
+ else
+ def sum(identity = nil, &block)
+ if block_given?
+ map(&block).sum(identity)
+ else
+ sum = identity ? inject(identity, :+) : inject(:+)
+ sum || identity || 0
+ end
end
end
diff --git a/activesupport/lib/active_support/core_ext/file.rb b/activesupport/lib/active_support/core_ext/file.rb
index 6d99bad2af..3c2364167d 100644
--- a/activesupport/lib/active_support/core_ext/file.rb
+++ b/activesupport/lib/active_support/core_ext/file.rb
@@ -1 +1,3 @@
-require "active_support/core_ext/file/atomic"
+# frozen_string_literal: true
+
+require_relative "file/atomic"
diff --git a/activesupport/lib/active_support/core_ext/file/atomic.rb b/activesupport/lib/active_support/core_ext/file/atomic.rb
index 8d6c0d3685..8e288833b6 100644
--- a/activesupport/lib/active_support/core_ext/file/atomic.rb
+++ b/activesupport/lib/active_support/core_ext/file/atomic.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "fileutils"
class File
diff --git a/activesupport/lib/active_support/core_ext/hash.rb b/activesupport/lib/active_support/core_ext/hash.rb
index c819307e8a..a74a8c15a6 100644
--- a/activesupport/lib/active_support/core_ext/hash.rb
+++ b/activesupport/lib/active_support/core_ext/hash.rb
@@ -1,9 +1,11 @@
-require "active_support/core_ext/hash/compact"
-require "active_support/core_ext/hash/conversions"
-require "active_support/core_ext/hash/deep_merge"
-require "active_support/core_ext/hash/except"
-require "active_support/core_ext/hash/indifferent_access"
-require "active_support/core_ext/hash/keys"
-require "active_support/core_ext/hash/reverse_merge"
-require "active_support/core_ext/hash/slice"
-require "active_support/core_ext/hash/transform_values"
+# frozen_string_literal: true
+
+require_relative "hash/compact"
+require_relative "hash/conversions"
+require_relative "hash/deep_merge"
+require_relative "hash/except"
+require_relative "hash/indifferent_access"
+require_relative "hash/keys"
+require_relative "hash/reverse_merge"
+require_relative "hash/slice"
+require_relative "hash/transform_values"
diff --git a/activesupport/lib/active_support/core_ext/hash/compact.rb b/activesupport/lib/active_support/core_ext/hash/compact.rb
index e357284be0..d6364dd9f3 100644
--- a/activesupport/lib/active_support/core_ext/hash/compact.rb
+++ b/activesupport/lib/active_support/core_ext/hash/compact.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Hash
unless Hash.instance_methods(false).include?(:compact)
# Returns a hash with non +nil+ values.
diff --git a/activesupport/lib/active_support/core_ext/hash/conversions.rb b/activesupport/lib/active_support/core_ext/hash/conversions.rb
index 2a58a7f1ca..0c0701134e 100644
--- a/activesupport/lib/active_support/core_ext/hash/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/hash/conversions.rb
@@ -1,11 +1,13 @@
-require "active_support/xml_mini"
-require "active_support/time"
-require "active_support/core_ext/object/blank"
-require "active_support/core_ext/object/to_param"
-require "active_support/core_ext/object/to_query"
-require "active_support/core_ext/array/wrap"
-require "active_support/core_ext/hash/reverse_merge"
-require "active_support/core_ext/string/inflections"
+# frozen_string_literal: true
+
+require_relative "../../xml_mini"
+require_relative "../../time"
+require_relative "../object/blank"
+require_relative "../object/to_param"
+require_relative "../object/to_query"
+require_relative "../array/wrap"
+require_relative "reverse_merge"
+require_relative "../string/inflections"
class Hash
# Returns a string containing an XML representation of its receiver:
@@ -71,7 +73,7 @@ class Hash
# configure your own builder with the <tt>:builder</tt> option. The method also accepts
# options like <tt>:dasherize</tt> and friends, they are forwarded to the builder.
def to_xml(options = {})
- require "active_support/builder" unless defined?(Builder)
+ require_relative "../../builder" unless defined?(Builder)
options = options.dup
options[:indent] ||= 2
diff --git a/activesupport/lib/active_support/core_ext/hash/deep_merge.rb b/activesupport/lib/active_support/core_ext/hash/deep_merge.rb
index 9c9faf67ea..f92a2f1c2a 100644
--- a/activesupport/lib/active_support/core_ext/hash/deep_merge.rb
+++ b/activesupport/lib/active_support/core_ext/hash/deep_merge.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Hash
# Returns a new hash with +self+ and +other_hash+ merged recursively.
#
diff --git a/activesupport/lib/active_support/core_ext/hash/except.rb b/activesupport/lib/active_support/core_ext/hash/except.rb
index 2f6d38c1f6..6258610c98 100644
--- a/activesupport/lib/active_support/core_ext/hash/except.rb
+++ b/activesupport/lib/active_support/core_ext/hash/except.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Hash
# Returns a hash that includes everything except given keys.
# hash = { a: true, b: false, c: nil }
diff --git a/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb b/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb
index 3e1ccecb6c..4681d986db 100644
--- a/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb
+++ b/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb
@@ -1,4 +1,6 @@
-require "active_support/hash_with_indifferent_access"
+# frozen_string_literal: true
+
+require_relative "../../hash_with_indifferent_access"
class Hash
# Returns an <tt>ActiveSupport::HashWithIndifferentAccess</tt> out of its receiver:
diff --git a/activesupport/lib/active_support/core_ext/hash/keys.rb b/activesupport/lib/active_support/core_ext/hash/keys.rb
index b7089357a8..d291802b40 100644
--- a/activesupport/lib/active_support/core_ext/hash/keys.rb
+++ b/activesupport/lib/active_support/core_ext/hash/keys.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Hash
# Returns a new hash with all keys converted using the +block+ operation.
#
diff --git a/activesupport/lib/active_support/core_ext/hash/reverse_merge.rb b/activesupport/lib/active_support/core_ext/hash/reverse_merge.rb
index bfae57d4be..ef8d592829 100644
--- a/activesupport/lib/active_support/core_ext/hash/reverse_merge.rb
+++ b/activesupport/lib/active_support/core_ext/hash/reverse_merge.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Hash
# Merges the caller into +other_hash+. For example,
#
@@ -12,10 +14,12 @@ class Hash
def reverse_merge(other_hash)
other_hash.merge(self)
end
+ alias_method :with_defaults, :reverse_merge
# Destructive +reverse_merge+.
def reverse_merge!(other_hash)
replace(reverse_merge(other_hash))
end
alias_method :reverse_update, :reverse_merge!
+ alias_method :with_defaults!, :reverse_merge!
end
diff --git a/activesupport/lib/active_support/core_ext/hash/slice.rb b/activesupport/lib/active_support/core_ext/hash/slice.rb
index 161b00dfb3..94dc225edb 100644
--- a/activesupport/lib/active_support/core_ext/hash/slice.rb
+++ b/activesupport/lib/active_support/core_ext/hash/slice.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Hash
# Slices a hash to include only the given keys. Returns a hash containing
# the given keys.
diff --git a/activesupport/lib/active_support/core_ext/hash/transform_values.rb b/activesupport/lib/active_support/core_ext/hash/transform_values.rb
index 2f693bff0c..4b19c9fc1f 100644
--- a/activesupport/lib/active_support/core_ext/hash/transform_values.rb
+++ b/activesupport/lib/active_support/core_ext/hash/transform_values.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Hash
# Returns a new hash with the results of running +block+ once for every value.
# The keys are unchanged.
diff --git a/activesupport/lib/active_support/core_ext/integer.rb b/activesupport/lib/active_support/core_ext/integer.rb
index 8f0c55f9d3..df80e7ffdb 100644
--- a/activesupport/lib/active_support/core_ext/integer.rb
+++ b/activesupport/lib/active_support/core_ext/integer.rb
@@ -1,3 +1,5 @@
-require "active_support/core_ext/integer/multiple"
-require "active_support/core_ext/integer/inflections"
-require "active_support/core_ext/integer/time"
+# frozen_string_literal: true
+
+require_relative "integer/multiple"
+require_relative "integer/inflections"
+require_relative "integer/time"
diff --git a/activesupport/lib/active_support/core_ext/integer/inflections.rb b/activesupport/lib/active_support/core_ext/integer/inflections.rb
index bc21b65533..7192e92346 100644
--- a/activesupport/lib/active_support/core_ext/integer/inflections.rb
+++ b/activesupport/lib/active_support/core_ext/integer/inflections.rb
@@ -1,4 +1,6 @@
-require "active_support/inflector"
+# frozen_string_literal: true
+
+require_relative "../../inflector"
class Integer
# Ordinalize turns a number into an ordinal string used to denote the
diff --git a/activesupport/lib/active_support/core_ext/integer/multiple.rb b/activesupport/lib/active_support/core_ext/integer/multiple.rb
index c668c7c2eb..e7606662d3 100644
--- a/activesupport/lib/active_support/core_ext/integer/multiple.rb
+++ b/activesupport/lib/active_support/core_ext/integer/multiple.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Integer
# Check whether the integer is evenly divisible by the argument.
#
diff --git a/activesupport/lib/active_support/core_ext/integer/time.rb b/activesupport/lib/active_support/core_ext/integer/time.rb
index 74baae3639..30c8f3bcf2 100644
--- a/activesupport/lib/active_support/core_ext/integer/time.rb
+++ b/activesupport/lib/active_support/core_ext/integer/time.rb
@@ -1,5 +1,7 @@
-require "active_support/duration"
-require "active_support/core_ext/numeric/time"
+# frozen_string_literal: true
+
+require_relative "../../duration"
+require_relative "../numeric/time"
class Integer
# Enables the use of time calculations and declarations, like <tt>45.minutes +
diff --git a/activesupport/lib/active_support/core_ext/kernel.rb b/activesupport/lib/active_support/core_ext/kernel.rb
index 3d41ff7876..30810ce315 100644
--- a/activesupport/lib/active_support/core_ext/kernel.rb
+++ b/activesupport/lib/active_support/core_ext/kernel.rb
@@ -1,4 +1,6 @@
-require "active_support/core_ext/kernel/agnostics"
-require "active_support/core_ext/kernel/concern"
-require "active_support/core_ext/kernel/reporting"
-require "active_support/core_ext/kernel/singleton_class"
+# frozen_string_literal: true
+
+require_relative "kernel/agnostics"
+require_relative "kernel/concern"
+require_relative "kernel/reporting"
+require_relative "kernel/singleton_class"
diff --git a/activesupport/lib/active_support/core_ext/kernel/agnostics.rb b/activesupport/lib/active_support/core_ext/kernel/agnostics.rb
index 64837d87aa..403b5f31f0 100644
--- a/activesupport/lib/active_support/core_ext/kernel/agnostics.rb
+++ b/activesupport/lib/active_support/core_ext/kernel/agnostics.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Object
# Makes backticks behave (somewhat more) similarly on all platforms.
# On win32 `nonexistent_command` raises Errno::ENOENT; on Unix, the
diff --git a/activesupport/lib/active_support/core_ext/kernel/concern.rb b/activesupport/lib/active_support/core_ext/kernel/concern.rb
index 307a7f7a63..32af9981a5 100644
--- a/activesupport/lib/active_support/core_ext/kernel/concern.rb
+++ b/activesupport/lib/active_support/core_ext/kernel/concern.rb
@@ -1,4 +1,6 @@
-require "active_support/core_ext/module/concerning"
+# frozen_string_literal: true
+
+require_relative "../module/concerning"
module Kernel
module_function
diff --git a/activesupport/lib/active_support/core_ext/kernel/reporting.rb b/activesupport/lib/active_support/core_ext/kernel/reporting.rb
index c02618d5f3..9155bd6c10 100644
--- a/activesupport/lib/active_support/core_ext/kernel/reporting.rb
+++ b/activesupport/lib/active_support/core_ext/kernel/reporting.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Kernel
module_function
diff --git a/activesupport/lib/active_support/core_ext/kernel/singleton_class.rb b/activesupport/lib/active_support/core_ext/kernel/singleton_class.rb
index 9bbf1bbd73..6715eba80a 100644
--- a/activesupport/lib/active_support/core_ext/kernel/singleton_class.rb
+++ b/activesupport/lib/active_support/core_ext/kernel/singleton_class.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Kernel
# class_eval on an object acts like singleton_class.class_eval.
def class_eval(*args, &block)
diff --git a/activesupport/lib/active_support/core_ext/load_error.rb b/activesupport/lib/active_support/core_ext/load_error.rb
index d273487010..c3939b5d0b 100644
--- a/activesupport/lib/active_support/core_ext/load_error.rb
+++ b/activesupport/lib/active_support/core_ext/load_error.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class LoadError
REGEXPS = [
/^no such file to load -- (.+)$/i,
diff --git a/activesupport/lib/active_support/core_ext/marshal.rb b/activesupport/lib/active_support/core_ext/marshal.rb
index bba2b3be2e..0c72cd7b47 100644
--- a/activesupport/lib/active_support/core_ext/marshal.rb
+++ b/activesupport/lib/active_support/core_ext/marshal.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActiveSupport
module MarshalWithAutoloading # :nodoc:
def load(source, proc = nil)
diff --git a/activesupport/lib/active_support/core_ext/module.rb b/activesupport/lib/active_support/core_ext/module.rb
index 2930255557..da8f572c3b 100644
--- a/activesupport/lib/active_support/core_ext/module.rb
+++ b/activesupport/lib/active_support/core_ext/module.rb
@@ -1,11 +1,13 @@
-require "active_support/core_ext/module/aliasing"
-require "active_support/core_ext/module/introspection"
-require "active_support/core_ext/module/anonymous"
-require "active_support/core_ext/module/reachable"
-require "active_support/core_ext/module/attribute_accessors"
-require "active_support/core_ext/module/attribute_accessors_per_thread"
-require "active_support/core_ext/module/attr_internal"
-require "active_support/core_ext/module/concerning"
-require "active_support/core_ext/module/delegation"
-require "active_support/core_ext/module/deprecation"
-require "active_support/core_ext/module/remove_method"
+# frozen_string_literal: true
+
+require_relative "module/aliasing"
+require_relative "module/introspection"
+require_relative "module/anonymous"
+require_relative "module/reachable"
+require_relative "module/attribute_accessors"
+require_relative "module/attribute_accessors_per_thread"
+require_relative "module/attr_internal"
+require_relative "module/concerning"
+require_relative "module/delegation"
+require_relative "module/deprecation"
+require_relative "module/remove_method"
diff --git a/activesupport/lib/active_support/core_ext/module/aliasing.rb b/activesupport/lib/active_support/core_ext/module/aliasing.rb
index c48bd3354a..6f64d11627 100644
--- a/activesupport/lib/active_support/core_ext/module/aliasing.rb
+++ b/activesupport/lib/active_support/core_ext/module/aliasing.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Module
# Allows you to make aliases for attributes, which includes
# getter, setter, and a predicate.
diff --git a/activesupport/lib/active_support/core_ext/module/anonymous.rb b/activesupport/lib/active_support/core_ext/module/anonymous.rb
index 510c9a5430..d1c86b8722 100644
--- a/activesupport/lib/active_support/core_ext/module/anonymous.rb
+++ b/activesupport/lib/active_support/core_ext/module/anonymous.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Module
# A module may or may not have a name.
#
diff --git a/activesupport/lib/active_support/core_ext/module/attr_internal.rb b/activesupport/lib/active_support/core_ext/module/attr_internal.rb
index 5081d5f7a3..7801f6d181 100644
--- a/activesupport/lib/active_support/core_ext/module/attr_internal.rb
+++ b/activesupport/lib/active_support/core_ext/module/attr_internal.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Module
# Declares an attribute reader backed by an internally-named instance variable.
def attr_internal_reader(*attrs)
diff --git a/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb b/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb
index 2c24081eb9..e667c1f4a4 100644
--- a/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb
+++ b/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb
@@ -1,5 +1,7 @@
-require "active_support/core_ext/array/extract_options"
-require "active_support/core_ext/regexp"
+# frozen_string_literal: true
+
+require_relative "../array/extract_options"
+require_relative "../regexp"
# Extends the module object with class/module and instance accessors for
# class/module attributes, just like the native attr* accessors for instance
@@ -38,13 +40,10 @@ class Module
#
# Person.new.hair_colors # => NoMethodError
#
- #
- # Also, you can pass a block to set up the attribute with a default value.
+ # You can set a default value for the attribute.
#
# module HairColors
- # mattr_reader :hair_colors do
- # [:brown, :black, :blonde, :red]
- # end
+ # mattr_reader :hair_colors, default: [:brown, :black, :blonde, :red]
# end
#
# class Person
@@ -52,8 +51,7 @@ class Module
# end
#
# Person.new.hair_colors # => [:brown, :black, :blonde, :red]
- def mattr_reader(*syms)
- options = syms.extract_options!
+ def mattr_reader(*syms, instance_reader: true, instance_accessor: true, default: nil)
syms.each do |sym|
raise NameError.new("invalid attribute name: #{sym}") unless /\A[_A-Za-z]\w*\z/.match?(sym)
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
@@ -64,14 +62,16 @@ class Module
end
EOS
- unless options[:instance_reader] == false || options[:instance_accessor] == false
+ if instance_reader && instance_accessor
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
def #{sym}
@@#{sym}
end
EOS
end
- class_variable_set("@@#{sym}", yield) if block_given?
+
+ sym_default_value = (block_given? && default.nil?) ? yield : default
+ class_variable_set("@@#{sym}", sym_default_value) unless sym_default_value.nil?
end
end
alias :cattr_reader :mattr_reader
@@ -107,12 +107,10 @@ class Module
#
# Person.new.hair_colors = [:blonde, :red] # => NoMethodError
#
- # Also, you can pass a block to set up the attribute with a default value.
+ # You can set a default value for the attribute.
#
# module HairColors
- # mattr_writer :hair_colors do
- # [:brown, :black, :blonde, :red]
- # end
+ # mattr_writer :hair_colors, default: [:brown, :black, :blonde, :red]
# end
#
# class Person
@@ -120,8 +118,7 @@ class Module
# end
#
# Person.class_variable_get("@@hair_colors") # => [:brown, :black, :blonde, :red]
- def mattr_writer(*syms)
- options = syms.extract_options!
+ def mattr_writer(*syms, instance_writer: true, instance_accessor: true, default: nil)
syms.each do |sym|
raise NameError.new("invalid attribute name: #{sym}") unless /\A[_A-Za-z]\w*\z/.match?(sym)
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
@@ -132,14 +129,16 @@ class Module
end
EOS
- unless options[:instance_writer] == false || options[:instance_accessor] == false
+ if instance_writer && instance_accessor
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
def #{sym}=(obj)
@@#{sym} = obj
end
EOS
end
- send("#{sym}=", yield) if block_given?
+
+ sym_default_value = (block_given? && default.nil?) ? yield : default
+ send("#{sym}=", sym_default_value) unless sym_default_value.nil?
end
end
alias :cattr_writer :mattr_writer
@@ -197,12 +196,10 @@ class Module
# Person.new.hair_colors = [:brown] # => NoMethodError
# Person.new.hair_colors # => NoMethodError
#
- # Also you can pass a block to set up the attribute with a default value.
+ # You can set a default value for the attribute.
#
# module HairColors
- # mattr_accessor :hair_colors do
- # [:brown, :black, :blonde, :red]
- # end
+ # mattr_accessor :hair_colors, default: [:brown, :black, :blonde, :red]
# end
#
# class Person
@@ -210,9 +207,9 @@ class Module
# end
#
# Person.class_variable_get("@@hair_colors") # => [:brown, :black, :blonde, :red]
- def mattr_accessor(*syms, &blk)
- mattr_reader(*syms, &blk)
- mattr_writer(*syms)
+ def mattr_accessor(*syms, instance_reader: true, instance_writer: true, instance_accessor: true, default: nil, &blk)
+ mattr_reader(*syms, instance_reader: instance_reader, instance_accessor: instance_accessor, default: default, &blk)
+ mattr_writer(*syms, instance_writer: instance_writer, instance_accessor: instance_accessor, default: default)
end
alias :cattr_accessor :mattr_accessor
end
diff --git a/activesupport/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb b/activesupport/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb
index 1e82b4acc2..90a350c5dc 100644
--- a/activesupport/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb
+++ b/activesupport/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb
@@ -1,5 +1,7 @@
-require "active_support/core_ext/array/extract_options"
-require "active_support/core_ext/regexp"
+# frozen_string_literal: true
+
+require_relative "../array/extract_options"
+require_relative "../regexp"
# Extends the module object with class/module and instance accessors for
# class/module attributes, just like the native attr* accessors for instance
diff --git a/activesupport/lib/active_support/core_ext/module/concerning.rb b/activesupport/lib/active_support/core_ext/module/concerning.rb
index 97b0a382ce..17c202a24a 100644
--- a/activesupport/lib/active_support/core_ext/module/concerning.rb
+++ b/activesupport/lib/active_support/core_ext/module/concerning.rb
@@ -1,4 +1,6 @@
-require "active_support/concern"
+# frozen_string_literal: true
+
+require_relative "../../concern"
class Module
# = Bite-sized separation of concerns
diff --git a/activesupport/lib/active_support/core_ext/module/delegation.rb b/activesupport/lib/active_support/core_ext/module/delegation.rb
index cdf27f49ad..6565d53a06 100644
--- a/activesupport/lib/active_support/core_ext/module/delegation.rb
+++ b/activesupport/lib/active_support/core_ext/module/delegation.rb
@@ -1,5 +1,7 @@
+# frozen_string_literal: true
+
require "set"
-require "active_support/core_ext/regexp"
+require_relative "../regexp"
class Module
# Error generated by +delegate+ when a method is called on +nil+ and +allow_nil+
@@ -174,7 +176,7 @@ class Module
to = to.to_s
to = "self.#{to}" if DELEGATION_RESERVED_METHOD_NAMES.include?(to)
- methods.each do |method|
+ methods.map do |method|
# Attribute writer methods only accept one argument. Makes sure []=
# methods still accept two arguments.
definition = /[^\]]=$/.match?(method) ? "arg" : "*args, &block"
@@ -219,55 +221,53 @@ class Module
# When building decorators, a common pattern may emerge:
#
# class Partition
- # def initialize(first_event)
- # @events = [ first_event ]
+ # def initialize(event)
+ # @event = event
# end
#
- # def people
- # if @events.first.detail.people.any?
- # @events.collect { |e| Array(e.detail.people) }.flatten.uniq
- # else
- # @events.collect(&:creator).uniq
- # end
+ # def person
+ # @event.detail.person || @event.creator
# end
#
# private
# def respond_to_missing?(name, include_private = false)
- # @events.respond_to?(name, include_private)
+ # @event.respond_to?(name, include_private)
# end
#
# def method_missing(method, *args, &block)
- # @events.send(method, *args, &block)
+ # @event.send(method, *args, &block)
# end
# end
#
- # With `Module#delegate_missing_to`, the above is condensed to:
+ # With <tt>Module#delegate_missing_to</tt>, the above is condensed to:
#
# class Partition
- # delegate_missing_to :@events
+ # delegate_missing_to :@event
#
- # def initialize(first_event)
- # @events = [ first_event ]
+ # def initialize(event)
+ # @event = event
# end
#
- # def people
- # if @events.first.detail.people.any?
- # @events.collect { |e| Array(e.detail.people) }.flatten.uniq
- # else
- # @events.collect(&:creator).uniq
- # end
+ # def person
+ # @event.detail.person || @event.creator
# end
# end
#
- # The target can be anything callable within the object. E.g. instance
- # variables, methods, constants and the likes.
+ # The target can be anything callable within the object, e.g. instance
+ # variables, methods, constants, etc.
+ #
+ # The delegated method must be public on the target, otherwise it will
+ # raise +NoMethodError+.
def delegate_missing_to(target)
target = target.to_s
target = "self.#{target}" if DELEGATION_RESERVED_METHOD_NAMES.include?(target)
module_eval <<-RUBY, __FILE__, __LINE__ + 1
def respond_to_missing?(name, include_private = false)
- #{target}.respond_to?(name, include_private)
+ # It may look like an oversight, but we deliberately do not pass
+ # +include_private+, because they do not get delegated.
+
+ #{target}.respond_to?(name) || super
end
def method_missing(method, *args, &block)
diff --git a/activesupport/lib/active_support/core_ext/module/deprecation.rb b/activesupport/lib/active_support/core_ext/module/deprecation.rb
index f3f2e7f5fc..71c42eb357 100644
--- a/activesupport/lib/active_support/core_ext/module/deprecation.rb
+++ b/activesupport/lib/active_support/core_ext/module/deprecation.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Module
# deprecate :foo
# deprecate bar: 'message'
diff --git a/activesupport/lib/active_support/core_ext/module/introspection.rb b/activesupport/lib/active_support/core_ext/module/introspection.rb
index ca20a6d4c5..540385ef6f 100644
--- a/activesupport/lib/active_support/core_ext/module/introspection.rb
+++ b/activesupport/lib/active_support/core_ext/module/introspection.rb
@@ -1,4 +1,6 @@
-require "active_support/inflector"
+# frozen_string_literal: true
+
+require_relative "../../inflector"
class Module
# Returns the name of the module containing this one.
diff --git a/activesupport/lib/active_support/core_ext/module/reachable.rb b/activesupport/lib/active_support/core_ext/module/reachable.rb
index b89a38f26c..91b230b46c 100644
--- a/activesupport/lib/active_support/core_ext/module/reachable.rb
+++ b/activesupport/lib/active_support/core_ext/module/reachable.rb
@@ -1,5 +1,7 @@
-require "active_support/core_ext/module/anonymous"
-require "active_support/core_ext/string/inflections"
+# frozen_string_literal: true
+
+require_relative "anonymous"
+require_relative "../string/inflections"
class Module
def reachable? #:nodoc:
diff --git a/activesupport/lib/active_support/core_ext/module/remove_method.rb b/activesupport/lib/active_support/core_ext/module/remove_method.rb
index d5ec16d68a..bf0d686e16 100644
--- a/activesupport/lib/active_support/core_ext/module/remove_method.rb
+++ b/activesupport/lib/active_support/core_ext/module/remove_method.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Module
# Removes the named method, if it exists.
def remove_possible_method(method)
diff --git a/activesupport/lib/active_support/core_ext/name_error.rb b/activesupport/lib/active_support/core_ext/name_error.rb
index 6b447d772b..d4f1e01140 100644
--- a/activesupport/lib/active_support/core_ext/name_error.rb
+++ b/activesupport/lib/active_support/core_ext/name_error.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class NameError
# Extract the name of the missing constant from the exception message.
#
diff --git a/activesupport/lib/active_support/core_ext/numeric.rb b/activesupport/lib/active_support/core_ext/numeric.rb
index 6062f9e3a8..76e33a7cb0 100644
--- a/activesupport/lib/active_support/core_ext/numeric.rb
+++ b/activesupport/lib/active_support/core_ext/numeric.rb
@@ -1,4 +1,6 @@
-require "active_support/core_ext/numeric/bytes"
-require "active_support/core_ext/numeric/time"
-require "active_support/core_ext/numeric/inquiry"
-require "active_support/core_ext/numeric/conversions"
+# frozen_string_literal: true
+
+require_relative "numeric/bytes"
+require_relative "numeric/time"
+require_relative "numeric/inquiry"
+require_relative "numeric/conversions"
diff --git a/activesupport/lib/active_support/core_ext/numeric/bytes.rb b/activesupport/lib/active_support/core_ext/numeric/bytes.rb
index dfbca32474..b002eba406 100644
--- a/activesupport/lib/active_support/core_ext/numeric/bytes.rb
+++ b/activesupport/lib/active_support/core_ext/numeric/bytes.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Numeric
KILOBYTE = 1024
MEGABYTE = KILOBYTE * 1024
diff --git a/activesupport/lib/active_support/core_ext/numeric/conversions.rb b/activesupport/lib/active_support/core_ext/numeric/conversions.rb
index 4f6621693e..05528f5069 100644
--- a/activesupport/lib/active_support/core_ext/numeric/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/numeric/conversions.rb
@@ -1,6 +1,8 @@
-require "active_support/core_ext/big_decimal/conversions"
-require "active_support/number_helper"
-require "active_support/core_ext/module/deprecation"
+# frozen_string_literal: true
+
+require_relative "../big_decimal/conversions"
+require_relative "../../number_helper"
+require_relative "../module/deprecation"
module ActiveSupport::NumericWithFormat
# Provides options for converting numbers into formatted strings.
diff --git a/activesupport/lib/active_support/core_ext/numeric/inquiry.rb b/activesupport/lib/active_support/core_ext/numeric/inquiry.rb
index ec79701189..15334c91f1 100644
--- a/activesupport/lib/active_support/core_ext/numeric/inquiry.rb
+++ b/activesupport/lib/active_support/core_ext/numeric/inquiry.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
unless 1.respond_to?(:positive?) # TODO: Remove this file when we drop support to ruby < 2.3
class Numeric
# Returns true if the number is positive.
diff --git a/activesupport/lib/active_support/core_ext/numeric/time.rb b/activesupport/lib/active_support/core_ext/numeric/time.rb
index 2e6c70d418..0cee87cb86 100644
--- a/activesupport/lib/active_support/core_ext/numeric/time.rb
+++ b/activesupport/lib/active_support/core_ext/numeric/time.rb
@@ -1,8 +1,10 @@
-require "active_support/duration"
-require "active_support/core_ext/time/calculations"
-require "active_support/core_ext/time/acts_like"
-require "active_support/core_ext/date/calculations"
-require "active_support/core_ext/date/acts_like"
+# frozen_string_literal: true
+
+require_relative "../../duration"
+require_relative "../time/calculations"
+require_relative "../time/acts_like"
+require_relative "../date/calculations"
+require_relative "../date/acts_like"
class Numeric
# Enables the use of time calculations and declarations, like 45.minutes + 2.hours + 4.years.
diff --git a/activesupport/lib/active_support/core_ext/object.rb b/activesupport/lib/active_support/core_ext/object.rb
index 58bbf78601..23f5eec8c7 100644
--- a/activesupport/lib/active_support/core_ext/object.rb
+++ b/activesupport/lib/active_support/core_ext/object.rb
@@ -1,14 +1,16 @@
-require "active_support/core_ext/object/acts_like"
-require "active_support/core_ext/object/blank"
-require "active_support/core_ext/object/duplicable"
-require "active_support/core_ext/object/deep_dup"
-require "active_support/core_ext/object/try"
-require "active_support/core_ext/object/inclusion"
+# frozen_string_literal: true
-require "active_support/core_ext/object/conversions"
-require "active_support/core_ext/object/instance_variables"
+require_relative "object/acts_like"
+require_relative "object/blank"
+require_relative "object/duplicable"
+require_relative "object/deep_dup"
+require_relative "object/try"
+require_relative "object/inclusion"
-require "active_support/core_ext/object/json"
-require "active_support/core_ext/object/to_param"
-require "active_support/core_ext/object/to_query"
-require "active_support/core_ext/object/with_options"
+require_relative "object/conversions"
+require_relative "object/instance_variables"
+
+require_relative "object/json"
+require_relative "object/to_param"
+require_relative "object/to_query"
+require_relative "object/with_options"
diff --git a/activesupport/lib/active_support/core_ext/object/acts_like.rb b/activesupport/lib/active_support/core_ext/object/acts_like.rb
index 3912cc5ace..2eb72f6b3a 100644
--- a/activesupport/lib/active_support/core_ext/object/acts_like.rb
+++ b/activesupport/lib/active_support/core_ext/object/acts_like.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Object
# A duck-type assistant method. For example, Active Support extends Date
# to define an <tt>acts_like_date?</tt> method, and extends Time to define
diff --git a/activesupport/lib/active_support/core_ext/object/blank.rb b/activesupport/lib/active_support/core_ext/object/blank.rb
index bdb50ee291..397adbdb5a 100644
--- a/activesupport/lib/active_support/core_ext/object/blank.rb
+++ b/activesupport/lib/active_support/core_ext/object/blank.rb
@@ -1,4 +1,6 @@
-require "active_support/core_ext/regexp"
+# frozen_string_literal: true
+
+require_relative "../regexp"
class Object
# An object is blank if it's false, empty, or a whitespace string.
diff --git a/activesupport/lib/active_support/core_ext/object/conversions.rb b/activesupport/lib/active_support/core_ext/object/conversions.rb
index 918ebcdc9f..fdc154188a 100644
--- a/activesupport/lib/active_support/core_ext/object/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/object/conversions.rb
@@ -1,4 +1,6 @@
-require "active_support/core_ext/object/to_param"
-require "active_support/core_ext/object/to_query"
-require "active_support/core_ext/array/conversions"
-require "active_support/core_ext/hash/conversions"
+# frozen_string_literal: true
+
+require_relative "to_param"
+require_relative "to_query"
+require_relative "../array/conversions"
+require_relative "../hash/conversions"
diff --git a/activesupport/lib/active_support/core_ext/object/deep_dup.rb b/activesupport/lib/active_support/core_ext/object/deep_dup.rb
index 5ac649e552..4021b15de6 100644
--- a/activesupport/lib/active_support/core_ext/object/deep_dup.rb
+++ b/activesupport/lib/active_support/core_ext/object/deep_dup.rb
@@ -1,4 +1,6 @@
-require "active_support/core_ext/object/duplicable"
+# frozen_string_literal: true
+
+require_relative "duplicable"
class Object
# Returns a deep copy of object if it's duplicable. If it's
diff --git a/activesupport/lib/active_support/core_ext/object/duplicable.rb b/activesupport/lib/active_support/core_ext/object/duplicable.rb
index ea81df2bd8..1744a44df6 100644
--- a/activesupport/lib/active_support/core_ext/object/duplicable.rb
+++ b/activesupport/lib/active_support/core_ext/object/duplicable.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
#--
# Most objects are cloneable, but not all. For example you can't dup methods:
#
@@ -106,8 +108,8 @@ require "bigdecimal"
class BigDecimal
# BigDecimals are duplicable:
#
- # BigDecimal.new("1.2").duplicable? # => true
- # BigDecimal.new("1.2").dup # => #<BigDecimal:...,'0.12E1',18(18)>
+ # BigDecimal.new("1.2").duplicable? # => true
+ # BigDecimal.new("1.2").dup # => #<BigDecimal:...,'0.12E1',18(18)>
def duplicable?
true
end
@@ -124,21 +126,31 @@ class Method
end
class Complex
- # Complexes are not duplicable:
- #
- # Complex(1).duplicable? # => false
- # Complex(1).dup # => TypeError: can't copy Complex
- def duplicable?
- false
+ begin
+ Complex(1).dup
+ rescue TypeError
+
+ # Complexes are not duplicable:
+ #
+ # Complex(1).duplicable? # => false
+ # Complex(1).dup # => TypeError: can't copy Complex
+ def duplicable?
+ false
+ end
end
end
class Rational
- # Rationals are not duplicable:
- #
- # Rational(1).duplicable? # => false
- # Rational(1).dup # => TypeError: can't copy Rational
- def duplicable?
- false
+ begin
+ Rational(1).dup
+ rescue TypeError
+
+ # Rationals are not duplicable:
+ #
+ # Rational(1).duplicable? # => false
+ # Rational(1).dup # => TypeError: can't copy Rational
+ def duplicable?
+ false
+ end
end
end
diff --git a/activesupport/lib/active_support/core_ext/object/inclusion.rb b/activesupport/lib/active_support/core_ext/object/inclusion.rb
index 98bf820d36..6064e92f20 100644
--- a/activesupport/lib/active_support/core_ext/object/inclusion.rb
+++ b/activesupport/lib/active_support/core_ext/object/inclusion.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Object
# Returns true if this object is included in the argument. Argument must be
# any object which responds to +#include?+. Usage:
diff --git a/activesupport/lib/active_support/core_ext/object/instance_variables.rb b/activesupport/lib/active_support/core_ext/object/instance_variables.rb
index 593a7a4940..12fdf840b5 100644
--- a/activesupport/lib/active_support/core_ext/object/instance_variables.rb
+++ b/activesupport/lib/active_support/core_ext/object/instance_variables.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Object
# Returns a hash with string keys that maps instance variable names without "@" to their
# corresponding values.
diff --git a/activesupport/lib/active_support/core_ext/object/json.rb b/activesupport/lib/active_support/core_ext/object/json.rb
index 1c4d181443..30495313d2 100644
--- a/activesupport/lib/active_support/core_ext/object/json.rb
+++ b/activesupport/lib/active_support/core_ext/object/json.rb
@@ -1,16 +1,18 @@
+# frozen_string_literal: true
+
# Hack to load json gem first so we can overwrite its to_json.
require "json"
require "bigdecimal"
require "uri/generic"
require "pathname"
-require "active_support/core_ext/big_decimal/conversions" # for #to_s
-require "active_support/core_ext/hash/except"
-require "active_support/core_ext/hash/slice"
-require "active_support/core_ext/object/instance_variables"
+require_relative "../big_decimal/conversions" # for #to_s
+require_relative "../hash/except"
+require_relative "../hash/slice"
+require_relative "instance_variables"
require "time"
-require "active_support/core_ext/time/conversions"
-require "active_support/core_ext/date_time/conversions"
-require "active_support/core_ext/date/conversions"
+require_relative "../time/conversions"
+require_relative "../date_time/conversions"
+require_relative "../date/conversions"
# The JSON gem adds a few modules to Ruby core classes containing :to_json definition, overwriting
# their default behavior. That said, we need to define the basic to_json method in all of them,
diff --git a/activesupport/lib/active_support/core_ext/object/to_param.rb b/activesupport/lib/active_support/core_ext/object/to_param.rb
index 5eeaf03163..c57488bcbc 100644
--- a/activesupport/lib/active_support/core_ext/object/to_param.rb
+++ b/activesupport/lib/active_support/core_ext/object/to_param.rb
@@ -1 +1,3 @@
-require "active_support/core_ext/object/to_query"
+# frozen_string_literal: true
+
+require_relative "to_query"
diff --git a/activesupport/lib/active_support/core_ext/object/to_query.rb b/activesupport/lib/active_support/core_ext/object/to_query.rb
index a3a3abacbb..abb461966a 100644
--- a/activesupport/lib/active_support/core_ext/object/to_query.rb
+++ b/activesupport/lib/active_support/core_ext/object/to_query.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "cgi"
class Object
diff --git a/activesupport/lib/active_support/core_ext/object/try.rb b/activesupport/lib/active_support/core_ext/object/try.rb
index b2be619b2d..c874691629 100644
--- a/activesupport/lib/active_support/core_ext/object/try.rb
+++ b/activesupport/lib/active_support/core_ext/object/try.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "delegate"
module ActiveSupport
diff --git a/activesupport/lib/active_support/core_ext/object/with_options.rb b/activesupport/lib/active_support/core_ext/object/with_options.rb
index cf39b1d312..47766f6012 100644
--- a/activesupport/lib/active_support/core_ext/object/with_options.rb
+++ b/activesupport/lib/active_support/core_ext/object/with_options.rb
@@ -1,4 +1,6 @@
-require "active_support/option_merger"
+# frozen_string_literal: true
+
+require_relative "../../option_merger"
class Object
# An elegant way to factor duplication out of options passed to a series of
@@ -62,6 +64,17 @@ class Object
#
# Hence the inherited default for `if` key is ignored.
#
+ # NOTE: You cannot call class methods implicitly inside of with_options.
+ # You can access these methods using the class name instead:
+ #
+ # class Phone < ActiveRecord::Base
+ # enum phone_number_type: [home: 0, office: 1, mobile: 2]
+ #
+ # with_options presence: true do
+ # validates :phone_number_type, inclusion: { in: Phone.phone_number_types.keys }
+ # end
+ # end
+ #
def with_options(options, &block)
option_merger = ActiveSupport::OptionMerger.new(self, options)
block.arity.zero? ? option_merger.instance_eval(&block) : block.call(option_merger)
diff --git a/activesupport/lib/active_support/core_ext/range.rb b/activesupport/lib/active_support/core_ext/range.rb
index 3190e3ff76..89bbbfcb81 100644
--- a/activesupport/lib/active_support/core_ext/range.rb
+++ b/activesupport/lib/active_support/core_ext/range.rb
@@ -1,4 +1,6 @@
-require "active_support/core_ext/range/conversions"
-require "active_support/core_ext/range/include_range"
-require "active_support/core_ext/range/overlaps"
-require "active_support/core_ext/range/each"
+# frozen_string_literal: true
+
+require_relative "range/conversions"
+require_relative "range/include_range"
+require_relative "range/overlaps"
+require_relative "range/each"
diff --git a/activesupport/lib/active_support/core_ext/range/conversions.rb b/activesupport/lib/active_support/core_ext/range/conversions.rb
index 69ea046cb6..37868f5875 100644
--- a/activesupport/lib/active_support/core_ext/range/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/range/conversions.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActiveSupport::RangeWithFormat
RANGE_FORMATS = {
db: Proc.new { |start, stop| "BETWEEN '#{start.to_s(:db)}' AND '#{stop.to_s(:db)}'" }
diff --git a/activesupport/lib/active_support/core_ext/range/each.rb b/activesupport/lib/active_support/core_ext/range/each.rb
index dc6dad5ced..cdff6393d7 100644
--- a/activesupport/lib/active_support/core_ext/range/each.rb
+++ b/activesupport/lib/active_support/core_ext/range/each.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActiveSupport
module EachTimeWithZone #:nodoc:
def each(&block)
diff --git a/activesupport/lib/active_support/core_ext/range/include_range.rb b/activesupport/lib/active_support/core_ext/range/include_range.rb
index c69e1e3fb9..7ba1011921 100644
--- a/activesupport/lib/active_support/core_ext/range/include_range.rb
+++ b/activesupport/lib/active_support/core_ext/range/include_range.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActiveSupport
module IncludeWithRange #:nodoc:
# Extends the default Range#include? to support range comparisons.
diff --git a/activesupport/lib/active_support/core_ext/range/overlaps.rb b/activesupport/lib/active_support/core_ext/range/overlaps.rb
index 603657c180..f753607f8b 100644
--- a/activesupport/lib/active_support/core_ext/range/overlaps.rb
+++ b/activesupport/lib/active_support/core_ext/range/overlaps.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Range
# Compare two ranges and see if they overlap each other
# (1..5).overlaps?(4..6) # => true
diff --git a/activesupport/lib/active_support/core_ext/regexp.rb b/activesupport/lib/active_support/core_ext/regexp.rb
index d77d01bf42..efbd708aee 100644
--- a/activesupport/lib/active_support/core_ext/regexp.rb
+++ b/activesupport/lib/active_support/core_ext/regexp.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Regexp #:nodoc:
def multiline?
options & MULTILINE == MULTILINE
diff --git a/activesupport/lib/active_support/core_ext/securerandom.rb b/activesupport/lib/active_support/core_ext/securerandom.rb
index a57685bea1..b4a491f5fd 100644
--- a/activesupport/lib/active_support/core_ext/securerandom.rb
+++ b/activesupport/lib/active_support/core_ext/securerandom.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "securerandom"
module SecureRandom
diff --git a/activesupport/lib/active_support/core_ext/string.rb b/activesupport/lib/active_support/core_ext/string.rb
index 4cb3200875..491eec2fc9 100644
--- a/activesupport/lib/active_support/core_ext/string.rb
+++ b/activesupport/lib/active_support/core_ext/string.rb
@@ -1,13 +1,15 @@
-require "active_support/core_ext/string/conversions"
-require "active_support/core_ext/string/filters"
-require "active_support/core_ext/string/multibyte"
-require "active_support/core_ext/string/starts_ends_with"
-require "active_support/core_ext/string/inflections"
-require "active_support/core_ext/string/access"
-require "active_support/core_ext/string/behavior"
-require "active_support/core_ext/string/output_safety"
-require "active_support/core_ext/string/exclude"
-require "active_support/core_ext/string/strip"
-require "active_support/core_ext/string/inquiry"
-require "active_support/core_ext/string/indent"
-require "active_support/core_ext/string/zones"
+# frozen_string_literal: true
+
+require_relative "string/conversions"
+require_relative "string/filters"
+require_relative "string/multibyte"
+require_relative "string/starts_ends_with"
+require_relative "string/inflections"
+require_relative "string/access"
+require_relative "string/behavior"
+require_relative "string/output_safety"
+require_relative "string/exclude"
+require_relative "string/strip"
+require_relative "string/inquiry"
+require_relative "string/indent"
+require_relative "string/zones"
diff --git a/activesupport/lib/active_support/core_ext/string/access.rb b/activesupport/lib/active_support/core_ext/string/access.rb
index 6133826f37..58591bbaaf 100644
--- a/activesupport/lib/active_support/core_ext/string/access.rb
+++ b/activesupport/lib/active_support/core_ext/string/access.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class String
# If you pass a single integer, returns a substring of one character at that
# position. The first character of the string is at position 0, the next at
diff --git a/activesupport/lib/active_support/core_ext/string/behavior.rb b/activesupport/lib/active_support/core_ext/string/behavior.rb
index 710f1f4670..35a5aa7840 100644
--- a/activesupport/lib/active_support/core_ext/string/behavior.rb
+++ b/activesupport/lib/active_support/core_ext/string/behavior.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class String
# Enables more predictable duck-typing on String-like classes. See <tt>Object#acts_like?</tt>.
def acts_like_string?
diff --git a/activesupport/lib/active_support/core_ext/string/conversions.rb b/activesupport/lib/active_support/core_ext/string/conversions.rb
index 221b4969cc..f8f6524b2b 100644
--- a/activesupport/lib/active_support/core_ext/string/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/string/conversions.rb
@@ -1,5 +1,7 @@
+# frozen_string_literal: true
+
require "date"
-require "active_support/core_ext/time/calculations"
+require_relative "../time/calculations"
class String
# Converts a string to a Time value.
diff --git a/activesupport/lib/active_support/core_ext/string/exclude.rb b/activesupport/lib/active_support/core_ext/string/exclude.rb
index 0ac684f6ee..8e462689f1 100644
--- a/activesupport/lib/active_support/core_ext/string/exclude.rb
+++ b/activesupport/lib/active_support/core_ext/string/exclude.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class String
# The inverse of <tt>String#include?</tt>. Returns true if the string
# does not include the other string.
diff --git a/activesupport/lib/active_support/core_ext/string/filters.rb b/activesupport/lib/active_support/core_ext/string/filters.rb
index a9ec2eb842..66e721eea3 100644
--- a/activesupport/lib/active_support/core_ext/string/filters.rb
+++ b/activesupport/lib/active_support/core_ext/string/filters.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class String
# Returns the string, first removing all whitespace on both ends of
# the string, and then changing remaining consecutive whitespace
diff --git a/activesupport/lib/active_support/core_ext/string/indent.rb b/activesupport/lib/active_support/core_ext/string/indent.rb
index d7b58301d3..af9d181487 100644
--- a/activesupport/lib/active_support/core_ext/string/indent.rb
+++ b/activesupport/lib/active_support/core_ext/string/indent.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class String
# Same as +indent+, except it indents the receiver in-place.
#
diff --git a/activesupport/lib/active_support/core_ext/string/inflections.rb b/activesupport/lib/active_support/core_ext/string/inflections.rb
index 7a2fc5c1b5..846600c623 100644
--- a/activesupport/lib/active_support/core_ext/string/inflections.rb
+++ b/activesupport/lib/active_support/core_ext/string/inflections.rb
@@ -1,5 +1,7 @@
-require "active_support/inflector/methods"
-require "active_support/inflector/transliterate"
+# frozen_string_literal: true
+
+require_relative "../../inflector/methods"
+require_relative "../../inflector/transliterate"
# String inflections define new methods on the String class to transform names for different purposes.
# For instance, you can figure out the name of a table from the name of a class.
@@ -100,12 +102,17 @@ class String
# a nicer looking title. +titleize+ is meant for creating pretty output. It is not
# used in the Rails internals.
#
+ # The trailing '_id','Id'.. can be kept and capitalized by setting the
+ # optional parameter +keep_id_suffix+ to true.
+ # By default, this parameter is false.
+ #
# +titleize+ is also aliased as +titlecase+.
#
- # 'man from the boondocks'.titleize # => "Man From The Boondocks"
- # 'x-men: the last stand'.titleize # => "X Men: The Last Stand"
- def titleize
- ActiveSupport::Inflector.titleize(self)
+ # 'man from the boondocks'.titleize # => "Man From The Boondocks"
+ # 'x-men: the last stand'.titleize # => "X Men: The Last Stand"
+ # 'string_ending_with_id'.titleize(keep_id_suffix: true) # => "String Ending With Id"
+ def titleize(keep_id_suffix: false)
+ ActiveSupport::Inflector.titleize(self, keep_id_suffix: keep_id_suffix)
end
alias_method :titlecase, :titleize
@@ -202,7 +209,7 @@ class String
ActiveSupport::Inflector.classify(self)
end
- # Capitalizes the first word, turns underscores into spaces, and strips a
+ # Capitalizes the first word, turns underscores into spaces, and (by default)strips a
# trailing '_id' if present.
# Like +titleize+, this is meant for creating pretty output.
#
@@ -210,12 +217,17 @@ class String
# optional parameter +capitalize+ to false.
# By default, this parameter is true.
#
- # 'employee_salary'.humanize # => "Employee salary"
- # 'author_id'.humanize # => "Author"
- # 'author_id'.humanize(capitalize: false) # => "author"
- # '_id'.humanize # => "Id"
- def humanize(options = {})
- ActiveSupport::Inflector.humanize(self, options)
+ # The trailing '_id' can be kept and capitalized by setting the
+ # optional parameter +keep_id_suffix+ to true.
+ # By default, this parameter is false.
+ #
+ # 'employee_salary'.humanize # => "Employee salary"
+ # 'author_id'.humanize # => "Author"
+ # 'author_id'.humanize(capitalize: false) # => "author"
+ # '_id'.humanize # => "Id"
+ # 'author_id'.humanize(keep_id_suffix: true) # => "Author Id"
+ def humanize(capitalize: true, keep_id_suffix: false)
+ ActiveSupport::Inflector.humanize(self, capitalize: capitalize, keep_id_suffix: keep_id_suffix)
end
# Converts just the first character to uppercase.
diff --git a/activesupport/lib/active_support/core_ext/string/inquiry.rb b/activesupport/lib/active_support/core_ext/string/inquiry.rb
index c95d83beae..92069981b6 100644
--- a/activesupport/lib/active_support/core_ext/string/inquiry.rb
+++ b/activesupport/lib/active_support/core_ext/string/inquiry.rb
@@ -1,4 +1,6 @@
-require "active_support/string_inquirer"
+# frozen_string_literal: true
+
+require_relative "../../string_inquirer"
class String
# Wraps the current string in the <tt>ActiveSupport::StringInquirer</tt> class,
diff --git a/activesupport/lib/active_support/core_ext/string/multibyte.rb b/activesupport/lib/active_support/core_ext/string/multibyte.rb
index 1c73182259..fba5b166a2 100644
--- a/activesupport/lib/active_support/core_ext/string/multibyte.rb
+++ b/activesupport/lib/active_support/core_ext/string/multibyte.rb
@@ -1,4 +1,6 @@
-require "active_support/multibyte"
+# frozen_string_literal: true
+
+require_relative "../../multibyte"
class String
# == Multibyte proxy
diff --git a/activesupport/lib/active_support/core_ext/string/output_safety.rb b/activesupport/lib/active_support/core_ext/string/output_safety.rb
index 94ce3f6a61..adcd2b1dca 100644
--- a/activesupport/lib/active_support/core_ext/string/output_safety.rb
+++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb
@@ -1,6 +1,8 @@
+# frozen_string_literal: true
+
require "erb"
-require "active_support/core_ext/kernel/singleton_class"
-require "active_support/multibyte/unicode"
+require_relative "../kernel/singleton_class"
+require_relative "../../multibyte/unicode"
class ERB
module Util
diff --git a/activesupport/lib/active_support/core_ext/string/starts_ends_with.rb b/activesupport/lib/active_support/core_ext/string/starts_ends_with.rb
index 641acf62d0..919eb7a573 100644
--- a/activesupport/lib/active_support/core_ext/string/starts_ends_with.rb
+++ b/activesupport/lib/active_support/core_ext/string/starts_ends_with.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class String
alias_method :starts_with?, :start_with?
alias_method :ends_with?, :end_with?
diff --git a/activesupport/lib/active_support/core_ext/string/strip.rb b/activesupport/lib/active_support/core_ext/string/strip.rb
index bb62e6c0ba..cc26274e4a 100644
--- a/activesupport/lib/active_support/core_ext/string/strip.rb
+++ b/activesupport/lib/active_support/core_ext/string/strip.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class String
# Strips indentation in heredocs.
#
diff --git a/activesupport/lib/active_support/core_ext/string/zones.rb b/activesupport/lib/active_support/core_ext/string/zones.rb
index de5a28e4f7..db30c03a8e 100644
--- a/activesupport/lib/active_support/core_ext/string/zones.rb
+++ b/activesupport/lib/active_support/core_ext/string/zones.rb
@@ -1,5 +1,7 @@
-require "active_support/core_ext/string/conversions"
-require "active_support/core_ext/time/zones"
+# frozen_string_literal: true
+
+require_relative "conversions"
+require_relative "../time/zones"
class String
# Converts String to a TimeWithZone in the current zone if Time.zone or Time.zone_default
diff --git a/activesupport/lib/active_support/core_ext/time.rb b/activesupport/lib/active_support/core_ext/time.rb
index b1ae4a45d9..4e16274443 100644
--- a/activesupport/lib/active_support/core_ext/time.rb
+++ b/activesupport/lib/active_support/core_ext/time.rb
@@ -1,5 +1,7 @@
-require "active_support/core_ext/time/acts_like"
-require "active_support/core_ext/time/calculations"
-require "active_support/core_ext/time/compatibility"
-require "active_support/core_ext/time/conversions"
-require "active_support/core_ext/time/zones"
+# frozen_string_literal: true
+
+require_relative "time/acts_like"
+require_relative "time/calculations"
+require_relative "time/compatibility"
+require_relative "time/conversions"
+require_relative "time/zones"
diff --git a/activesupport/lib/active_support/core_ext/time/acts_like.rb b/activesupport/lib/active_support/core_ext/time/acts_like.rb
index cf4b2539c5..309418df42 100644
--- a/activesupport/lib/active_support/core_ext/time/acts_like.rb
+++ b/activesupport/lib/active_support/core_ext/time/acts_like.rb
@@ -1,4 +1,6 @@
-require "active_support/core_ext/object/acts_like"
+# frozen_string_literal: true
+
+require_relative "../object/acts_like"
class Time
# Duck-types as a Time-like class. See Object#acts_like?.
diff --git a/activesupport/lib/active_support/core_ext/time/calculations.rb b/activesupport/lib/active_support/core_ext/time/calculations.rb
index 7b7aeef25a..0e51df44ef 100644
--- a/activesupport/lib/active_support/core_ext/time/calculations.rb
+++ b/activesupport/lib/active_support/core_ext/time/calculations.rb
@@ -1,9 +1,11 @@
-require "active_support/duration"
-require "active_support/core_ext/time/conversions"
-require "active_support/time_with_zone"
-require "active_support/core_ext/time/zones"
-require "active_support/core_ext/date_and_time/calculations"
-require "active_support/core_ext/date/calculations"
+# frozen_string_literal: true
+
+require_relative "../../duration"
+require_relative "conversions"
+require_relative "../../time_with_zone"
+require_relative "zones"
+require_relative "../date_and_time/calculations"
+require_relative "../date/calculations"
class Time
include DateAndTime::Calculations
@@ -107,21 +109,22 @@ class Time
# to the +options+ parameter. The time options (<tt>:hour</tt>, <tt>:min</tt>,
# <tt>:sec</tt>, <tt>:usec</tt>, <tt>:nsec</tt>) reset cascadingly, so if only
# the hour is passed, then minute, sec, usec and nsec is set to 0. If the hour
- # and minute is passed, then sec, usec and nsec is set to 0. The +options+
- # parameter takes a hash with any of these keys: <tt>:year</tt>, <tt>:month</tt>,
- # <tt>:day</tt>, <tt>:hour</tt>, <tt>:min</tt>, <tt>:sec</tt>, <tt>:usec</tt>
- # <tt>:nsec</tt>. Pass either <tt>:usec</tt> or <tt>:nsec</tt>, not both.
+ # and minute is passed, then sec, usec and nsec is set to 0. The +options+ parameter
+ # takes a hash with any of these keys: <tt>:year</tt>, <tt>:month</tt>, <tt>:day</tt>,
+ # <tt>:hour</tt>, <tt>:min</tt>, <tt>:sec</tt>, <tt>:usec</tt>, <tt>:nsec</tt>,
+ # <tt>:offset</tt>. Pass either <tt>:usec</tt> or <tt>:nsec</tt>, not both.
#
# Time.new(2012, 8, 29, 22, 35, 0).change(day: 1) # => Time.new(2012, 8, 1, 22, 35, 0)
# Time.new(2012, 8, 29, 22, 35, 0).change(year: 1981, day: 1) # => Time.new(1981, 8, 1, 22, 35, 0)
# Time.new(2012, 8, 29, 22, 35, 0).change(year: 1981, hour: 0) # => Time.new(1981, 8, 29, 0, 0, 0)
def change(options)
- new_year = options.fetch(:year, year)
- new_month = options.fetch(:month, month)
- new_day = options.fetch(:day, day)
- new_hour = options.fetch(:hour, hour)
- new_min = options.fetch(:min, options[:hour] ? 0 : min)
- new_sec = options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec)
+ new_year = options.fetch(:year, year)
+ new_month = options.fetch(:month, month)
+ new_day = options.fetch(:day, day)
+ new_hour = options.fetch(:hour, hour)
+ new_min = options.fetch(:min, options[:hour] ? 0 : min)
+ new_sec = options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec)
+ new_offset = options.fetch(:offset, nil)
if new_nsec = options[:nsec]
raise ArgumentError, "Can't change both :nsec and :usec at the same time: #{options.inspect}" if options[:usec]
@@ -130,13 +133,18 @@ class Time
new_usec = options.fetch(:usec, (options[:hour] || options[:min] || options[:sec]) ? 0 : Rational(nsec, 1000))
end
- if utc?
- ::Time.utc(new_year, new_month, new_day, new_hour, new_min, new_sec, new_usec)
+ raise ArgumentError, "argument out of range" if new_usec >= 1000000
+
+ new_sec += Rational(new_usec, 1000000)
+
+ if new_offset
+ ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, new_offset)
+ elsif utc?
+ ::Time.utc(new_year, new_month, new_day, new_hour, new_min, new_sec)
elsif zone
- ::Time.local(new_year, new_month, new_day, new_hour, new_min, new_sec, new_usec)
+ ::Time.local(new_year, new_month, new_day, new_hour, new_min, new_sec)
else
- raise ArgumentError, "argument out of range" if new_usec >= 1000000
- ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec + (new_usec.to_r / 1000000), utc_offset)
+ ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, utc_offset)
end
end
diff --git a/activesupport/lib/active_support/core_ext/time/compatibility.rb b/activesupport/lib/active_support/core_ext/time/compatibility.rb
index ca4b9574d5..93840e93ca 100644
--- a/activesupport/lib/active_support/core_ext/time/compatibility.rb
+++ b/activesupport/lib/active_support/core_ext/time/compatibility.rb
@@ -1,5 +1,16 @@
-require "active_support/core_ext/date_and_time/compatibility"
+# frozen_string_literal: true
+
+require_relative "../date_and_time/compatibility"
+require_relative "../module/remove_method"
class Time
- prepend DateAndTime::Compatibility
+ include DateAndTime::Compatibility
+
+ remove_possible_method :to_time
+
+ # Either return +self+ or the time in the local system timezone depending
+ # on the setting of +ActiveSupport.to_time_preserves_timezone+.
+ def to_time
+ preserve_timezone ? self : getlocal
+ end
end
diff --git a/activesupport/lib/active_support/core_ext/time/conversions.rb b/activesupport/lib/active_support/core_ext/time/conversions.rb
index 595bda6b4f..e3fc930ef6 100644
--- a/activesupport/lib/active_support/core_ext/time/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/time/conversions.rb
@@ -1,5 +1,7 @@
-require "active_support/inflector/methods"
-require "active_support/values/time_zone"
+# frozen_string_literal: true
+
+require_relative "../../inflector/methods"
+require_relative "../../values/time_zone"
class Time
DATE_FORMATS = {
diff --git a/activesupport/lib/active_support/core_ext/time/zones.rb b/activesupport/lib/active_support/core_ext/time/zones.rb
index 87b5ad903a..c48edb135f 100644
--- a/activesupport/lib/active_support/core_ext/time/zones.rb
+++ b/activesupport/lib/active_support/core_ext/time/zones.rb
@@ -1,6 +1,8 @@
-require "active_support/time_with_zone"
-require "active_support/core_ext/time/acts_like"
-require "active_support/core_ext/date_and_time/zones"
+# frozen_string_literal: true
+
+require_relative "../../time_with_zone"
+require_relative "acts_like"
+require_relative "../date_and_time/zones"
class Time
include DateAndTime::Zones
diff --git a/activesupport/lib/active_support/core_ext/uri.rb b/activesupport/lib/active_support/core_ext/uri.rb
index 342a5fcd52..60fc7f084f 100644
--- a/activesupport/lib/active_support/core_ext/uri.rb
+++ b/activesupport/lib/active_support/core_ext/uri.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "uri"
str = "\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E" # Ni-ho-nn-go in UTF-8, means Japanese.
parser = URI::Parser.new
diff --git a/activesupport/lib/active_support/current_attributes.rb b/activesupport/lib/active_support/current_attributes.rb
new file mode 100644
index 0000000000..9ab1546064
--- /dev/null
+++ b/activesupport/lib/active_support/current_attributes.rb
@@ -0,0 +1,195 @@
+# frozen_string_literal: true
+
+module ActiveSupport
+ # Abstract super class that provides a thread-isolated attributes singleton, which resets automatically
+ # before and after each request. This allows you to keep all the per-request attributes easily
+ # available to the whole system.
+ #
+ # The following full app-like example demonstrates how to use a Current class to
+ # facilitate easy access to the global, per-request attributes without passing them deeply
+ # around everywhere:
+ #
+ # # app/models/current.rb
+ # class Current < ActiveSupport::CurrentAttributes
+ # attribute :account, :user
+ # attribute :request_id, :user_agent, :ip_address
+ #
+ # resets { Time.zone = nil }
+ #
+ # def user=(user)
+ # super
+ # self.account = user.account
+ # Time.zone = user.time_zone
+ # end
+ # end
+ #
+ # # app/controllers/concerns/authentication.rb
+ # module Authentication
+ # extend ActiveSupport::Concern
+ #
+ # included do
+ # before_action :authenticate
+ # end
+ #
+ # private
+ # def authenticate
+ # if authenticated_user = User.find_by(id: cookies.signed[:user_id])
+ # Current.user = authenticated_user
+ # else
+ # redirect_to new_session_url
+ # end
+ # end
+ # end
+ #
+ # # app/controllers/concerns/set_current_request_details.rb
+ # module SetCurrentRequestDetails
+ # extend ActiveSupport::Concern
+ #
+ # included do
+ # before_action do
+ # Current.request_id = request.uuid
+ # Current.user_agent = request.user_agent
+ # Current.ip_address = request.ip
+ # end
+ # end
+ # end
+ #
+ # class ApplicationController < ActionController::Base
+ # include Authentication
+ # include SetCurrentRequestDetails
+ # end
+ #
+ # class MessagesController < ApplicationController
+ # def create
+ # Current.account.messages.create(message_params)
+ # end
+ # end
+ #
+ # class Message < ApplicationRecord
+ # belongs_to :creator, default: -> { Current.user }
+ # after_create { |message| Event.create(record: message) }
+ # end
+ #
+ # class Event < ApplicationRecord
+ # before_create do
+ # self.request_id = Current.request_id
+ # self.user_agent = Current.user_agent
+ # self.ip_address = Current.ip_address
+ # end
+ # end
+ #
+ # A word of caution: It's easy to overdo a global singleton like Current and tangle your model as a result.
+ # Current should only be used for a few, top-level globals, like account, user, and request details.
+ # The attributes stuck in Current should be used by more or less all actions on all requests. If you start
+ # sticking controller-specific attributes in there, you're going to create a mess.
+ class CurrentAttributes
+ include ActiveSupport::Callbacks
+ define_callbacks :reset
+
+ class << self
+ # Returns singleton instance for this class in this thread. If none exists, one is created.
+ def instance
+ current_instances[name] ||= new
+ end
+
+ # Declares one or more attributes that will be given both class and instance accessor methods.
+ def attribute(*names)
+ generated_attribute_methods.module_eval do
+ names.each do |name|
+ define_method(name) do
+ attributes[name.to_sym]
+ end
+
+ define_method("#{name}=") do |attribute|
+ attributes[name.to_sym] = attribute
+ end
+ end
+ end
+
+ names.each do |name|
+ define_singleton_method(name) do
+ instance.public_send(name)
+ end
+
+ define_singleton_method("#{name}=") do |attribute|
+ instance.public_send("#{name}=", attribute)
+ end
+ end
+ end
+
+ # Calls this block after #reset is called on the instance. Used for resetting external collaborators, like Time.zone.
+ def resets(&block)
+ set_callback :reset, :after, &block
+ end
+
+ delegate :set, :reset, to: :instance
+
+ def reset_all # :nodoc:
+ current_instances.each_value(&:reset)
+ end
+
+ def clear_all # :nodoc:
+ reset_all
+ current_instances.clear
+ end
+
+ private
+ def generated_attribute_methods
+ @generated_attribute_methods ||= Module.new.tap { |mod| include mod }
+ end
+
+ def current_instances
+ Thread.current[:current_attributes_instances] ||= {}
+ end
+
+ def method_missing(name, *args, &block)
+ # Caches the method definition as a singleton method of the receiver.
+ #
+ # By letting #delegate handle it, we avoid an enclosure that'll capture args.
+ singleton_class.delegate name, to: :instance
+
+ send(name, *args, &block)
+ end
+ end
+
+ attr_accessor :attributes
+
+ def initialize
+ @attributes = {}
+ end
+
+ # Expose one or more attributes within a block. Old values are returned after the block concludes.
+ # Example demonstrating the common use of needing to set Current attributes outside the request-cycle:
+ #
+ # class Chat::PublicationJob < ApplicationJob
+ # def perform(attributes, room_number, creator)
+ # Current.set(person: creator) do
+ # Chat::Publisher.publish(attributes: attributes, room_number: room_number)
+ # end
+ # end
+ # end
+ def set(set_attributes)
+ old_attributes = compute_attributes(set_attributes.keys)
+ assign_attributes(set_attributes)
+ yield
+ ensure
+ assign_attributes(old_attributes)
+ end
+
+ # Reset all attributes. Should be called before and after actions, when used as a per-request singleton.
+ def reset
+ run_callbacks :reset do
+ self.attributes = {}
+ end
+ end
+
+ private
+ def assign_attributes(new_attributes)
+ new_attributes.each { |key, value| public_send("#{key}=", value) }
+ end
+
+ def compute_attributes(keys)
+ keys.collect { |key| [ key, public_send(key) ] }.to_h
+ end
+ end
+end
diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb
index e125b657f2..3ffe21e559 100644
--- a/activesupport/lib/active_support/dependencies.rb
+++ b/activesupport/lib/active_support/dependencies.rb
@@ -1,25 +1,26 @@
+# frozen_string_literal: true
+
require "set"
require "thread"
require "concurrent/map"
require "pathname"
-require "active_support/core_ext/module/aliasing"
-require "active_support/core_ext/module/attribute_accessors"
-require "active_support/core_ext/module/introspection"
-require "active_support/core_ext/module/anonymous"
-require "active_support/core_ext/object/blank"
-require "active_support/core_ext/kernel/reporting"
-require "active_support/core_ext/load_error"
-require "active_support/core_ext/name_error"
-require "active_support/core_ext/string/starts_ends_with"
-require "active_support/dependencies/interlock"
-require "active_support/inflector"
+require_relative "core_ext/module/aliasing"
+require_relative "core_ext/module/attribute_accessors"
+require_relative "core_ext/module/introspection"
+require_relative "core_ext/module/anonymous"
+require_relative "core_ext/object/blank"
+require_relative "core_ext/kernel/reporting"
+require_relative "core_ext/load_error"
+require_relative "core_ext/name_error"
+require_relative "core_ext/string/starts_ends_with"
+require_relative "dependencies/interlock"
+require_relative "inflector"
module ActiveSupport #:nodoc:
module Dependencies #:nodoc:
extend self
- mattr_accessor :interlock
- self.interlock = Interlock.new
+ mattr_accessor :interlock, default: Interlock.new
# :doc:
@@ -46,46 +47,37 @@ module ActiveSupport #:nodoc:
# :nodoc:
# Should we turn on Ruby warnings on the first load of dependent files?
- mattr_accessor :warnings_on_first_load
- self.warnings_on_first_load = false
+ mattr_accessor :warnings_on_first_load, default: false
# All files ever loaded.
- mattr_accessor :history
- self.history = Set.new
+ mattr_accessor :history, default: Set.new
# All files currently loaded.
- mattr_accessor :loaded
- self.loaded = Set.new
+ mattr_accessor :loaded, default: Set.new
# Stack of files being loaded.
- mattr_accessor :loading
- self.loading = []
+ mattr_accessor :loading, default: []
# Should we load files or require them?
- mattr_accessor :mechanism
- self.mechanism = ENV["NO_RELOAD"] ? :require : :load
+ mattr_accessor :mechanism, default: ENV["NO_RELOAD"] ? :require : :load
# The set of directories from which we may automatically load files. Files
# under these directories will be reloaded on each request in development mode,
# unless the directory also appears in autoload_once_paths.
- mattr_accessor :autoload_paths
- self.autoload_paths = []
+ mattr_accessor :autoload_paths, default: []
# The set of directories from which automatically loaded constants are loaded
# only once. All directories in this set must also be present in +autoload_paths+.
- mattr_accessor :autoload_once_paths
- self.autoload_once_paths = []
+ mattr_accessor :autoload_once_paths, default: []
# An array of qualified constant names that have been loaded. Adding a name
# to this array will cause it to be unloaded the next time Dependencies are
# cleared.
- mattr_accessor :autoloaded_constants
- self.autoloaded_constants = []
+ mattr_accessor :autoloaded_constants, default: []
# An array of constant names that need to be unloaded on every request. Used
# to allow arbitrary constants to be marked for unloading.
- mattr_accessor :explicitly_unloadable_constants
- self.explicitly_unloadable_constants = []
+ mattr_accessor :explicitly_unloadable_constants, default: []
# The WatchStack keeps a stack of the modules being watched as files are
# loaded. If a file in the process of being loaded (parent.rb) triggers the
@@ -175,8 +167,7 @@ module ActiveSupport #:nodoc:
end
# An internal stack used to record which constants are loaded by any block.
- mattr_accessor :constant_watch_stack
- self.constant_watch_stack = WatchStack.new
+ mattr_accessor :constant_watch_stack, default: WatchStack.new
# Module includes this module.
module ModuleConstMissing #:nodoc:
diff --git a/activesupport/lib/active_support/dependencies/autoload.rb b/activesupport/lib/active_support/dependencies/autoload.rb
index 13036d521d..1c3775f5eb 100644
--- a/activesupport/lib/active_support/dependencies/autoload.rb
+++ b/activesupport/lib/active_support/dependencies/autoload.rb
@@ -1,4 +1,6 @@
-require "active_support/inflector/methods"
+# frozen_string_literal: true
+
+require_relative "../inflector/methods"
module ActiveSupport
# Autoload and eager load conveniences for your library.
diff --git a/activesupport/lib/active_support/dependencies/interlock.rb b/activesupport/lib/active_support/dependencies/interlock.rb
index e4e18439c5..4e9595ed42 100644
--- a/activesupport/lib/active_support/dependencies/interlock.rb
+++ b/activesupport/lib/active_support/dependencies/interlock.rb
@@ -1,4 +1,6 @@
-require "active_support/concurrency/share_lock"
+# frozen_string_literal: true
+
+require_relative "../concurrency/share_lock"
module ActiveSupport #:nodoc:
module Dependencies #:nodoc:
diff --git a/activesupport/lib/active_support/deprecation.rb b/activesupport/lib/active_support/deprecation.rb
index 191e582de8..e6550fdcd0 100644
--- a/activesupport/lib/active_support/deprecation.rb
+++ b/activesupport/lib/active_support/deprecation.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "singleton"
module ActiveSupport
@@ -12,12 +14,13 @@ module ActiveSupport
# a circular require warning for active_support/deprecation.rb.
#
# So, we define the constant first, and load dependencies later.
- require "active_support/deprecation/instance_delegator"
- require "active_support/deprecation/behaviors"
- require "active_support/deprecation/reporting"
- require "active_support/deprecation/method_wrappers"
- require "active_support/deprecation/proxy_wrappers"
- require "active_support/core_ext/module/deprecation"
+ require_relative "deprecation/instance_delegator"
+ require_relative "deprecation/behaviors"
+ require_relative "deprecation/reporting"
+ require_relative "deprecation/constant_accessor"
+ require_relative "deprecation/method_wrappers"
+ require_relative "deprecation/proxy_wrappers"
+ require_relative "core_ext/module/deprecation"
include Singleton
include InstanceDelegator
@@ -29,10 +32,10 @@ module ActiveSupport
attr_accessor :deprecation_horizon
# It accepts two parameters on initialization. The first is a version of library
- # and the second is a library name
+ # and the second is a library name.
#
# ActiveSupport::Deprecation.new('2.0', 'MyLibrary')
- def initialize(deprecation_horizon = "5.2", gem_name = "Rails")
+ def initialize(deprecation_horizon = "6.0", gem_name = "Rails")
self.gem_name = gem_name
self.deprecation_horizon = deprecation_horizon
# By default, warnings are not silenced and debugging is off.
diff --git a/activesupport/lib/active_support/deprecation/behaviors.rb b/activesupport/lib/active_support/deprecation/behaviors.rb
index 1d1354c23e..967320bcb9 100644
--- a/activesupport/lib/active_support/deprecation/behaviors.rb
+++ b/activesupport/lib/active_support/deprecation/behaviors.rb
@@ -1,4 +1,6 @@
-require "active_support/notifications"
+# frozen_string_literal: true
+
+require_relative "../notifications"
module ActiveSupport
# Raised when <tt>ActiveSupport::Deprecation::Behavior#behavior</tt> is set with <tt>:raise</tt>.
@@ -9,35 +11,39 @@ module ActiveSupport
class Deprecation
# Default warning behaviors per Rails.env.
DEFAULT_BEHAVIORS = {
- raise: ->(message, callstack) {
+ raise: ->(message, callstack, deprecation_horizon, gem_name) {
e = DeprecationException.new(message)
e.set_backtrace(callstack.map(&:to_s))
raise e
},
- stderr: ->(message, callstack) {
+ stderr: ->(message, callstack, deprecation_horizon, gem_name) {
$stderr.puts(message)
$stderr.puts callstack.join("\n ") if debug
},
- log: ->(message, callstack) {
+ log: ->(message, callstack, deprecation_horizon, gem_name) {
logger =
if defined?(Rails.logger) && Rails.logger
Rails.logger
else
- require "active_support/logger"
+ require_relative "../logger"
ActiveSupport::Logger.new($stderr)
end
logger.warn message
logger.debug callstack.join("\n ") if debug
},
- notify: ->(message, callstack) {
- ActiveSupport::Notifications.instrument("deprecation.rails",
- message: message, callstack: callstack)
+ notify: ->(message, callstack, deprecation_horizon, gem_name) {
+ notification_name = "deprecation.#{gem_name.underscore.tr('/', '_')}"
+ ActiveSupport::Notifications.instrument(notification_name,
+ message: message,
+ callstack: callstack,
+ gem_name: gem_name,
+ deprecation_horizon: deprecation_horizon)
},
- silence: ->(message, callstack) {},
+ silence: ->(message, callstack, deprecation_horizon, gem_name) {},
}
# Behavior module allows to determine how to display deprecation messages.
@@ -83,8 +89,17 @@ module ActiveSupport
# # custom stuff
# }
def behavior=(behavior)
- @behavior = Array(behavior).map { |b| DEFAULT_BEHAVIORS[b] || b }
+ @behavior = Array(behavior).map { |b| DEFAULT_BEHAVIORS[b] || arity_coerce(b) }
end
+
+ private
+ def arity_coerce(behavior)
+ if behavior.arity == 4 || behavior.arity == -1
+ behavior
+ else
+ -> message, callstack, _, _ { behavior.call(message, callstack) }
+ end
+ end
end
end
end
diff --git a/activesupport/lib/active_support/deprecation/constant_accessor.rb b/activesupport/lib/active_support/deprecation/constant_accessor.rb
new file mode 100644
index 0000000000..0dfd96d134
--- /dev/null
+++ b/activesupport/lib/active_support/deprecation/constant_accessor.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require_relative "../inflector/methods"
+
+module ActiveSupport
+ class Deprecation
+ # DeprecatedConstantAccessor transforms a constant into a deprecated one by
+ # hooking +const_missing+.
+ #
+ # It takes the names of an old (deprecated) constant and of a new constant
+ # (both in string form) and optionally a deprecator. The deprecator defaults
+ # to +ActiveSupport::Deprecator+ if none is specified.
+ #
+ # The deprecated constant now returns the same object as the new one rather
+ # than a proxy object, so it can be used transparently in +rescue+ blocks
+ # etc.
+ #
+ # PLANETS = %w(mercury venus earth mars jupiter saturn uranus neptune pluto)
+ #
+ # (In a later update, the original implementation of `PLANETS` has been removed.)
+ #
+ # PLANETS_POST_2006 = %w(mercury venus earth mars jupiter saturn uranus neptune)
+ # include ActiveSupport::Deprecation::DeprecatedConstantAccessor
+ # deprecate_constant 'PLANETS', 'PLANETS_POST_2006'
+ #
+ # PLANETS.map { |planet| planet.capitalize }
+ # # => DEPRECATION WARNING: PLANETS is deprecated! Use PLANETS_POST_2006 instead.
+ # (Backtrace information…)
+ # ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"]
+ module DeprecatedConstantAccessor
+ def self.included(base)
+ extension = Module.new do
+ def const_missing(missing_const_name)
+ if class_variable_defined?(:@@_deprecated_constants)
+ if (replacement = class_variable_get(:@@_deprecated_constants)[missing_const_name.to_s])
+ replacement[:deprecator].warn(replacement[:message] || "#{name}::#{missing_const_name} is deprecated! Use #{replacement[:new]} instead.", caller_locations)
+ return ActiveSupport::Inflector.constantize(replacement[:new].to_s)
+ end
+ end
+ super
+ end
+
+ def deprecate_constant(const_name, new_constant, message: nil, deprecator: ActiveSupport::Deprecation.instance)
+ class_variable_set(:@@_deprecated_constants, {}) unless class_variable_defined?(:@@_deprecated_constants)
+ class_variable_get(:@@_deprecated_constants)[const_name.to_s] = { new: new_constant, message: message, deprecator: deprecator }
+ end
+ end
+ base.singleton_class.prepend extension
+ end
+ end
+ end
+end
diff --git a/activesupport/lib/active_support/deprecation/instance_delegator.rb b/activesupport/lib/active_support/deprecation/instance_delegator.rb
index 6d390f3b37..539357c83e 100644
--- a/activesupport/lib/active_support/deprecation/instance_delegator.rb
+++ b/activesupport/lib/active_support/deprecation/instance_delegator.rb
@@ -1,5 +1,7 @@
-require "active_support/core_ext/kernel/singleton_class"
-require "active_support/core_ext/module/delegation"
+# frozen_string_literal: true
+
+require_relative "../core_ext/kernel/singleton_class"
+require_relative "../core_ext/module/delegation"
module ActiveSupport
class Deprecation
diff --git a/activesupport/lib/active_support/deprecation/method_wrappers.rb b/activesupport/lib/active_support/deprecation/method_wrappers.rb
index 930d71e8d2..8c942ed9a5 100644
--- a/activesupport/lib/active_support/deprecation/method_wrappers.rb
+++ b/activesupport/lib/active_support/deprecation/method_wrappers.rb
@@ -1,5 +1,7 @@
-require "active_support/core_ext/module/aliasing"
-require "active_support/core_ext/array/extract_options"
+# frozen_string_literal: true
+
+require_relative "../core_ext/module/aliasing"
+require_relative "../core_ext/array/extract_options"
module ActiveSupport
class Deprecation
diff --git a/activesupport/lib/active_support/deprecation/proxy_wrappers.rb b/activesupport/lib/active_support/deprecation/proxy_wrappers.rb
index ce39e9a232..1920d75faf 100644
--- a/activesupport/lib/active_support/deprecation/proxy_wrappers.rb
+++ b/activesupport/lib/active_support/deprecation/proxy_wrappers.rb
@@ -1,5 +1,7 @@
-require "active_support/inflector/methods"
-require "active_support/core_ext/regexp"
+# frozen_string_literal: true
+
+require_relative "../inflector/methods"
+require_relative "../core_ext/regexp"
module ActiveSupport
class Deprecation
diff --git a/activesupport/lib/active_support/deprecation/reporting.rb b/activesupport/lib/active_support/deprecation/reporting.rb
index 58c5c50e30..242e21b782 100644
--- a/activesupport/lib/active_support/deprecation/reporting.rb
+++ b/activesupport/lib/active_support/deprecation/reporting.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rbconfig"
module ActiveSupport
@@ -18,7 +20,7 @@ module ActiveSupport
callstack ||= caller_locations(2)
deprecation_message(callstack, message).tap do |m|
- behavior.each { |b| b.call(m, callstack) }
+ behavior.each { |b| b.call(m, callstack, deprecation_horizon, gem_name) }
end
end
@@ -102,7 +104,7 @@ module ActiveSupport
end
end
- RAILS_GEM_ROOT = File.expand_path("../../../../..", __FILE__) + "/"
+ RAILS_GEM_ROOT = File.expand_path("../../../..", __dir__)
def ignored_callstack(path)
path.start_with?(RAILS_GEM_ROOT) || path.start_with?(RbConfig::CONFIG["rubylibdir"])
diff --git a/activesupport/lib/active_support/descendants_tracker.rb b/activesupport/lib/active_support/descendants_tracker.rb
index 27861e01d0..a4cee788b6 100644
--- a/activesupport/lib/active_support/descendants_tracker.rb
+++ b/activesupport/lib/active_support/descendants_tracker.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActiveSupport
# This module provides an internal implementation to track descendants
# which is faster than iterating through ObjectSpace.
diff --git a/activesupport/lib/active_support/duration.rb b/activesupport/lib/active_support/duration.rb
index d26bbac511..068adcea24 100644
--- a/activesupport/lib/active_support/duration.rb
+++ b/activesupport/lib/active_support/duration.rb
@@ -1,7 +1,10 @@
-require "active_support/core_ext/array/conversions"
-require "active_support/core_ext/object/acts_like"
-require "active_support/core_ext/string/filters"
-require "active_support/deprecation"
+# frozen_string_literal: true
+
+require_relative "core_ext/array/conversions"
+require_relative "core_ext/module/delegation"
+require_relative "core_ext/object/acts_like"
+require_relative "core_ext/string/filters"
+require_relative "deprecation"
module ActiveSupport
# Provides accurate date and time measurements using Date#advance and
@@ -9,6 +12,95 @@ module ActiveSupport
#
# 1.month.ago # equivalent to Time.now.advance(months: -1)
class Duration
+ class Scalar < Numeric #:nodoc:
+ attr_reader :value
+ delegate :to_i, :to_f, :to_s, to: :value
+
+ def initialize(value)
+ @value = value
+ end
+
+ def coerce(other)
+ [Scalar.new(other), self]
+ end
+
+ def -@
+ Scalar.new(-value)
+ end
+
+ def <=>(other)
+ if Scalar === other || Duration === other
+ value <=> other.value
+ elsif Numeric === other
+ value <=> other
+ else
+ nil
+ end
+ end
+
+ def +(other)
+ if Duration === other
+ seconds = value + other.parts[:seconds]
+ new_parts = other.parts.merge(seconds: seconds)
+ new_value = value + other.value
+
+ Duration.new(new_value, new_parts)
+ else
+ calculate(:+, other)
+ end
+ end
+
+ def -(other)
+ if Duration === other
+ seconds = value - other.parts[:seconds]
+ new_parts = other.parts.map { |part, other_value| [part, -other_value] }.to_h
+ new_parts = new_parts.merge(seconds: seconds)
+ new_value = value - other.value
+
+ Duration.new(new_value, new_parts)
+ else
+ calculate(:-, other)
+ end
+ end
+
+ def *(other)
+ if Duration === other
+ new_parts = other.parts.map { |part, other_value| [part, value * other_value] }.to_h
+ new_value = value * other.value
+
+ Duration.new(new_value, new_parts)
+ else
+ calculate(:*, other)
+ end
+ end
+
+ def /(other)
+ if Duration === other
+ new_parts = other.parts.map { |part, other_value| [part, value / other_value] }.to_h
+ new_value = new_parts.inject(0) { |total, (part, value)| total + value * Duration::PARTS_IN_SECONDS[part] }
+
+ Duration.new(new_value, new_parts)
+ else
+ calculate(:/, other)
+ end
+ end
+
+ private
+ def calculate(op, other)
+ if Scalar === other
+ Scalar.new(value.public_send(op, other.value))
+ elsif Numeric === other
+ Scalar.new(value.public_send(op, other))
+ else
+ raise_type_error(other)
+ end
+ end
+
+ def raise_type_error(other)
+ raise TypeError, "no implicit conversion of #{other.class} into #{self.class}"
+ end
+ end
+
SECONDS_PER_MINUTE = 60
SECONDS_PER_HOUR = 3600
SECONDS_PER_DAY = 86400
@@ -91,12 +183,11 @@ module ActiveSupport
end
def coerce(other) #:nodoc:
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
- Implicit coercion of ActiveSupport::Duration to a Numeric
- is deprecated and will raise a TypeError in Rails 5.2.
- MSG
-
- [other, value]
+ if Scalar === other
+ [other, self]
+ else
+ [Scalar.new(other), self]
+ end
end
# Compares one Duration with another or a Numeric to this Duration.
@@ -132,19 +223,23 @@ module ActiveSupport
# Multiplies this Duration by a Numeric and returns a new Duration.
def *(other)
- if Numeric === other
+ if Scalar === other || Duration === other
+ Duration.new(value * other.value, parts.map { |type, number| [type, number * other.value] })
+ elsif Numeric === other
Duration.new(value * other, parts.map { |type, number| [type, number * other] })
else
- value * other
+ raise_type_error(other)
end
end
# Divides this Duration by a Numeric and returns a new Duration.
def /(other)
- if Numeric === other
+ if Scalar === other || Duration === other
+ Duration.new(value / other.value, parts.map { |type, number| [type, number / other.value] })
+ elsif Numeric === other
Duration.new(value / other, parts.map { |type, number| [type, number / other] })
else
- value / other
+ raise_type_error(other)
end
end
@@ -241,10 +336,6 @@ module ActiveSupport
to_i
end
- def respond_to_missing?(method, include_private = false) #:nodoc:
- @value.respond_to?(method, include_private)
- end
-
# Build ISO 8601 Duration string for this duration.
# The +precision+ parameter can be used to limit seconds' precision of duration.
def iso8601(precision: nil)
@@ -271,8 +362,16 @@ module ActiveSupport
end
end
+ def respond_to_missing?(method, _)
+ value.respond_to?(method)
+ end
+
def method_missing(method, *args, &block)
- value.send(method, *args, &block)
+ value.public_send(method, *args, &block)
+ end
+
+ def raise_type_error(other)
+ raise TypeError, "no implicit conversion of #{other.class} into #{self.class}"
end
end
end
diff --git a/activesupport/lib/active_support/duration/iso8601_parser.rb b/activesupport/lib/active_support/duration/iso8601_parser.rb
index e96cb8e883..14b2c27d82 100644
--- a/activesupport/lib/active_support/duration/iso8601_parser.rb
+++ b/activesupport/lib/active_support/duration/iso8601_parser.rb
@@ -1,5 +1,7 @@
+# frozen_string_literal: true
+
require "strscan"
-require "active_support/core_ext/regexp"
+require_relative "../core_ext/regexp"
module ActiveSupport
class Duration
diff --git a/activesupport/lib/active_support/duration/iso8601_serializer.rb b/activesupport/lib/active_support/duration/iso8601_serializer.rb
index e5d458b3ab..985eac113f 100644
--- a/activesupport/lib/active_support/duration/iso8601_serializer.rb
+++ b/activesupport/lib/active_support/duration/iso8601_serializer.rb
@@ -1,5 +1,7 @@
-require "active_support/core_ext/object/blank"
-require "active_support/core_ext/hash/transform_values"
+# frozen_string_literal: true
+
+require_relative "../core_ext/object/blank"
+require_relative "../core_ext/hash/transform_values"
module ActiveSupport
class Duration
@@ -15,12 +17,12 @@ module ActiveSupport
parts, sign = normalize
return "PT0S".freeze if parts.empty?
- output = "P"
+ output = "P".dup
output << "#{parts[:years]}Y" if parts.key?(:years)
output << "#{parts[:months]}M" if parts.key?(:months)
output << "#{parts[:weeks]}W" if parts.key?(:weeks)
output << "#{parts[:days]}D" if parts.key?(:days)
- time = ""
+ time = "".dup
time << "#{parts[:hours]}H" if parts.key?(:hours)
time << "#{parts[:minutes]}M" if parts.key?(:minutes)
if parts.key?(:seconds)
diff --git a/activesupport/lib/active_support/evented_file_update_checker.rb b/activesupport/lib/active_support/evented_file_update_checker.rb
index 8e0dc71dca..97e982eb05 100644
--- a/activesupport/lib/active_support/evented_file_update_checker.rb
+++ b/activesupport/lib/active_support/evented_file_update_checker.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "set"
require "pathname"
require "concurrent/atomic/atomic_boolean"
@@ -125,6 +127,11 @@ module ActiveSupport
dtw.compact!
dtw.uniq!
+ normalized_gem_paths = Gem.path.map { |path| File.join path, "" }
+ dtw = dtw.reject do |path|
+ normalized_gem_paths.any? { |gem_path| path.to_s.start_with?(gem_path) }
+ end
+
@ph.filter_out_descendants(dtw)
end
diff --git a/activesupport/lib/active_support/execution_wrapper.rb b/activesupport/lib/active_support/execution_wrapper.rb
index ca88e7876b..fd87d84795 100644
--- a/activesupport/lib/active_support/execution_wrapper.rb
+++ b/activesupport/lib/active_support/execution_wrapper.rb
@@ -1,4 +1,6 @@
-require "active_support/callbacks"
+# frozen_string_literal: true
+
+require_relative "callbacks"
module ActiveSupport
class ExecutionWrapper
diff --git a/activesupport/lib/active_support/executor.rb b/activesupport/lib/active_support/executor.rb
index a6400cae0a..e6487ba69d 100644
--- a/activesupport/lib/active_support/executor.rb
+++ b/activesupport/lib/active_support/executor.rb
@@ -1,4 +1,6 @@
-require "active_support/execution_wrapper"
+# frozen_string_literal: true
+
+require_relative "execution_wrapper"
module ActiveSupport
class Executor < ExecutionWrapper
diff --git a/activesupport/lib/active_support/file_update_checker.rb b/activesupport/lib/active_support/file_update_checker.rb
index 2b5e3c1350..bcf7b9de64 100644
--- a/activesupport/lib/active_support/file_update_checker.rb
+++ b/activesupport/lib/active_support/file_update_checker.rb
@@ -1,4 +1,6 @@
-require "active_support/core_ext/time/calculations"
+# frozen_string_literal: true
+
+require_relative "core_ext/time/calculations"
module ActiveSupport
# FileUpdateChecker specifies the API used by Rails to watch files
diff --git a/activesupport/lib/active_support/gem_version.rb b/activesupport/lib/active_support/gem_version.rb
index a641b96c57..2a7ef2f820 100644
--- a/activesupport/lib/active_support/gem_version.rb
+++ b/activesupport/lib/active_support/gem_version.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActiveSupport
# Returns the version of the currently loaded Active Support as a <tt>Gem::Version</tt>.
def self.gem_version
@@ -6,9 +8,9 @@ module ActiveSupport
module VERSION
MAJOR = 5
- MINOR = 1
+ MINOR = 2
TINY = 0
- PRE = "beta1"
+ PRE = "alpha"
STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
end
diff --git a/activesupport/lib/active_support/gzip.rb b/activesupport/lib/active_support/gzip.rb
index 95a86889ec..7ffa6d90a2 100644
--- a/activesupport/lib/active_support/gzip.rb
+++ b/activesupport/lib/active_support/gzip.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "zlib"
require "stringio"
diff --git a/activesupport/lib/active_support/hash_with_indifferent_access.rb b/activesupport/lib/active_support/hash_with_indifferent_access.rb
index 29ca6fbae8..4ce5b4534e 100644
--- a/activesupport/lib/active_support/hash_with_indifferent_access.rb
+++ b/activesupport/lib/active_support/hash_with_indifferent_access.rb
@@ -1,5 +1,7 @@
-require "active_support/core_ext/hash/keys"
-require "active_support/core_ext/hash/reverse_merge"
+# frozen_string_literal: true
+
+require_relative "core_ext/hash/keys"
+require_relative "core_ext/hash/reverse_merge"
module ActiveSupport
# Implements a hash where keys <tt>:foo</tt> and <tt>"foo"</tt> are considered
@@ -195,6 +197,19 @@ module ActiveSupport
indices.collect { |key| self[convert_key(key)] }
end
+ # Returns an array of the values at the specified indices, but also
+ # raises an exception when one of the keys can't be found.
+ #
+ # hash = ActiveSupport::HashWithIndifferentAccess.new
+ # hash[:a] = 'x'
+ # hash[:b] = 'y'
+ # hash.fetch_values('a', 'b') # => ["x", "y"]
+ # hash.fetch_values('a', 'c') { |key| 'z' } # => ["x", "z"]
+ # hash.fetch_values('a', 'c') # => KeyError: key not found: "c"
+ def fetch_values(*indices, &block)
+ indices.collect { |key| fetch(key, &block) }
+ end if Hash.method_defined?(:fetch_values)
+
# Returns a shallow copy of the hash.
#
# hash = ActiveSupport::HashWithIndifferentAccess.new({ a: { b: 'b' } })
@@ -225,11 +240,13 @@ module ActiveSupport
def reverse_merge(other_hash)
super(self.class.new(other_hash))
end
+ alias_method :with_defaults, :reverse_merge
# Same semantics as +reverse_merge+ but modifies the receiver in-place.
def reverse_merge!(other_hash)
super(self.class.new(other_hash))
end
+ alias_method :with_defaults!, :reverse_merge!
# Replaces the contents of this hash with other_hash.
#
diff --git a/activesupport/lib/active_support/i18n.rb b/activesupport/lib/active_support/i18n.rb
index f0408f429c..80f1475630 100644
--- a/activesupport/lib/active_support/i18n.rb
+++ b/activesupport/lib/active_support/i18n.rb
@@ -1,13 +1,15 @@
-require "active_support/core_ext/hash/deep_merge"
-require "active_support/core_ext/hash/except"
-require "active_support/core_ext/hash/slice"
+# frozen_string_literal: true
+
+require_relative "core_ext/hash/deep_merge"
+require_relative "core_ext/hash/except"
+require_relative "core_ext/hash/slice"
begin
require "i18n"
rescue LoadError => e
$stderr.puts "The i18n gem is not available. Please add it to your Gemfile and run bundle install"
raise e
end
-require "active_support/lazy_load_hooks"
+require_relative "lazy_load_hooks"
ActiveSupport.run_load_hooks(:i18n)
-I18n.load_path << "#{File.dirname(__FILE__)}/locale/en.yml"
+I18n.load_path << File.expand_path("locale/en.yml", __dir__)
diff --git a/activesupport/lib/active_support/i18n_railtie.rb b/activesupport/lib/active_support/i18n_railtie.rb
index b749913ee9..369aecff69 100644
--- a/activesupport/lib/active_support/i18n_railtie.rb
+++ b/activesupport/lib/active_support/i18n_railtie.rb
@@ -1,6 +1,8 @@
+# frozen_string_literal: true
+
require "active_support"
-require "active_support/file_update_checker"
-require "active_support/core_ext/array/wrap"
+require_relative "file_update_checker"
+require_relative "core_ext/array/wrap"
# :enddoc:
@@ -42,7 +44,7 @@ module I18n
case setting
when :railties_load_path
reloadable_paths = value
- app.config.i18n.load_path.unshift(*value.map(&:existent).flatten)
+ app.config.i18n.load_path.unshift(*value.flat_map(&:existent))
when :load_path
I18n.load_path += value
else
@@ -58,7 +60,7 @@ module I18n
directories = watched_dirs_with_extensions(reloadable_paths)
reloader = app.config.file_watcher.new(I18n.load_path.dup, directories) do
I18n.load_path.keep_if { |p| File.exist?(p) }
- I18n.load_path |= reloadable_paths.map(&:existent).flatten
+ I18n.load_path |= reloadable_paths.flat_map(&:existent)
I18n.reload!
end
@@ -66,10 +68,6 @@ module I18n
app.reloaders << reloader
app.reloader.to_run do
reloader.execute_if_updated { require_unload_lock! }
- # TODO: remove the following line as soon as the return value of
- # callbacks is ignored, that is, returning `false` does not
- # display a deprecation warning or halts the callback chain.
- true
end
reloader.execute
diff --git a/activesupport/lib/active_support/inflections.rb b/activesupport/lib/active_support/inflections.rb
index afa7d1f325..e8e1657111 100644
--- a/activesupport/lib/active_support/inflections.rb
+++ b/activesupport/lib/active_support/inflections.rb
@@ -1,4 +1,6 @@
-require "active_support/inflector/inflections"
+# frozen_string_literal: true
+
+require_relative "inflector/inflections"
#--
# Defines the standard inflection rules. These are the starting point for
diff --git a/activesupport/lib/active_support/inflector.rb b/activesupport/lib/active_support/inflector.rb
index 48631b16a8..a6adb15a18 100644
--- a/activesupport/lib/active_support/inflector.rb
+++ b/activesupport/lib/active_support/inflector.rb
@@ -1,7 +1,9 @@
+# frozen_string_literal: true
+
# in case active_support/inflector is required without the rest of active_support
-require "active_support/inflector/inflections"
-require "active_support/inflector/transliterate"
-require "active_support/inflector/methods"
+require_relative "inflector/inflections"
+require_relative "inflector/transliterate"
+require_relative "inflector/methods"
-require "active_support/inflections"
-require "active_support/core_ext/string/inflections"
+require_relative "inflections"
+require_relative "core_ext/string/inflections"
diff --git a/activesupport/lib/active_support/inflector/inflections.rb b/activesupport/lib/active_support/inflector/inflections.rb
index c47a2e34e1..36dfbc5f42 100644
--- a/activesupport/lib/active_support/inflector/inflections.rb
+++ b/activesupport/lib/active_support/inflector/inflections.rb
@@ -1,7 +1,9 @@
+# frozen_string_literal: true
+
require "concurrent/map"
-require "active_support/core_ext/array/prepend_and_append"
-require "active_support/core_ext/regexp"
-require "active_support/i18n"
+require_relative "../core_ext/array/prepend_and_append"
+require_relative "../core_ext/regexp"
+require_relative "../i18n"
module ActiveSupport
module Inflector
diff --git a/activesupport/lib/active_support/inflector/methods.rb b/activesupport/lib/active_support/inflector/methods.rb
index 8ccb735c6d..9398ed60a4 100644
--- a/activesupport/lib/active_support/inflector/methods.rb
+++ b/activesupport/lib/active_support/inflector/methods.rb
@@ -1,5 +1,7 @@
-require "active_support/inflections"
-require "active_support/core_ext/regexp"
+# frozen_string_literal: true
+
+require_relative "../inflections"
+require_relative "../core_ext/regexp"
module ActiveSupport
# The Inflector transforms words from singular to plural, class names to table
@@ -28,7 +30,7 @@ module ActiveSupport
# pluralize('CamelOctopus') # => "CamelOctopi"
# pluralize('ley', :es) # => "leyes"
def pluralize(word, locale = :en)
- apply_inflections(word, inflections(locale).plurals)
+ apply_inflections(word, inflections(locale).plurals, locale)
end
# The reverse of #pluralize, returns the singular form of a word in a
@@ -45,7 +47,7 @@ module ActiveSupport
# singularize('CamelOctopi') # => "CamelOctopus"
# singularize('leyes', :es) # => "ley"
def singularize(word, locale = :en)
- apply_inflections(word, inflections(locale).singulars)
+ apply_inflections(word, inflections(locale).singulars, locale)
end
# Converts strings to UpperCamelCase.
@@ -108,33 +110,38 @@ module ActiveSupport
# * Replaces underscores with spaces, if any.
# * Downcases all words except acronyms.
# * Capitalizes the first word.
- #
# The capitalization of the first word can be turned off by setting the
# +:capitalize+ option to false (default is true).
#
- # humanize('employee_salary') # => "Employee salary"
- # humanize('author_id') # => "Author"
- # humanize('author_id', capitalize: false) # => "author"
- # humanize('_id') # => "Id"
+ # The trailing '_id' can be kept and capitalized by setting the
+ # optional parameter +keep_id_suffix+ to true (default is false).
+ #
+ # humanize('employee_salary') # => "Employee salary"
+ # humanize('author_id') # => "Author"
+ # humanize('author_id', capitalize: false) # => "author"
+ # humanize('_id') # => "Id"
+ # humanize('author_id', keep_id_suffix: true) # => "Author Id"
#
# If "SSL" was defined to be an acronym:
#
# humanize('ssl_error') # => "SSL error"
#
- def humanize(lower_case_and_underscored_word, options = {})
+ def humanize(lower_case_and_underscored_word, capitalize: true, keep_id_suffix: false)
result = lower_case_and_underscored_word.to_s.dup
inflections.humans.each { |(rule, replacement)| break if result.sub!(rule, replacement) }
result.sub!(/\A_+/, "".freeze)
- result.sub!(/_id\z/, "".freeze)
+ unless keep_id_suffix
+ result.sub!(/_id\z/, "".freeze)
+ end
result.tr!("_".freeze, " ".freeze)
result.gsub!(/([a-z\d]*)/i) do |match|
"#{inflections.acronyms[match] || match.downcase}"
end
- if options.fetch(:capitalize, true)
+ if capitalize
result.sub!(/\A\w/) { |match| match.upcase }
end
@@ -154,14 +161,21 @@ module ActiveSupport
# create a nicer looking title. +titleize+ is meant for creating pretty
# output. It is not used in the Rails internals.
#
+ # The trailing '_id','Id'.. can be kept and capitalized by setting the
+ # optional parameter +keep_id_suffix+ to true.
+ # By default, this parameter is false.
+ #
# +titleize+ is also aliased as +titlecase+.
#
- # titleize('man from the boondocks') # => "Man From The Boondocks"
- # titleize('x-men: the last stand') # => "X Men: The Last Stand"
- # titleize('TheManWithoutAPast') # => "The Man Without A Past"
- # titleize('raiders_of_the_lost_ark') # => "Raiders Of The Lost Ark"
- def titleize(word)
- humanize(underscore(word)).gsub(/\b(?<!['’`])[a-z]/) { |match| match.capitalize }
+ # titleize('man from the boondocks') # => "Man From The Boondocks"
+ # titleize('x-men: the last stand') # => "X Men: The Last Stand"
+ # titleize('TheManWithoutAPast') # => "The Man Without A Past"
+ # titleize('raiders_of_the_lost_ark') # => "Raiders Of The Lost Ark"
+ # titleize('string_ending_with_id', keep_id_suffix: true) # => "String Ending With Id"
+ def titleize(word, keep_id_suffix: false)
+ humanize(underscore(word), keep_id_suffix: keep_id_suffix).gsub(/\b(?<!\w['’`])[a-z]/) do |match|
+ match.capitalize
+ end
end
# Creates the name of a table like Rails does for models to table names.
@@ -375,12 +389,15 @@ module ActiveSupport
# Applies inflection rules for +singularize+ and +pluralize+.
#
- # apply_inflections('post', inflections.plurals) # => "posts"
- # apply_inflections('posts', inflections.singulars) # => "post"
- def apply_inflections(word, rules)
+ # If passed an optional +locale+ parameter, the uncountables will be
+ # found for that locale.
+ #
+ # apply_inflections('post', inflections.plurals, :en) # => "posts"
+ # apply_inflections('posts', inflections.singulars, :en) # => "post"
+ def apply_inflections(word, rules, locale = :en)
result = word.to_s.dup
- if word.empty? || inflections.uncountables.uncountable?(result)
+ if word.empty? || inflections(locale).uncountables.uncountable?(result)
result
else
rules.each { |(rule, replacement)| break if result.sub!(rule, replacement) }
diff --git a/activesupport/lib/active_support/inflector/transliterate.rb b/activesupport/lib/active_support/inflector/transliterate.rb
index de6dd2720b..aa7b21734e 100644
--- a/activesupport/lib/active_support/inflector/transliterate.rb
+++ b/activesupport/lib/active_support/inflector/transliterate.rb
@@ -1,5 +1,7 @@
-require "active_support/core_ext/string/multibyte"
-require "active_support/i18n"
+# frozen_string_literal: true
+
+require_relative "../core_ext/string/multibyte"
+require_relative "../i18n"
module ActiveSupport
module Inflector
@@ -59,9 +61,10 @@ module ActiveSupport
def transliterate(string, replacement = "?".freeze)
raise ArgumentError, "Can only transliterate strings. Received #{string.class.name}" unless string.is_a?(String)
- I18n.transliterate(ActiveSupport::Multibyte::Unicode.normalize(
- ActiveSupport::Multibyte::Unicode.tidy_bytes(string), :c),
- replacement: replacement)
+ I18n.transliterate(
+ ActiveSupport::Multibyte::Unicode.normalize(
+ ActiveSupport::Multibyte::Unicode.tidy_bytes(string), :c),
+ replacement: replacement)
end
# Replaces special characters in a string so that it may be used as part of
diff --git a/activesupport/lib/active_support/json.rb b/activesupport/lib/active_support/json.rb
index da938d1555..b5672025fb 100644
--- a/activesupport/lib/active_support/json.rb
+++ b/activesupport/lib/active_support/json.rb
@@ -1,2 +1,4 @@
-require "active_support/json/decoding"
-require "active_support/json/encoding"
+# frozen_string_literal: true
+
+require_relative "json/decoding"
+require_relative "json/encoding"
diff --git a/activesupport/lib/active_support/json/decoding.rb b/activesupport/lib/active_support/json/decoding.rb
index f487fa0c65..caa4082dde 100644
--- a/activesupport/lib/active_support/json/decoding.rb
+++ b/activesupport/lib/active_support/json/decoding.rb
@@ -1,5 +1,7 @@
-require "active_support/core_ext/module/attribute_accessors"
-require "active_support/core_ext/module/delegation"
+# frozen_string_literal: true
+
+require_relative "../core_ext/module/attribute_accessors"
+require_relative "../core_ext/module/delegation"
require "json"
module ActiveSupport
diff --git a/activesupport/lib/active_support/json/encoding.rb b/activesupport/lib/active_support/json/encoding.rb
index defaf3f395..4016d13364 100644
--- a/activesupport/lib/active_support/json/encoding.rb
+++ b/activesupport/lib/active_support/json/encoding.rb
@@ -1,5 +1,7 @@
-require "active_support/core_ext/object/json"
-require "active_support/core_ext/module/delegation"
+# frozen_string_literal: true
+
+require_relative "../core_ext/object/json"
+require_relative "../core_ext/module/delegation"
module ActiveSupport
class << self
diff --git a/activesupport/lib/active_support/key_generator.rb b/activesupport/lib/active_support/key_generator.rb
index 23ab804eb1..31de37b400 100644
--- a/activesupport/lib/active_support/key_generator.rb
+++ b/activesupport/lib/active_support/key_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "concurrent/map"
require "openssl"
diff --git a/activesupport/lib/active_support/lazy_load_hooks.rb b/activesupport/lib/active_support/lazy_load_hooks.rb
index 720ed47331..c23b319046 100644
--- a/activesupport/lib/active_support/lazy_load_hooks.rb
+++ b/activesupport/lib/active_support/lazy_load_hooks.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActiveSupport
# lazy_load_hooks allows Rails to lazily load a lot of components and thus
# making the app boot faster. Because of this feature now there is no need to
diff --git a/activesupport/lib/active_support/log_subscriber.rb b/activesupport/lib/active_support/log_subscriber.rb
index e2c4f33565..05a11221bf 100644
--- a/activesupport/lib/active_support/log_subscriber.rb
+++ b/activesupport/lib/active_support/log_subscriber.rb
@@ -1,6 +1,8 @@
-require "active_support/core_ext/module/attribute_accessors"
-require "active_support/core_ext/class/attribute"
-require "active_support/subscriber"
+# frozen_string_literal: true
+
+require_relative "core_ext/module/attribute_accessors"
+require_relative "core_ext/class/attribute"
+require_relative "subscriber"
module ActiveSupport
# ActiveSupport::LogSubscriber is an object set to consume
@@ -49,8 +51,7 @@ module ActiveSupport
CYAN = "\e[36m"
WHITE = "\e[37m"
- mattr_accessor :colorize_logging
- self.colorize_logging = true
+ mattr_accessor :colorize_logging, default: true
class << self
def logger
@@ -81,8 +82,10 @@ module ActiveSupport
def finish(name, id, payload)
super if logger
- rescue Exception => e
- logger.error "Could not log #{name.inspect} event. #{e.class}: #{e.message} #{e.backtrace}"
+ rescue => e
+ if logger
+ logger.error "Could not log #{name.inspect} event. #{e.class}: #{e.message} #{e.backtrace}"
+ end
end
private
diff --git a/activesupport/lib/active_support/log_subscriber/test_helper.rb b/activesupport/lib/active_support/log_subscriber/test_helper.rb
index 953ee77c2a..5b2abfc57c 100644
--- a/activesupport/lib/active_support/log_subscriber/test_helper.rb
+++ b/activesupport/lib/active_support/log_subscriber/test_helper.rb
@@ -1,6 +1,8 @@
-require "active_support/log_subscriber"
-require "active_support/logger"
-require "active_support/notifications"
+# frozen_string_literal: true
+
+require_relative "../log_subscriber"
+require_relative "../logger"
+require_relative "../notifications"
module ActiveSupport
class LogSubscriber
diff --git a/activesupport/lib/active_support/logger.rb b/activesupport/lib/active_support/logger.rb
index ea09d7d2df..3397ac4c9f 100644
--- a/activesupport/lib/active_support/logger.rb
+++ b/activesupport/lib/active_support/logger.rb
@@ -1,5 +1,7 @@
-require "active_support/logger_silence"
-require "active_support/logger_thread_safe_level"
+# frozen_string_literal: true
+
+require_relative "logger_silence"
+require_relative "logger_thread_safe_level"
require "logger"
module ActiveSupport
diff --git a/activesupport/lib/active_support/logger_silence.rb b/activesupport/lib/active_support/logger_silence.rb
index 632994cf50..693c7a1947 100644
--- a/activesupport/lib/active_support/logger_silence.rb
+++ b/activesupport/lib/active_support/logger_silence.rb
@@ -1,13 +1,14 @@
-require "active_support/concern"
-require "active_support/core_ext/module/attribute_accessors"
+# frozen_string_literal: true
+
+require_relative "concern"
+require_relative "core_ext/module/attribute_accessors"
require "concurrent"
module LoggerSilence
extend ActiveSupport::Concern
included do
- cattr_accessor :silencer
- self.silencer = true
+ cattr_accessor :silencer, default: true
end
# Silences the logger for the duration of the block.
diff --git a/activesupport/lib/active_support/logger_thread_safe_level.rb b/activesupport/lib/active_support/logger_thread_safe_level.rb
index 7fb175dea6..3c7f53d92c 100644
--- a/activesupport/lib/active_support/logger_thread_safe_level.rb
+++ b/activesupport/lib/active_support/logger_thread_safe_level.rb
@@ -1,4 +1,6 @@
-require "active_support/concern"
+# frozen_string_literal: true
+
+require_relative "concern"
module ActiveSupport
module LoggerThreadSafeLevel # :nodoc:
diff --git a/activesupport/lib/active_support/message_encryptor.rb b/activesupport/lib/active_support/message_encryptor.rb
index 69109d2005..d5db2920b9 100644
--- a/activesupport/lib/active_support/message_encryptor.rb
+++ b/activesupport/lib/active_support/message_encryptor.rb
@@ -1,7 +1,9 @@
+# frozen_string_literal: true
+
require "openssl"
require "base64"
-require "active_support/core_ext/array/extract_options"
-require "active_support/message_verifier"
+require_relative "core_ext/array/extract_options"
+require_relative "message_verifier"
module ActiveSupport
# MessageEncryptor is a simple way to encrypt values which get stored
@@ -13,13 +15,24 @@ module ActiveSupport
# This can be used in situations similar to the <tt>MessageVerifier</tt>, but
# where you don't want users to be able to determine the value of the payload.
#
- # salt = SecureRandom.random_bytes(64)
- # key = ActiveSupport::KeyGenerator.new('password').generate_key(salt, 32) # => "\x89\xE0\x156\xAC..."
- # crypt = ActiveSupport::MessageEncryptor.new(key) # => #<ActiveSupport::MessageEncryptor ...>
- # encrypted_data = crypt.encrypt_and_sign('my secret data') # => "NlFBTTMwOUV5UlA1QlNEN2xkY2d6eThYWWh..."
- # crypt.decrypt_and_verify(encrypted_data) # => "my secret data"
+ # len = ActiveSupport::MessageEncryptor.key_len
+ # salt = SecureRandom.random_bytes(len)
+ # key = ActiveSupport::KeyGenerator.new('password').generate_key(salt, len) # => "\x89\xE0\x156\xAC..."
+ # crypt = ActiveSupport::MessageEncryptor.new(key) # => #<ActiveSupport::MessageEncryptor ...>
+ # encrypted_data = crypt.encrypt_and_sign('my secret data') # => "NlFBTTMwOUV5UlA1QlNEN2xkY2d6eThYWWh..."
+ # crypt.decrypt_and_verify(encrypted_data) # => "my secret data"
class MessageEncryptor
- DEFAULT_CIPHER = "aes-256-cbc"
+ class << self
+ attr_accessor :use_authenticated_message_encryption #:nodoc:
+
+ def default_cipher #:nodoc:
+ if use_authenticated_message_encryption
+ "aes-256-gcm"
+ else
+ "aes-256-cbc"
+ end
+ end
+ end
module NullSerializer #:nodoc:
def self.load(value)
@@ -45,14 +58,19 @@ module ActiveSupport
OpenSSLCipherError = OpenSSL::Cipher::CipherError
# Initialize a new MessageEncryptor. +secret+ must be at least as long as
- # the cipher key size. For the default 'aes-256-cbc' cipher, this is 256
+ # the cipher key size. For the default 'aes-256-gcm' cipher, this is 256
# bits. If you are using a user-entered secret, you can generate a suitable
# key by using <tt>ActiveSupport::KeyGenerator</tt> or a similar key
# derivation function.
#
+ # First additional parameter is used as the signature key for +MessageVerifier+.
+ # This allows you to specify keys to encrypt and sign data.
+ #
+ # ActiveSupport::MessageEncryptor.new('secret', 'signature_secret')
+ #
# Options:
# * <tt>:cipher</tt> - Cipher to use. Can be any cipher returned by
- # <tt>OpenSSL::Cipher.ciphers</tt>. Default is 'aes-256-cbc'.
+ # <tt>OpenSSL::Cipher.ciphers</tt>. Default is 'aes-256-gcm'.
# * <tt>:digest</tt> - String of digest to use for signing. Default is
# +SHA1+. Ignored when using an AEAD cipher like 'aes-256-gcm'.
# * <tt>:serializer</tt> - Object serializer to use. Default is +Marshal+.
@@ -61,7 +79,7 @@ module ActiveSupport
sign_secret = signature_key_or_options.first
@secret = secret
@sign_secret = sign_secret
- @cipher = options[:cipher] || DEFAULT_CIPHER
+ @cipher = options[:cipher] || self.class.default_cipher
@digest = options[:digest] || "SHA1" unless aead_mode?
@verifier = resolve_verifier
@serializer = options[:serializer] || Marshal
@@ -80,7 +98,7 @@ module ActiveSupport
end
# Given a cipher, returns the key length of the cipher to help generate the key of desired size
- def self.key_len(cipher = DEFAULT_CIPHER)
+ def self.key_len(cipher = default_cipher)
OpenSSL::Cipher.new(cipher).key_len
end
@@ -99,7 +117,7 @@ module ActiveSupport
encrypted_data << cipher.final
blob = "#{::Base64.strict_encode64 encrypted_data}--#{::Base64.strict_encode64 iv}"
- blob << "--#{::Base64.strict_encode64 cipher.auth_tag}" if aead_mode?
+ blob = "#{blob}--#{::Base64.strict_encode64 cipher.auth_tag}" if aead_mode?
blob
end
@@ -110,7 +128,7 @@ module ActiveSupport
# Currently the OpenSSL bindings do not raise an error if auth_tag is
# truncated, which would allow an attacker to easily forge it. See
# https://github.com/ruby/openssl/issues/63
- raise InvalidMessage if aead_mode? && auth_tag.bytes.length != 16
+ raise InvalidMessage if aead_mode? && (auth_tag.nil? || auth_tag.bytes.length != 16)
cipher.decrypt
cipher.key = @secret
diff --git a/activesupport/lib/active_support/message_verifier.rb b/activesupport/lib/active_support/message_verifier.rb
index 8419e858c6..b889f31f7a 100644
--- a/activesupport/lib/active_support/message_verifier.rb
+++ b/activesupport/lib/active_support/message_verifier.rb
@@ -1,6 +1,8 @@
+# frozen_string_literal: true
+
require "base64"
-require "active_support/core_ext/object/blank"
-require "active_support/security_utils"
+require_relative "core_ext/object/blank"
+require_relative "security_utils"
module ActiveSupport
# +MessageVerifier+ makes it easy to generate and verify messages which are
diff --git a/activesupport/lib/active_support/multibyte.rb b/activesupport/lib/active_support/multibyte.rb
index f7c7befee0..3fe3a05e93 100644
--- a/activesupport/lib/active_support/multibyte.rb
+++ b/activesupport/lib/active_support/multibyte.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActiveSupport #:nodoc:
module Multibyte
autoload :Chars, "active_support/multibyte/chars"
diff --git a/activesupport/lib/active_support/multibyte/chars.rb b/activesupport/lib/active_support/multibyte/chars.rb
index 8c58466556..d676827e8e 100644
--- a/activesupport/lib/active_support/multibyte/chars.rb
+++ b/activesupport/lib/active_support/multibyte/chars.rb
@@ -1,8 +1,10 @@
-require "active_support/json"
-require "active_support/core_ext/string/access"
-require "active_support/core_ext/string/behavior"
-require "active_support/core_ext/module/delegation"
-require "active_support/core_ext/regexp"
+# frozen_string_literal: true
+
+require_relative "../json"
+require_relative "../core_ext/string/access"
+require_relative "../core_ext/string/behavior"
+require_relative "../core_ext/module/delegation"
+require_relative "../core_ext/regexp"
module ActiveSupport #:nodoc:
module Multibyte #:nodoc:
diff --git a/activesupport/lib/active_support/multibyte/unicode.rb b/activesupport/lib/active_support/multibyte/unicode.rb
index 0912912aba..a64223c0e0 100644
--- a/activesupport/lib/active_support/multibyte/unicode.rb
+++ b/activesupport/lib/active_support/multibyte/unicode.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActiveSupport
module Multibyte
module Unicode
@@ -357,7 +359,7 @@ module ActiveSupport
# Returns the directory in which the data files are stored.
def self.dirname
- File.dirname(__FILE__) + "/../values/"
+ File.expand_path("../values", __dir__)
end
# Returns the filename for the data file for this version.
diff --git a/activesupport/lib/active_support/notifications.rb b/activesupport/lib/active_support/notifications.rb
index 2df819e554..96a3463905 100644
--- a/activesupport/lib/active_support/notifications.rb
+++ b/activesupport/lib/active_support/notifications.rb
@@ -1,6 +1,8 @@
-require "active_support/notifications/instrumenter"
-require "active_support/notifications/fanout"
-require "active_support/per_thread_registry"
+# frozen_string_literal: true
+
+require_relative "notifications/instrumenter"
+require_relative "notifications/fanout"
+require_relative "per_thread_registry"
module ActiveSupport
# = Notifications
@@ -64,6 +66,8 @@ module ActiveSupport
# If an exception happens during that particular instrumentation the payload will
# have a key <tt>:exception</tt> with an array of two elements as value: a string with
# the name of the exception class, and the exception message.
+ # The <tt>:exception_object</tt> key of the payload will have the exception
+ # itself as the value.
#
# As the previous example depicts, the class <tt>ActiveSupport::Notifications::Event</tt>
# is able to take the arguments as they come and provide an object-oriented
diff --git a/activesupport/lib/active_support/notifications/fanout.rb b/activesupport/lib/active_support/notifications/fanout.rb
index 9da115f552..25aab175b4 100644
--- a/activesupport/lib/active_support/notifications/fanout.rb
+++ b/activesupport/lib/active_support/notifications/fanout.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "mutex_m"
require "concurrent/map"
diff --git a/activesupport/lib/active_support/notifications/instrumenter.rb b/activesupport/lib/active_support/notifications/instrumenter.rb
index e11e2e0689..e99f5ee688 100644
--- a/activesupport/lib/active_support/notifications/instrumenter.rb
+++ b/activesupport/lib/active_support/notifications/instrumenter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "securerandom"
module ActiveSupport
diff --git a/activesupport/lib/active_support/number_helper.rb b/activesupport/lib/active_support/number_helper.rb
index 880340ca86..8fd6e932f1 100644
--- a/activesupport/lib/active_support/number_helper.rb
+++ b/activesupport/lib/active_support/number_helper.rb
@@ -1,9 +1,12 @@
+# frozen_string_literal: true
+
module ActiveSupport
module NumberHelper
extend ActiveSupport::Autoload
eager_autoload do
autoload :NumberConverter
+ autoload :RoundingHelper
autoload :NumberToRoundedConverter
autoload :NumberToDelimitedConverter
autoload :NumberToHumanConverter
diff --git a/activesupport/lib/active_support/number_helper/number_converter.rb b/activesupport/lib/active_support/number_helper/number_converter.rb
index ce363287cf..5ea9c8f113 100644
--- a/activesupport/lib/active_support/number_helper/number_converter.rb
+++ b/activesupport/lib/active_support/number_helper/number_converter.rb
@@ -1,8 +1,10 @@
-require "active_support/core_ext/big_decimal/conversions"
-require "active_support/core_ext/object/blank"
-require "active_support/core_ext/hash/keys"
-require "active_support/i18n"
-require "active_support/core_ext/class/attribute"
+# frozen_string_literal: true
+
+require_relative "../core_ext/big_decimal/conversions"
+require_relative "../core_ext/object/blank"
+require_relative "../core_ext/hash/keys"
+require_relative "../i18n"
+require_relative "../core_ext/class/attribute"
module ActiveSupport
module NumberHelper
diff --git a/activesupport/lib/active_support/number_helper/number_to_currency_converter.rb b/activesupport/lib/active_support/number_helper/number_to_currency_converter.rb
index 0f9dce722f..1943b9e295 100644
--- a/activesupport/lib/active_support/number_helper/number_to_currency_converter.rb
+++ b/activesupport/lib/active_support/number_helper/number_to_currency_converter.rb
@@ -1,4 +1,6 @@
-require "active_support/core_ext/numeric/inquiry"
+# frozen_string_literal: true
+
+require_relative "../core_ext/numeric/inquiry"
module ActiveSupport
module NumberHelper
diff --git a/activesupport/lib/active_support/number_helper/number_to_delimited_converter.rb b/activesupport/lib/active_support/number_helper/number_to_delimited_converter.rb
index e3b35531b1..d5b5706705 100644
--- a/activesupport/lib/active_support/number_helper/number_to_delimited_converter.rb
+++ b/activesupport/lib/active_support/number_helper/number_to_delimited_converter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActiveSupport
module NumberHelper
class NumberToDelimitedConverter < NumberConverter #:nodoc:
diff --git a/activesupport/lib/active_support/number_helper/number_to_human_converter.rb b/activesupport/lib/active_support/number_helper/number_to_human_converter.rb
index 56185ddf4b..03eb6671ec 100644
--- a/activesupport/lib/active_support/number_helper/number_to_human_converter.rb
+++ b/activesupport/lib/active_support/number_helper/number_to_human_converter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActiveSupport
module NumberHelper
class NumberToHumanConverter < NumberConverter # :nodoc:
@@ -9,6 +11,7 @@ module ActiveSupport
self.validate_float = true
def convert # :nodoc:
+ @number = RoundingHelper.new(options).round(number)
@number = Float(number)
# for backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files
@@ -20,10 +23,7 @@ module ActiveSupport
exponent = calculate_exponent(units)
@number = number / (10**exponent)
- until (rounded_number = NumberToRoundedConverter.convert(number, options)) != NumberToRoundedConverter.convert(1000, options)
- @number = number / 1000.0
- exponent += 3
- end
+ rounded_number = NumberToRoundedConverter.convert(number, options)
unit = determine_unit(units, exponent)
format.gsub("%n".freeze, rounded_number).gsub("%u".freeze, unit).strip
end
diff --git a/activesupport/lib/active_support/number_helper/number_to_human_size_converter.rb b/activesupport/lib/active_support/number_helper/number_to_human_size_converter.rb
index f263dbe9f8..842f2fc8df 100644
--- a/activesupport/lib/active_support/number_helper/number_to_human_size_converter.rb
+++ b/activesupport/lib/active_support/number_helper/number_to_human_size_converter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActiveSupport
module NumberHelper
class NumberToHumanSizeConverter < NumberConverter #:nodoc:
diff --git a/activesupport/lib/active_support/number_helper/number_to_percentage_converter.rb b/activesupport/lib/active_support/number_helper/number_to_percentage_converter.rb
index ac647ca9b7..4dcdad2e2c 100644
--- a/activesupport/lib/active_support/number_helper/number_to_percentage_converter.rb
+++ b/activesupport/lib/active_support/number_helper/number_to_percentage_converter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActiveSupport
module NumberHelper
class NumberToPercentageConverter < NumberConverter # :nodoc:
diff --git a/activesupport/lib/active_support/number_helper/number_to_phone_converter.rb b/activesupport/lib/active_support/number_helper/number_to_phone_converter.rb
index 1de9f50f34..96410f4995 100644
--- a/activesupport/lib/active_support/number_helper/number_to_phone_converter.rb
+++ b/activesupport/lib/active_support/number_helper/number_to_phone_converter.rb
@@ -1,8 +1,10 @@
+# frozen_string_literal: true
+
module ActiveSupport
module NumberHelper
class NumberToPhoneConverter < NumberConverter #:nodoc:
def convert
- str = country_code(opts[:country_code])
+ str = country_code(opts[:country_code]).dup
str << convert_to_phone_number(number.to_s.strip)
str << phone_ext(opts[:extension])
end
diff --git a/activesupport/lib/active_support/number_helper/number_to_rounded_converter.rb b/activesupport/lib/active_support/number_helper/number_to_rounded_converter.rb
index 1f013990ea..3b62fe6819 100644
--- a/activesupport/lib/active_support/number_helper/number_to_rounded_converter.rb
+++ b/activesupport/lib/active_support/number_helper/number_to_rounded_converter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActiveSupport
module NumberHelper
class NumberToRoundedConverter < NumberConverter # :nodoc:
@@ -5,26 +7,14 @@ module ActiveSupport
self.validate_float = true
def convert
- precision = options.delete :precision
+ helper = RoundingHelper.new(options)
+ rounded_number = helper.round(number)
- if precision
- case number
- when Float, String
- @number = BigDecimal(number.to_s)
- when Rational
- @number = BigDecimal(number, digit_count(number.to_i) + precision)
- else
- @number = number.to_d
- end
-
- if options.delete(:significant) && precision > 0
- digits, rounded_number = digits_and_rounded_number(precision)
+ if precision = options[:precision]
+ if options[:significant] && precision > 0
+ digits = helper.digit_count(rounded_number)
precision -= digits
precision = 0 if precision < 0 # don't let it be negative
- else
- rounded_number = number.round(precision)
- rounded_number = rounded_number.to_i if precision == 0 && rounded_number.finite?
- rounded_number = rounded_number.abs if rounded_number.zero? # prevent showing negative zeros
end
formatted_string =
@@ -38,7 +28,7 @@ module ActiveSupport
"%00.#{precision}f" % rounded_number
end
else
- formatted_string = number
+ formatted_string = rounded_number
end
delimited_number = NumberToDelimitedConverter.convert(formatted_string, options)
@@ -79,14 +69,6 @@ module ActiveSupport
number
end
end
-
- def absolute_number(number)
- number.respond_to?(:abs) ? number.abs : number.to_d.abs
- end
-
- def zero?
- number.respond_to?(:zero?) ? number.zero? : number.to_d.zero?
- end
end
end
end
diff --git a/activesupport/lib/active_support/number_helper/rounding_helper.rb b/activesupport/lib/active_support/number_helper/rounding_helper.rb
new file mode 100644
index 0000000000..a5b28296a2
--- /dev/null
+++ b/activesupport/lib/active_support/number_helper/rounding_helper.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+module ActiveSupport
+ module NumberHelper
+ class RoundingHelper # :nodoc:
+ attr_reader :options
+
+ def initialize(options)
+ @options = options
+ end
+
+ def round(number)
+ return number unless precision
+ number = convert_to_decimal(number)
+ if significant && precision > 0
+ round_significant(number)
+ else
+ round_without_significant(number)
+ end
+ end
+
+ def digit_count(number)
+ return 1 if number.zero?
+ (Math.log10(absolute_number(number)) + 1).floor
+ end
+
+ private
+ def round_without_significant(number)
+ number = number.round(precision)
+ number = number.to_i if precision == 0 && number.finite?
+ number = number.abs if number.zero? # prevent showing negative zeros
+ number
+ end
+
+ def round_significant(number)
+ return 0 if number.zero?
+ digits = digit_count(number)
+ multiplier = 10**(digits - precision)
+ (number / BigDecimal.new(multiplier.to_f.to_s)).round * multiplier
+ end
+
+ def convert_to_decimal(number)
+ case number
+ when Float, String
+ BigDecimal(number.to_s)
+ when Rational
+ BigDecimal(number, digit_count(number.to_i) + precision)
+ else
+ number.to_d
+ end
+ end
+
+ def precision
+ options[:precision]
+ end
+
+ def significant
+ options[:significant]
+ end
+
+ def absolute_number(number)
+ number.respond_to?(:abs) ? number.abs : number.to_d.abs
+ end
+ end
+ end
+end
diff --git a/activesupport/lib/active_support/option_merger.rb b/activesupport/lib/active_support/option_merger.rb
index 0f2caa98f2..42cbbe7c42 100644
--- a/activesupport/lib/active_support/option_merger.rb
+++ b/activesupport/lib/active_support/option_merger.rb
@@ -1,4 +1,6 @@
-require "active_support/core_ext/hash/deep_merge"
+# frozen_string_literal: true
+
+require_relative "core_ext/hash/deep_merge"
module ActiveSupport
class OptionMerger #:nodoc:
diff --git a/activesupport/lib/active_support/ordered_hash.rb b/activesupport/lib/active_support/ordered_hash.rb
index 3aa0a14f04..5758513021 100644
--- a/activesupport/lib/active_support/ordered_hash.rb
+++ b/activesupport/lib/active_support/ordered_hash.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "yaml"
YAML.add_builtin_type("omap") do |type, val|
diff --git a/activesupport/lib/active_support/ordered_options.rb b/activesupport/lib/active_support/ordered_options.rb
index 04d6dfaf9c..fa7825b3ba 100644
--- a/activesupport/lib/active_support/ordered_options.rb
+++ b/activesupport/lib/active_support/ordered_options.rb
@@ -1,4 +1,6 @@
-require "active_support/core_ext/object/blank"
+# frozen_string_literal: true
+
+require_relative "core_ext/object/blank"
module ActiveSupport
# Usually key value pairs are handled something like this:
diff --git a/activesupport/lib/active_support/per_thread_registry.rb b/activesupport/lib/active_support/per_thread_registry.rb
index 02431704d3..dd0cc6a604 100644
--- a/activesupport/lib/active_support/per_thread_registry.rb
+++ b/activesupport/lib/active_support/per_thread_registry.rb
@@ -1,4 +1,6 @@
-require "active_support/core_ext/module/delegation"
+# frozen_string_literal: true
+
+require_relative "core_ext/module/delegation"
module ActiveSupport
# NOTE: This approach has been deprecated for end-user code in favor of {thread_mattr_accessor}[rdoc-ref:Module#thread_mattr_accessor] and friends.
diff --git a/activesupport/lib/active_support/proxy_object.rb b/activesupport/lib/active_support/proxy_object.rb
index 20a0fd8e62..0965fcd2d9 100644
--- a/activesupport/lib/active_support/proxy_object.rb
+++ b/activesupport/lib/active_support/proxy_object.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActiveSupport
# A class with no predefined methods that behaves similarly to Builder's
# BlankSlate. Used for proxy classes.
diff --git a/activesupport/lib/active_support/rails.rb b/activesupport/lib/active_support/rails.rb
index f6b018f0d3..fe82d1cc14 100644
--- a/activesupport/lib/active_support/rails.rb
+++ b/activesupport/lib/active_support/rails.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# This is private interface.
#
# Rails components cherry pick from Active Support as needed, but there are a
@@ -9,25 +11,25 @@
# Rails and can change anytime.
# Defines Object#blank? and Object#present?.
-require "active_support/core_ext/object/blank"
+require_relative "core_ext/object/blank"
# Rails own autoload, eager_load, etc.
-require "active_support/dependencies/autoload"
+require_relative "dependencies/autoload"
# Support for ClassMethods and the included macro.
-require "active_support/concern"
+require_relative "concern"
# Defines Class#class_attribute.
-require "active_support/core_ext/class/attribute"
+require_relative "core_ext/class/attribute"
# Defines Module#delegate.
-require "active_support/core_ext/module/delegation"
+require_relative "core_ext/module/delegation"
# Defines ActiveSupport::Deprecation.
-require "active_support/deprecation"
+require_relative "deprecation"
# Defines Regexp#match?.
#
# This should be removed when Rails needs Ruby 2.4 or later, and the require
# added where other Regexp extensions are being used (easy to grep).
-require "active_support/core_ext/regexp"
+require_relative "core_ext/regexp"
diff --git a/activesupport/lib/active_support/railtie.rb b/activesupport/lib/active_support/railtie.rb
index b875875afe..2efe391d01 100644
--- a/activesupport/lib/active_support/railtie.rb
+++ b/activesupport/lib/active_support/railtie.rb
@@ -1,5 +1,7 @@
+# frozen_string_literal: true
+
require "active_support"
-require "active_support/i18n_railtie"
+require_relative "i18n_railtie"
module ActiveSupport
class Railtie < Rails::Railtie # :nodoc:
@@ -7,6 +9,19 @@ module ActiveSupport
config.eager_load_namespaces << ActiveSupport
+ initializer "active_support.set_authenticated_message_encryption" do |app|
+ if app.config.active_support.respond_to?(:use_authenticated_message_encryption)
+ ActiveSupport::MessageEncryptor.use_authenticated_message_encryption =
+ app.config.active_support.use_authenticated_message_encryption
+ end
+ end
+
+ initializer "active_support.reset_all_current_attributes_instances" do |app|
+ app.reloader.before_class_unload { ActiveSupport::CurrentAttributes.clear_all }
+ app.executor.to_run { ActiveSupport::CurrentAttributes.reset_all }
+ app.executor.to_complete { ActiveSupport::CurrentAttributes.reset_all }
+ end
+
initializer "active_support.deprecation_behavior" do |app|
if deprecation = app.config.active_support.deprecation
ActiveSupport::Deprecation.behavior = deprecation
@@ -21,21 +36,14 @@ module ActiveSupport
rescue TZInfo::DataSourceNotFound => e
raise e.exception "tzinfo-data is not present. Please add gem 'tzinfo-data' to your Gemfile and run bundle install"
end
- require "active_support/core_ext/time/zones"
- zone_default = Time.find_zone!(app.config.time_zone)
-
- unless zone_default
- raise "Value assigned to config.time_zone not recognized. " \
- 'Run "rake time:zones:all" for a time zone names list.'
- end
-
- Time.zone_default = zone_default
+ require_relative "core_ext/time/zones"
+ Time.zone_default = Time.find_zone!(app.config.time_zone)
end
# Sets the default week start
# If assigned value is not a valid day symbol (e.g. :sunday, :monday, ...), an exception will be raised.
initializer "active_support.initialize_beginning_of_week" do |app|
- require "active_support/core_ext/date/calculations"
+ require_relative "core_ext/date/calculations"
beginning_of_week_default = Date.find_beginning_of_week!(app.config.beginning_of_week)
Date.beginning_of_week_default = beginning_of_week_default
diff --git a/activesupport/lib/active_support/reloader.rb b/activesupport/lib/active_support/reloader.rb
index 121c621751..44062e3491 100644
--- a/activesupport/lib/active_support/reloader.rb
+++ b/activesupport/lib/active_support/reloader.rb
@@ -1,4 +1,6 @@
-require "active_support/execution_wrapper"
+# frozen_string_literal: true
+
+require_relative "execution_wrapper"
module ActiveSupport
#--
@@ -69,11 +71,8 @@ module ActiveSupport
end
end
- class_attribute :executor
- class_attribute :check
-
- self.executor = Executor
- self.check = lambda { false }
+ class_attribute :executor, default: Executor
+ class_attribute :check, default: lambda { false }
def self.check! # :nodoc:
@should_reload ||= check.call
diff --git a/activesupport/lib/active_support/rescuable.rb b/activesupport/lib/active_support/rescuable.rb
index ee6592fb5a..2f6aeef48a 100644
--- a/activesupport/lib/active_support/rescuable.rb
+++ b/activesupport/lib/active_support/rescuable.rb
@@ -1,6 +1,8 @@
-require "active_support/concern"
-require "active_support/core_ext/class/attribute"
-require "active_support/core_ext/string/inflections"
+# frozen_string_literal: true
+
+require_relative "concern"
+require_relative "core_ext/class/attribute"
+require_relative "core_ext/string/inflections"
module ActiveSupport
# Rescuable module adds support for easier exception handling.
@@ -8,8 +10,7 @@ module ActiveSupport
extend Concern
included do
- class_attribute :rescue_handlers
- self.rescue_handlers = []
+ class_attribute :rescue_handlers, default: []
end
module ClassMethods
@@ -84,12 +85,18 @@ module ActiveSupport
# end
#
# Returns the exception if it was handled and +nil+ if it was not.
- def rescue_with_handler(exception, object: self)
+ def rescue_with_handler(exception, object: self, visited_exceptions: [])
+ visited_exceptions << exception
+
if handler = handler_for_rescue(exception, object: object)
handler.call exception
exception
elsif exception
- rescue_with_handler(exception.cause, object: object)
+ if visited_exceptions.include?(exception.cause)
+ nil
+ else
+ rescue_with_handler(exception.cause, object: object, visited_exceptions: visited_exceptions)
+ end
end
end
diff --git a/activesupport/lib/active_support/security_utils.rb b/activesupport/lib/active_support/security_utils.rb
index b655d64449..51870559ec 100644
--- a/activesupport/lib/active_support/security_utils.rb
+++ b/activesupport/lib/active_support/security_utils.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "digest"
module ActiveSupport
diff --git a/activesupport/lib/active_support/string_inquirer.rb b/activesupport/lib/active_support/string_inquirer.rb
index 90eac89c9e..a3af36720e 100644
--- a/activesupport/lib/active_support/string_inquirer.rb
+++ b/activesupport/lib/active_support/string_inquirer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActiveSupport
# Wrapping a string in this class gives you a prettier way to test
# for equality. The value returned by <tt>Rails.env</tt> is wrapped
diff --git a/activesupport/lib/active_support/subscriber.rb b/activesupport/lib/active_support/subscriber.rb
index 2924139755..7913bb815e 100644
--- a/activesupport/lib/active_support/subscriber.rb
+++ b/activesupport/lib/active_support/subscriber.rb
@@ -1,5 +1,7 @@
-require "active_support/per_thread_registry"
-require "active_support/notifications"
+# frozen_string_literal: true
+
+require_relative "per_thread_registry"
+require_relative "notifications"
module ActiveSupport
# ActiveSupport::Subscriber is an object set to consume
diff --git a/activesupport/lib/active_support/tagged_logging.rb b/activesupport/lib/active_support/tagged_logging.rb
index ad134c49b6..fe13eaed4e 100644
--- a/activesupport/lib/active_support/tagged_logging.rb
+++ b/activesupport/lib/active_support/tagged_logging.rb
@@ -1,7 +1,9 @@
-require "active_support/core_ext/module/delegation"
-require "active_support/core_ext/object/blank"
+# frozen_string_literal: true
+
+require_relative "core_ext/module/delegation"
+require_relative "core_ext/object/blank"
require "logger"
-require "active_support/logger"
+require_relative "logger"
module ActiveSupport
# Wraps any standard Logger object to provide tagging capabilities.
diff --git a/activesupport/lib/active_support/test_case.rb b/activesupport/lib/active_support/test_case.rb
index 3de4ccc1da..bc42758f76 100644
--- a/activesupport/lib/active_support/test_case.rb
+++ b/activesupport/lib/active_support/test_case.rb
@@ -1,15 +1,17 @@
+# frozen_string_literal: true
+
gem "minitest" # make sure we get the gem, not stdlib
require "minitest"
-require "active_support/testing/tagged_logging"
-require "active_support/testing/setup_and_teardown"
-require "active_support/testing/assertions"
-require "active_support/testing/deprecation"
-require "active_support/testing/declarative"
-require "active_support/testing/isolation"
-require "active_support/testing/constant_lookup"
-require "active_support/testing/time_helpers"
-require "active_support/testing/file_fixtures"
-require "active_support/core_ext/kernel/reporting"
+require_relative "testing/tagged_logging"
+require_relative "testing/setup_and_teardown"
+require_relative "testing/assertions"
+require_relative "testing/deprecation"
+require_relative "testing/declarative"
+require_relative "testing/isolation"
+require_relative "testing/constant_lookup"
+require_relative "testing/time_helpers"
+require_relative "testing/file_fixtures"
+require_relative "core_ext/kernel/reporting"
module ActiveSupport
class TestCase < ::Minitest::Test
diff --git a/activesupport/lib/active_support/testing/assertions.rb b/activesupport/lib/active_support/testing/assertions.rb
index 28cf2953bf..f6366bfd39 100644
--- a/activesupport/lib/active_support/testing/assertions.rb
+++ b/activesupport/lib/active_support/testing/assertions.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActiveSupport
module Testing
module Assertions
@@ -167,7 +169,7 @@ module ActiveSupport
retval
end
- # Assertion that the result of evaluating an expression is changed before
+ # Assertion that the result of evaluating an expression is not changed before
# and after invoking the passed in block.
#
# assert_no_changes 'Status.all_good?' do
diff --git a/activesupport/lib/active_support/testing/autorun.rb b/activesupport/lib/active_support/testing/autorun.rb
index a18788f38e..889b41659a 100644
--- a/activesupport/lib/active_support/testing/autorun.rb
+++ b/activesupport/lib/active_support/testing/autorun.rb
@@ -1,9 +1,7 @@
+# frozen_string_literal: true
+
gem "minitest"
require "minitest"
-if Minitest.respond_to?(:run_via) && !Minitest.run_via.set?
- Minitest.run_via = :ruby
-end
-
Minitest.autorun
diff --git a/activesupport/lib/active_support/testing/constant_lookup.rb b/activesupport/lib/active_support/testing/constant_lookup.rb
index 647395d2b3..0fedd486fb 100644
--- a/activesupport/lib/active_support/testing/constant_lookup.rb
+++ b/activesupport/lib/active_support/testing/constant_lookup.rb
@@ -1,5 +1,7 @@
-require "active_support/concern"
-require "active_support/inflector"
+# frozen_string_literal: true
+
+require_relative "../concern"
+require_relative "../inflector"
module ActiveSupport
module Testing
diff --git a/activesupport/lib/active_support/testing/declarative.rb b/activesupport/lib/active_support/testing/declarative.rb
index 53ab3ebf78..7c3403684d 100644
--- a/activesupport/lib/active_support/testing/declarative.rb
+++ b/activesupport/lib/active_support/testing/declarative.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActiveSupport
module Testing
module Declarative
diff --git a/activesupport/lib/active_support/testing/deprecation.rb b/activesupport/lib/active_support/testing/deprecation.rb
index 58911570e8..4fda4832cc 100644
--- a/activesupport/lib/active_support/testing/deprecation.rb
+++ b/activesupport/lib/active_support/testing/deprecation.rb
@@ -1,5 +1,7 @@
-require "active_support/deprecation"
-require "active_support/core_ext/regexp"
+# frozen_string_literal: true
+
+require_relative "../deprecation"
+require_relative "../core_ext/regexp"
module ActiveSupport
module Testing
diff --git a/activesupport/lib/active_support/testing/file_fixtures.rb b/activesupport/lib/active_support/testing/file_fixtures.rb
index affb84cda5..ad923d1aab 100644
--- a/activesupport/lib/active_support/testing/file_fixtures.rb
+++ b/activesupport/lib/active_support/testing/file_fixtures.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActiveSupport
module Testing
# Adds simple access to sample files called file fixtures.
diff --git a/activesupport/lib/active_support/testing/isolation.rb b/activesupport/lib/active_support/testing/isolation.rb
index 54c3263efa..954197a3cc 100644
--- a/activesupport/lib/active_support/testing/isolation.rb
+++ b/activesupport/lib/active_support/testing/isolation.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActiveSupport
module Testing
module Isolation
diff --git a/activesupport/lib/active_support/testing/method_call_assertions.rb b/activesupport/lib/active_support/testing/method_call_assertions.rb
index 6b07416fdc..c6358002ea 100644
--- a/activesupport/lib/active_support/testing/method_call_assertions.rb
+++ b/activesupport/lib/active_support/testing/method_call_assertions.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "minitest/mock"
module ActiveSupport
diff --git a/activesupport/lib/active_support/testing/setup_and_teardown.rb b/activesupport/lib/active_support/testing/setup_and_teardown.rb
index 358c79c321..18de7185d9 100644
--- a/activesupport/lib/active_support/testing/setup_and_teardown.rb
+++ b/activesupport/lib/active_support/testing/setup_and_teardown.rb
@@ -1,5 +1,7 @@
-require "active_support/concern"
-require "active_support/callbacks"
+# frozen_string_literal: true
+
+require_relative "../concern"
+require_relative "../callbacks"
module ActiveSupport
module Testing
diff --git a/activesupport/lib/active_support/testing/stream.rb b/activesupport/lib/active_support/testing/stream.rb
index 1d06b94559..d070a1793d 100644
--- a/activesupport/lib/active_support/testing/stream.rb
+++ b/activesupport/lib/active_support/testing/stream.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActiveSupport
module Testing
module Stream #:nodoc:
diff --git a/activesupport/lib/active_support/testing/tagged_logging.rb b/activesupport/lib/active_support/testing/tagged_logging.rb
index afdff87b45..9ca50c7918 100644
--- a/activesupport/lib/active_support/testing/tagged_logging.rb
+++ b/activesupport/lib/active_support/testing/tagged_logging.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActiveSupport
module Testing
# Logs a "PostsControllerTest: test name" heading before each test to
diff --git a/activesupport/lib/active_support/testing/time_helpers.rb b/activesupport/lib/active_support/testing/time_helpers.rb
index 07c9be0604..b529592910 100644
--- a/activesupport/lib/active_support/testing/time_helpers.rb
+++ b/activesupport/lib/active_support/testing/time_helpers.rb
@@ -1,4 +1,7 @@
-require "active_support/core_ext/string/strip" # for strip_heredoc
+# frozen_string_literal: true
+
+require_relative "../core_ext/string/strip" # for strip_heredoc
+require_relative "../core_ext/time/calculations"
require "concurrent/map"
module ActiveSupport
@@ -148,7 +151,7 @@ module ActiveSupport
end
# Returns the current time back to its original state, by removing the stubs added by
- # `travel` and `travel_to`.
+ # +travel+ and +travel_to+.
#
# Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
# travel_to Time.zone.local(2004, 11, 24, 01, 04, 44)
@@ -159,6 +162,26 @@ module ActiveSupport
simple_stubs.unstub_all!
end
+ # Calls +travel_to+ with +Time.now+.
+ #
+ # Time.current # => Sun, 09 Jul 2017 15:34:49 EST -05:00
+ # freeze_time
+ # sleep(1)
+ # Time.current # => Sun, 09 Jul 2017 15:34:49 EST -05:00
+ #
+ # This method also accepts a block, which will return the current time back to its original
+ # state at the end of the block:
+ #
+ # Time.current # => Sun, 09 Jul 2017 15:34:49 EST -05:00
+ # freeze_time do
+ # sleep(1)
+ # User.create.created_at # => Sun, 09 Jul 2017 15:34:49 EST -05:00
+ # end
+ # Time.current # => Sun, 09 Jul 2017 15:34:50 EST -05:00
+ def freeze_time(&block)
+ travel_to Time.now, &block
+ end
+
private
def simple_stubs
diff --git a/activesupport/lib/active_support/time.rb b/activesupport/lib/active_support/time.rb
index 7658228ca6..fb1c5cee1c 100644
--- a/activesupport/lib/active_support/time.rb
+++ b/activesupport/lib/active_support/time.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ActiveSupport
autoload :Duration, "active_support/duration"
autoload :TimeWithZone, "active_support/time_with_zone"
@@ -7,12 +9,12 @@ end
require "date"
require "time"
-require "active_support/core_ext/time"
-require "active_support/core_ext/date"
-require "active_support/core_ext/date_time"
+require_relative "core_ext/time"
+require_relative "core_ext/date"
+require_relative "core_ext/date_time"
-require "active_support/core_ext/integer/time"
-require "active_support/core_ext/numeric/time"
+require_relative "core_ext/integer/time"
+require_relative "core_ext/numeric/time"
-require "active_support/core_ext/string/conversions"
-require "active_support/core_ext/string/zones"
+require_relative "core_ext/string/conversions"
+require_relative "core_ext/string/zones"
diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb
index e31983cf26..59cafa193e 100644
--- a/activesupport/lib/active_support/time_with_zone.rb
+++ b/activesupport/lib/active_support/time_with_zone.rb
@@ -1,7 +1,9 @@
-require "active_support/duration"
-require "active_support/values/time_zone"
-require "active_support/core_ext/object/acts_like"
-require "active_support/core_ext/date_and_time/compatibility"
+# frozen_string_literal: true
+
+require_relative "duration"
+require_relative "values/time_zone"
+require_relative "core_ext/object/acts_like"
+require_relative "core_ext/date_and_time/compatibility"
module ActiveSupport
# A Time-like class that can represent a time in any time zone. Necessary
@@ -330,6 +332,42 @@ module ActiveSupport
since(-other)
end
+ # Returns a new +ActiveSupport::TimeWithZone+ where one or more of the elements have
+ # been changed according to the +options+ parameter. The time options (<tt>:hour</tt>,
+ # <tt>:min</tt>, <tt>:sec</tt>, <tt>:usec</tt>, <tt>:nsec</tt>) reset cascadingly,
+ # so if only the hour is passed, then minute, sec, usec and nsec is set to 0. If the
+ # hour and minute is passed, then sec, usec and nsec is set to 0. The +options+
+ # parameter takes a hash with any of these keys: <tt>:year</tt>, <tt>:month</tt>,
+ # <tt>:day</tt>, <tt>:hour</tt>, <tt>:min</tt>, <tt>:sec</tt>, <tt>:usec</tt>,
+ # <tt>:nsec</tt>, <tt>:offset</tt>, <tt>:zone</tt>. Pass either <tt>:usec</tt>
+ # or <tt>:nsec</tt>, not both. Similarly, pass either <tt>:zone</tt> or
+ # <tt>:offset</tt>, not both.
+ #
+ # t = Time.zone.now # => Fri, 14 Apr 2017 11:45:15 EST -05:00
+ # t.change(year: 2020) # => Tue, 14 Apr 2020 11:45:15 EST -05:00
+ # t.change(hour: 12) # => Fri, 14 Apr 2017 12:00:00 EST -05:00
+ # t.change(min: 30) # => Fri, 14 Apr 2017 11:30:00 EST -05:00
+ # t.change(offset: "-10:00") # => Fri, 14 Apr 2017 11:45:15 HST -10:00
+ # t.change(zone: "Hawaii") # => Fri, 14 Apr 2017 11:45:15 HST -10:00
+ def change(options)
+ if options[:zone] && options[:offset]
+ raise ArgumentError, "Can't change both :offset and :zone at the same time: #{options.inspect}"
+ end
+
+ new_time = time.change(options)
+
+ if options[:zone]
+ new_zone = ::Time.find_zone(options[:zone])
+ elsif options[:offset]
+ new_zone = ::Time.find_zone(new_time.utc_offset)
+ end
+
+ new_zone ||= time_zone
+ periods = new_zone.periods_for_local(new_time)
+
+ self.class.new(nil, new_zone, new_time, periods.include?(period) ? period : nil)
+ end
+
# Uses Date to provide precise Time calculations for years, months, and days
# according to the proleptic Gregorian calendar. The result is returned as a
# new TimeWithZone object.
@@ -411,6 +449,17 @@ module ActiveSupport
@to_datetime ||= utc.to_datetime.new_offset(Rational(utc_offset, 86_400))
end
+ # Returns an instance of +Time+, either with the same UTC offset
+ # as +self+ or in the local system timezone depending on the setting
+ # of +ActiveSupport.to_time_preserves_timezone+.
+ def to_time
+ if preserve_timezone
+ @to_time_with_instance_offset ||= getlocal(utc_offset)
+ else
+ @to_time_with_system_offset ||= getlocal
+ end
+ end
+
# So that +self+ <tt>acts_like?(:time)</tt>.
def acts_like_time?
true
@@ -429,7 +478,7 @@ module ActiveSupport
def freeze
# preload instance variables before freezing
- period; utc; time; to_datetime
+ period; utc; time; to_datetime; to_time
super
end
diff --git a/activesupport/lib/active_support/values/time_zone.rb b/activesupport/lib/active_support/values/time_zone.rb
index 18477b9f6b..c871f11422 100644
--- a/activesupport/lib/active_support/values/time_zone.rb
+++ b/activesupport/lib/active_support/values/time_zone.rb
@@ -1,12 +1,14 @@
+# frozen_string_literal: true
+
require "tzinfo"
require "concurrent/map"
-require "active_support/core_ext/object/blank"
+require_relative "../core_ext/object/blank"
module ActiveSupport
# The TimeZone class serves as a wrapper around TZInfo::Timezone instances.
# It allows us to do the following:
#
- # * Limit the set of zones provided by TZInfo to a meaningful subset of 146
+ # * Limit the set of zones provided by TZInfo to a meaningful subset of 134
# zones.
# * Retrieve and display zones with a friendlier name
# (e.g., "Eastern Time (US & Canada)" instead of "America/New_York").
@@ -59,6 +61,7 @@ module ActiveSupport
"Buenos Aires" => "America/Argentina/Buenos_Aires",
"Montevideo" => "America/Montevideo",
"Georgetown" => "America/Guyana",
+ "Puerto Rico" => "America/Puerto_Rico",
"Greenland" => "America/Godthab",
"Mid-Atlantic" => "Atlantic/South_Georgia",
"Azores" => "Atlantic/Azores",
@@ -250,14 +253,21 @@ module ActiveSupport
# for time zones in the country specified by its ISO 3166-1 Alpha2 code.
def country_zones(country_code)
code = country_code.to_s.upcase
- @country_zones[code] ||=
- TZInfo::Country.get(code).zone_identifiers.map do |tz_id|
- name = MAPPING.key(tz_id)
- name && self[name]
- end.compact.sort!
+ @country_zones[code] ||= load_country_zones(code)
end
private
+ def load_country_zones(code)
+ country = TZInfo::Country.get(code)
+ country.zone_identifiers.map do |tz_id|
+ if MAPPING.value?(tz_id)
+ self[MAPPING.key(tz_id)]
+ else
+ create(tz_id, nil, TZInfo::Timezone.new(tz_id))
+ end
+ end.sort!
+ end
+
def zones_map
@zones_map ||= begin
MAPPING.each_key { |place| self[place] } # load all the zones
@@ -351,7 +361,7 @@ module ActiveSupport
# Time.zone.iso8601('1999-12-31') # => Fri, 31 Dec 1999 00:00:00 HST -10:00
#
# If the string is invalid then an +ArgumentError+ will be raised unlike +parse+
- # which returns +nil+ when given an invalid date string.
+ # which usually returns +nil+ when given an invalid date string.
def iso8601(str)
parts = Date._iso8601(str)
@@ -390,6 +400,8 @@ module ActiveSupport
# components are supplied, then the day of the month defaults to 1:
#
# Time.zone.parse('Mar 2000') # => Wed, 01 Mar 2000 00:00:00 HST -10:00
+ #
+ # If the string is invalid then an +ArgumentError+ could be raised.
def parse(str, now = now())
parts_to_time(Date._parse(str, false), now)
end
diff --git a/activesupport/lib/active_support/version.rb b/activesupport/lib/active_support/version.rb
index 20b91ac911..928838c837 100644
--- a/activesupport/lib/active_support/version.rb
+++ b/activesupport/lib/active_support/version.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require_relative "gem_version"
module ActiveSupport
diff --git a/activesupport/lib/active_support/xml_mini.rb b/activesupport/lib/active_support/xml_mini.rb
index 782fb41288..d49ee4508e 100644
--- a/activesupport/lib/active_support/xml_mini.rb
+++ b/activesupport/lib/active_support/xml_mini.rb
@@ -1,9 +1,11 @@
+# frozen_string_literal: true
+
require "time"
require "base64"
require "bigdecimal"
-require "active_support/core_ext/module/delegation"
-require "active_support/core_ext/string/inflections"
-require "active_support/core_ext/date_time/calculations"
+require_relative "core_ext/module/delegation"
+require_relative "core_ext/string/inflections"
+require_relative "core_ext/date_time/calculations"
module ActiveSupport
# = XmlMini
@@ -197,7 +199,7 @@ module ActiveSupport
if name.is_a?(Module)
name
else
- require "active_support/xml_mini/#{name.downcase}"
+ require_relative "xml_mini/#{name.downcase}"
ActiveSupport.const_get("XmlMini_#{name}")
end
end
diff --git a/activesupport/lib/active_support/xml_mini/jdom.rb b/activesupport/lib/active_support/xml_mini/jdom.rb
index a7939b3185..60c7277028 100644
--- a/activesupport/lib/active_support/xml_mini/jdom.rb
+++ b/activesupport/lib/active_support/xml_mini/jdom.rb
@@ -1,9 +1,11 @@
+# frozen_string_literal: true
+
raise "JRuby is required to use the JDOM backend for XmlMini" unless RUBY_PLATFORM.include?("java")
require "jruby"
include Java
-require "active_support/core_ext/object/blank"
+require_relative "../core_ext/object/blank"
java_import javax.xml.parsers.DocumentBuilder unless defined? DocumentBuilder
java_import javax.xml.parsers.DocumentBuilderFactory unless defined? DocumentBuilderFactory
diff --git a/activesupport/lib/active_support/xml_mini/libxml.rb b/activesupport/lib/active_support/xml_mini/libxml.rb
index cde2967132..b1be38fadf 100644
--- a/activesupport/lib/active_support/xml_mini/libxml.rb
+++ b/activesupport/lib/active_support/xml_mini/libxml.rb
@@ -1,5 +1,7 @@
+# frozen_string_literal: true
+
require "libxml"
-require "active_support/core_ext/object/blank"
+require_relative "../core_ext/object/blank"
require "stringio"
module ActiveSupport
@@ -14,11 +16,9 @@ module ActiveSupport
data = StringIO.new(data || "")
end
- char = data.getc
- if char.nil?
+ if data.eof?
{}
else
- data.ungetc(char)
LibXML::XML::Parser.io(data).parse.to_hash
end
end
@@ -55,7 +55,7 @@ module LibXML #:nodoc:
if c.element?
c.to_hash(node_hash)
elsif c.text? || c.cdata?
- node_hash[CONTENT_ROOT] ||= ""
+ node_hash[CONTENT_ROOT] ||= "".dup
node_hash[CONTENT_ROOT] << c.content
end
end
diff --git a/activesupport/lib/active_support/xml_mini/libxmlsax.rb b/activesupport/lib/active_support/xml_mini/libxmlsax.rb
index 8a43b05b17..3ad494310d 100644
--- a/activesupport/lib/active_support/xml_mini/libxmlsax.rb
+++ b/activesupport/lib/active_support/xml_mini/libxmlsax.rb
@@ -1,5 +1,7 @@
+# frozen_string_literal: true
+
require "libxml"
-require "active_support/core_ext/object/blank"
+require_relative "../core_ext/object/blank"
require "stringio"
module ActiveSupport
@@ -21,7 +23,7 @@ module ActiveSupport
end
def on_start_document
- @hash = { CONTENT_KEY => "" }
+ @hash = { CONTENT_KEY => "".dup }
@hash_stack = [@hash]
end
@@ -31,7 +33,7 @@ module ActiveSupport
end
def on_start_element(name, attrs = {})
- new_hash = { CONTENT_KEY => "" }.merge!(attrs)
+ new_hash = { CONTENT_KEY => "".dup }.merge!(attrs)
new_hash[HASH_SIZE_KEY] = new_hash.size + 1
case current_hash[name]
@@ -65,12 +67,9 @@ module ActiveSupport
data = StringIO.new(data || "")
end
- char = data.getc
- if char.nil?
+ if data.eof?
{}
else
- data.ungetc(char)
-
LibXML::XML::Error.set_handler(&LibXML::XML::Error::QUIET_HANDLER)
parser = LibXML::XML::SaxParser.io(data)
document = document_class.new
diff --git a/activesupport/lib/active_support/xml_mini/nokogiri.rb b/activesupport/lib/active_support/xml_mini/nokogiri.rb
index 4c2be3f3ec..1987330c25 100644
--- a/activesupport/lib/active_support/xml_mini/nokogiri.rb
+++ b/activesupport/lib/active_support/xml_mini/nokogiri.rb
@@ -1,10 +1,12 @@
+# frozen_string_literal: true
+
begin
require "nokogiri"
rescue LoadError => e
$stderr.puts "You don't have nokogiri installed in your application. Please add it to your Gemfile and run bundle install"
raise e
end
-require "active_support/core_ext/object/blank"
+require_relative "../core_ext/object/blank"
require "stringio"
module ActiveSupport
@@ -19,11 +21,9 @@ module ActiveSupport
data = StringIO.new(data || "")
end
- char = data.getc
- if char.nil?
+ if data.eof?
{}
else
- data.ungetc(char)
doc = Nokogiri::XML(data)
raise doc.errors.first if doc.errors.length > 0
doc.to_hash
@@ -59,7 +59,7 @@ module ActiveSupport
if c.element?
c.to_hash(node_hash)
elsif c.text? || c.cdata?
- node_hash[CONTENT_ROOT] ||= ""
+ node_hash[CONTENT_ROOT] ||= "".dup
node_hash[CONTENT_ROOT] << c.content
end
end
diff --git a/activesupport/lib/active_support/xml_mini/nokogirisax.rb b/activesupport/lib/active_support/xml_mini/nokogirisax.rb
index 7388bea5d8..fb57eb8867 100644
--- a/activesupport/lib/active_support/xml_mini/nokogirisax.rb
+++ b/activesupport/lib/active_support/xml_mini/nokogirisax.rb
@@ -1,10 +1,12 @@
+# frozen_string_literal: true
+
begin
require "nokogiri"
rescue LoadError => e
$stderr.puts "You don't have nokogiri installed in your application. Please add it to your Gemfile and run bundle install"
raise e
end
-require "active_support/core_ext/object/blank"
+require_relative "../core_ext/object/blank"
require "stringio"
module ActiveSupport
@@ -37,7 +39,7 @@ module ActiveSupport
end
def start_element(name, attrs = [])
- new_hash = { CONTENT_KEY => "" }.merge!(Hash[attrs])
+ new_hash = { CONTENT_KEY => "".dup }.merge!(Hash[attrs])
new_hash[HASH_SIZE_KEY] = new_hash.size + 1
case current_hash[name]
@@ -71,11 +73,9 @@ module ActiveSupport
data = StringIO.new(data || "")
end
- char = data.getc
- if char.nil?
+ if data.eof?
{}
else
- data.ungetc(char)
document = document_class.new
parser = Nokogiri::XML::SAX::Parser.new(document)
parser.parse(data)
diff --git a/activesupport/lib/active_support/xml_mini/rexml.rb b/activesupport/lib/active_support/xml_mini/rexml.rb
index 03fa910fa5..5fd8978fc0 100644
--- a/activesupport/lib/active_support/xml_mini/rexml.rb
+++ b/activesupport/lib/active_support/xml_mini/rexml.rb
@@ -1,5 +1,7 @@
-require "active_support/core_ext/kernel/reporting"
-require "active_support/core_ext/object/blank"
+# frozen_string_literal: true
+
+require_relative "../core_ext/kernel/reporting"
+require_relative "../core_ext/object/blank"
require "stringio"
module ActiveSupport
@@ -74,7 +76,7 @@ module ActiveSupport
hash
else
# must use value to prevent double-escaping
- texts = ""
+ texts = "".dup
element.texts.each { |t| texts << t.value }
merge!(hash, CONTENT_KEY, texts)
end