activesupport 7.1.6 → 8.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +256 -1133
  3. data/README.rdoc +1 -1
  4. data/lib/active_support/array_inquirer.rb +1 -1
  5. data/lib/active_support/backtrace_cleaner.rb +81 -3
  6. data/lib/active_support/benchmark.rb +21 -0
  7. data/lib/active_support/benchmarkable.rb +3 -2
  8. data/lib/active_support/broadcast_logger.rb +65 -78
  9. data/lib/active_support/cache/file_store.rb +29 -14
  10. data/lib/active_support/cache/mem_cache_store.rb +42 -102
  11. data/lib/active_support/cache/memory_store.rb +11 -6
  12. data/lib/active_support/cache/null_store.rb +2 -2
  13. data/lib/active_support/cache/redis_cache_store.rb +58 -46
  14. data/lib/active_support/cache/serializer_with_fallback.rb +0 -23
  15. data/lib/active_support/cache/strategy/local_cache.rb +72 -27
  16. data/lib/active_support/cache/strategy/local_cache_middleware.rb +7 -7
  17. data/lib/active_support/cache.rb +146 -86
  18. data/lib/active_support/callbacks.rb +102 -126
  19. data/lib/active_support/class_attribute.rb +33 -0
  20. data/lib/active_support/code_generator.rb +9 -0
  21. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +8 -62
  22. data/lib/active_support/concurrency/share_lock.rb +0 -1
  23. data/lib/active_support/concurrency/thread_monitor.rb +55 -0
  24. data/lib/active_support/configurable.rb +34 -0
  25. data/lib/active_support/configuration_file.rb +15 -6
  26. data/lib/active_support/continuous_integration.rb +145 -0
  27. data/lib/active_support/core_ext/array/conversions.rb +3 -5
  28. data/lib/active_support/core_ext/array.rb +7 -7
  29. data/lib/active_support/core_ext/benchmark.rb +4 -14
  30. data/lib/active_support/core_ext/big_decimal.rb +1 -1
  31. data/lib/active_support/core_ext/class/attribute.rb +26 -19
  32. data/lib/active_support/core_ext/class/subclasses.rb +15 -35
  33. data/lib/active_support/core_ext/class.rb +2 -2
  34. data/lib/active_support/core_ext/date/blank.rb +4 -0
  35. data/lib/active_support/core_ext/date/conversions.rb +2 -2
  36. data/lib/active_support/core_ext/date.rb +5 -5
  37. data/lib/active_support/core_ext/date_and_time/compatibility.rb +1 -9
  38. data/lib/active_support/core_ext/date_time/blank.rb +4 -0
  39. data/lib/active_support/core_ext/date_time/compatibility.rb +3 -5
  40. data/lib/active_support/core_ext/date_time/conversions.rb +4 -6
  41. data/lib/active_support/core_ext/date_time.rb +5 -5
  42. data/lib/active_support/core_ext/digest/uuid.rb +6 -0
  43. data/lib/active_support/core_ext/digest.rb +1 -1
  44. data/lib/active_support/core_ext/enumerable.rb +25 -8
  45. data/lib/active_support/core_ext/erb/util.rb +10 -5
  46. data/lib/active_support/core_ext/file.rb +1 -1
  47. data/lib/active_support/core_ext/hash/deep_merge.rb +1 -0
  48. data/lib/active_support/core_ext/hash/except.rb +0 -12
  49. data/lib/active_support/core_ext/hash/keys.rb +4 -4
  50. data/lib/active_support/core_ext/hash.rb +8 -8
  51. data/lib/active_support/core_ext/integer.rb +3 -3
  52. data/lib/active_support/core_ext/kernel.rb +3 -3
  53. data/lib/active_support/core_ext/module/attr_internal.rb +16 -6
  54. data/lib/active_support/core_ext/module/delegation.rb +20 -163
  55. data/lib/active_support/core_ext/module/deprecation.rb +1 -4
  56. data/lib/active_support/core_ext/module/introspection.rb +3 -0
  57. data/lib/active_support/core_ext/module.rb +11 -11
  58. data/lib/active_support/core_ext/numeric/conversions.rb +3 -3
  59. data/lib/active_support/core_ext/numeric.rb +3 -3
  60. data/lib/active_support/core_ext/object/blank.rb +45 -1
  61. data/lib/active_support/core_ext/object/instance_variables.rb +11 -19
  62. data/lib/active_support/core_ext/object/json.rb +24 -11
  63. data/lib/active_support/core_ext/object/to_query.rb +7 -1
  64. data/lib/active_support/core_ext/object/try.rb +2 -2
  65. data/lib/active_support/core_ext/object/with.rb +5 -3
  66. data/lib/active_support/core_ext/object.rb +13 -13
  67. data/lib/active_support/core_ext/pathname/blank.rb +4 -0
  68. data/lib/active_support/core_ext/pathname.rb +2 -2
  69. data/lib/active_support/core_ext/range/overlap.rb +4 -4
  70. data/lib/active_support/core_ext/range/sole.rb +17 -0
  71. data/lib/active_support/core_ext/range.rb +4 -4
  72. data/lib/active_support/core_ext/securerandom.rb +4 -4
  73. data/lib/active_support/core_ext/string/conversions.rb +1 -1
  74. data/lib/active_support/core_ext/string/filters.rb +4 -4
  75. data/lib/active_support/core_ext/string/multibyte.rb +13 -4
  76. data/lib/active_support/core_ext/string/output_safety.rb +19 -19
  77. data/lib/active_support/core_ext/string.rb +13 -13
  78. data/lib/active_support/core_ext/symbol.rb +1 -1
  79. data/lib/active_support/core_ext/thread/backtrace/location.rb +2 -7
  80. data/lib/active_support/core_ext/time/calculations.rb +25 -30
  81. data/lib/active_support/core_ext/time/compatibility.rb +2 -3
  82. data/lib/active_support/core_ext/time/conversions.rb +2 -2
  83. data/lib/active_support/core_ext/time/zones.rb +1 -1
  84. data/lib/active_support/core_ext/time.rb +5 -5
  85. data/lib/active_support/core_ext.rb +1 -2
  86. data/lib/active_support/current_attributes/test_helper.rb +2 -2
  87. data/lib/active_support/current_attributes.rb +58 -50
  88. data/lib/active_support/delegation.rb +200 -0
  89. data/lib/active_support/dependencies/autoload.rb +0 -12
  90. data/lib/active_support/dependencies/interlock.rb +11 -5
  91. data/lib/active_support/dependencies.rb +6 -2
  92. data/lib/active_support/deprecation/constant_accessor.rb +47 -26
  93. data/lib/active_support/deprecation/proxy_wrappers.rb +9 -12
  94. data/lib/active_support/deprecation/reporting.rb +5 -17
  95. data/lib/active_support/deprecation.rb +8 -5
  96. data/lib/active_support/descendants_tracker.rb +9 -87
  97. data/lib/active_support/duration/iso8601_parser.rb +2 -2
  98. data/lib/active_support/duration/iso8601_serializer.rb +1 -2
  99. data/lib/active_support/duration.rb +25 -16
  100. data/lib/active_support/editor.rb +70 -0
  101. data/lib/active_support/encrypted_configuration.rb +20 -2
  102. data/lib/active_support/encrypted_file.rb +1 -1
  103. data/lib/active_support/error_reporter.rb +121 -6
  104. data/lib/active_support/event_reporter/test_helper.rb +32 -0
  105. data/lib/active_support/event_reporter.rb +592 -0
  106. data/lib/active_support/evented_file_update_checker.rb +5 -3
  107. data/lib/active_support/execution_context.rb +64 -7
  108. data/lib/active_support/execution_wrapper.rb +1 -2
  109. data/lib/active_support/file_update_checker.rb +9 -7
  110. data/lib/active_support/fork_tracker.rb +2 -38
  111. data/lib/active_support/gem_version.rb +2 -2
  112. data/lib/active_support/gzip.rb +1 -0
  113. data/lib/active_support/hash_with_indifferent_access.rb +66 -45
  114. data/lib/active_support/html_safe_translation.rb +3 -0
  115. data/lib/active_support/i18n_railtie.rb +19 -11
  116. data/lib/active_support/inflector/inflections.rb +31 -15
  117. data/lib/active_support/inflector/transliterate.rb +6 -8
  118. data/lib/active_support/isolated_execution_state.rb +12 -17
  119. data/lib/active_support/json/decoding.rb +6 -4
  120. data/lib/active_support/json/encoding.rb +157 -21
  121. data/lib/active_support/lazy_load_hooks.rb +1 -1
  122. data/lib/active_support/log_subscriber.rb +2 -18
  123. data/lib/active_support/logger.rb +15 -2
  124. data/lib/active_support/logger_thread_safe_level.rb +4 -9
  125. data/lib/active_support/message_encryptors.rb +54 -2
  126. data/lib/active_support/message_pack/extensions.rb +20 -2
  127. data/lib/active_support/message_verifier.rb +21 -0
  128. data/lib/active_support/message_verifiers.rb +57 -3
  129. data/lib/active_support/messages/rotation_coordinator.rb +9 -0
  130. data/lib/active_support/messages/rotator.rb +10 -0
  131. data/lib/active_support/multibyte/chars.rb +14 -4
  132. data/lib/active_support/multibyte.rb +4 -0
  133. data/lib/active_support/notifications/fanout.rb +68 -50
  134. data/lib/active_support/notifications/instrumenter.rb +22 -19
  135. data/lib/active_support/notifications.rb +28 -27
  136. data/lib/active_support/number_helper/number_converter.rb +2 -2
  137. data/lib/active_support/number_helper.rb +22 -0
  138. data/lib/active_support/option_merger.rb +2 -2
  139. data/lib/active_support/ordered_options.rb +53 -15
  140. data/lib/active_support/railtie.rb +36 -20
  141. data/lib/active_support/string_inquirer.rb +1 -1
  142. data/lib/active_support/structured_event_subscriber.rb +99 -0
  143. data/lib/active_support/subscriber.rb +1 -5
  144. data/lib/active_support/syntax_error_proxy.rb +3 -0
  145. data/lib/active_support/tagged_logging.rb +5 -1
  146. data/lib/active_support/test_case.rb +63 -6
  147. data/lib/active_support/testing/assertions.rb +113 -27
  148. data/lib/active_support/testing/constant_stubbing.rb +30 -8
  149. data/lib/active_support/testing/deprecation.rb +5 -12
  150. data/lib/active_support/testing/error_reporter_assertions.rb +18 -1
  151. data/lib/active_support/testing/event_reporter_assertions.rb +227 -0
  152. data/lib/active_support/testing/isolation.rb +19 -9
  153. data/lib/active_support/testing/method_call_assertions.rb +2 -16
  154. data/lib/active_support/testing/notification_assertions.rb +92 -0
  155. data/lib/active_support/testing/parallelization/server.rb +18 -2
  156. data/lib/active_support/testing/parallelization/worker.rb +4 -2
  157. data/lib/active_support/testing/parallelization.rb +25 -1
  158. data/lib/active_support/testing/tests_without_assertions.rb +19 -0
  159. data/lib/active_support/testing/time_helpers.rb +11 -6
  160. data/lib/active_support/time_with_zone.rb +39 -26
  161. data/lib/active_support/values/time_zone.rb +26 -17
  162. data/lib/active_support/xml_mini.rb +14 -4
  163. data/lib/active_support.rb +22 -9
  164. metadata +31 -17
  165. data/lib/active_support/core_ext/range/each.rb +0 -24
  166. data/lib/active_support/deprecation/instance_delegator.rb +0 -65
  167. data/lib/active_support/proxy_object.rb +0 -17
  168. data/lib/active_support/ruby_features.rb +0 -7
  169. data/lib/active_support/testing/strict_warnings.rb +0 -39
@@ -0,0 +1,145 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ # Provides a DSL for declaring a continuous integration workflow that can be run either locally or in the cloud.
5
+ # Each step is timed, reports success/error, and is aggregated into a collective report that reports total runtime,
6
+ # as well as whether the entire run was successful or not.
7
+ #
8
+ # Example:
9
+ #
10
+ # ActiveSupport::ContinuousIntegration.run do
11
+ # step "Setup", "bin/setup --skip-server"
12
+ # step "Style: Ruby", "bin/rubocop"
13
+ # step "Security: Gem audit", "bin/bundler-audit"
14
+ # step "Tests: Rails", "bin/rails test test:system"
15
+ #
16
+ # if success?
17
+ # step "Signoff: Ready for merge and deploy", "gh signoff"
18
+ # else
19
+ # failure "Skipping signoff; CI failed.", "Fix the issues and try again."
20
+ # end
21
+ # end
22
+ #
23
+ # Starting with Rails 8.1, a default `bin/ci` and `config/ci.rb` file are created to provide out-of-the-box CI.
24
+ class ContinuousIntegration
25
+ COLORS = {
26
+ banner: "\033[1;32m", # Green
27
+ title: "\033[1;35m", # Purple
28
+ subtitle: "\033[1;90m", # Medium Gray
29
+ error: "\033[1;31m", # Red
30
+ success: "\033[1;32m" # Green
31
+ }
32
+
33
+ attr_reader :results
34
+
35
+ # Perform a CI run. Execute each step, show their results and runtime, and exit with a non-zero status if there are any failures.
36
+ #
37
+ # Pass an optional title, subtitle, and a block that declares the steps to be executed.
38
+ #
39
+ # Sets the CI environment variable to "true" to allow for conditional behavior in the app, like enabling eager loading and disabling logging.
40
+ #
41
+ # Example:
42
+ #
43
+ # ActiveSupport::ContinuousIntegration.run do
44
+ # step "Setup", "bin/setup --skip-server"
45
+ # step "Style: Ruby", "bin/rubocop"
46
+ # step "Security: Gem audit", "bin/bundler-audit"
47
+ # step "Tests: Rails", "bin/rails test test:system"
48
+ #
49
+ # if success?
50
+ # step "Signoff: Ready for merge and deploy", "gh signoff"
51
+ # else
52
+ # failure "Skipping signoff; CI failed.", "Fix the issues and try again."
53
+ # end
54
+ # end
55
+ def self.run(title = "Continuous Integration", subtitle = "Running tests, style checks, and security audits", &block)
56
+ new.tap do |ci|
57
+ ENV["CI"] = "true"
58
+ ci.heading title, subtitle, padding: false
59
+ ci.report(title, &block)
60
+ abort unless ci.success?
61
+ end
62
+ end
63
+
64
+ def initialize
65
+ @results = []
66
+ end
67
+
68
+ # Declare a step with a title and a command. The command can either be given as a single string or as multiple
69
+ # strings that will be passed to `system` as individual arguments (and therefore correctly escaped for paths etc).
70
+ #
71
+ # Examples:
72
+ #
73
+ # step "Setup", "bin/setup"
74
+ # step "Single test", "bin/rails", "test", "--name", "test_that_is_one"
75
+ def step(title, *command)
76
+ heading title, command.join(" "), type: :title
77
+ report(title) { results << system(*command) }
78
+ end
79
+
80
+ # Returns true if all steps were successful.
81
+ def success?
82
+ results.all?
83
+ end
84
+
85
+ # Display an error heading with the title and optional subtitle to reflect that the run failed.
86
+ def failure(title, subtitle = nil)
87
+ heading title, subtitle, type: :error
88
+ end
89
+
90
+ # Display a colorized heading followed by an optional subtitle.
91
+ #
92
+ # Examples:
93
+ #
94
+ # heading "Smoke Testing", "End-to-end tests verifying key functionality", padding: false
95
+ # heading "Skipping video encoding tests", "Install FFmpeg to run these tests", type: :error
96
+ #
97
+ # See ActiveSupport::ContinuousIntegration::COLORS for a complete list of options.
98
+ def heading(heading, subtitle = nil, type: :banner, padding: true)
99
+ echo "#{padding ? "\n\n" : ""}#{heading}", type: type
100
+ echo "#{subtitle}#{padding ? "\n" : ""}", type: :subtitle if subtitle
101
+ end
102
+
103
+ # Echo text to the terminal in the color corresponding to the type of the text.
104
+ #
105
+ # Examples:
106
+ #
107
+ # echo "This is going to be green!", type: :success
108
+ # echo "This is going to be red!", type: :error
109
+ #
110
+ # See ActiveSupport::ContinuousIntegration::COLORS for a complete list of options.
111
+ def echo(text, type:)
112
+ puts colorize(text, type)
113
+ end
114
+
115
+ # :nodoc:
116
+ def report(title, &block)
117
+ Signal.trap("INT") { abort colorize(:error, "\n❌ #{title} interrupted") }
118
+
119
+ ci = self.class.new
120
+ elapsed = timing { ci.instance_eval(&block) }
121
+
122
+ if ci.success?
123
+ echo "\n✅ #{title} passed in #{elapsed}", type: :success
124
+ else
125
+ echo "\n❌ #{title} failed in #{elapsed}", type: :error
126
+ end
127
+
128
+ results.concat ci.results
129
+ ensure
130
+ Signal.trap("INT", "-")
131
+ end
132
+
133
+ private
134
+ def timing
135
+ started_at = Time.now.to_f
136
+ yield
137
+ min, sec = (Time.now.to_f - started_at).divmod(60)
138
+ "#{"#{min}m" if min > 0}%.2fs" % sec
139
+ end
140
+
141
+ def colorize(text, type)
142
+ "#{COLORS.fetch(type)}#{text}\033[0m"
143
+ end
144
+ end
145
+ end
@@ -16,11 +16,11 @@ class Array
16
16
  # ==== Options
17
17
  #
18
18
  # * <tt>:words_connector</tt> - The sign or word used to join all but the last
19
- # element in arrays with three or more elements (default: ", ").
19
+ # element in arrays with three or more elements (default: <tt>", "</tt>).
20
20
  # * <tt>:last_word_connector</tt> - The sign or word used to join the last element
21
- # in arrays with three or more elements (default: ", and ").
21
+ # in arrays with three or more elements (default: <tt>", and "</tt>).
22
22
  # * <tt>:two_words_connector</tt> - The sign or word used to join the elements
23
- # in arrays with two elements (default: " and ").
23
+ # in arrays with two elements (default: <tt>" and "</tt>).
24
24
  # * <tt>:locale</tt> - If +i18n+ is available, you can set a locale and use
25
25
  # the connector options defined on the 'support.array' namespace in the
26
26
  # corresponding dictionary file.
@@ -104,8 +104,6 @@ class Array
104
104
  end
105
105
  end
106
106
  alias_method :to_formatted_s, :to_fs
107
- alias_method :to_default_s, :to_s
108
- deprecate to_default_s: :to_s, deprecator: ActiveSupport.deprecator
109
107
 
110
108
  # Returns a string that represents the array in XML by invoking +to_xml+
111
109
  # on each element. Active Record collections delegate their representation
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/array/wrap"
4
- require "active_support/core_ext/array/access"
5
- require "active_support/core_ext/array/conversions"
6
- require "active_support/core_ext/array/extract"
7
- require "active_support/core_ext/array/extract_options"
8
- require "active_support/core_ext/array/grouping"
9
- require "active_support/core_ext/array/inquiry"
3
+ require_relative "array/wrap"
4
+ require_relative "array/access"
5
+ require_relative "array/conversions"
6
+ require_relative "array/extract"
7
+ require_relative "array/extract_options"
8
+ require_relative "array/grouping"
9
+ require_relative "array/inquiry"
@@ -1,16 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "benchmark"
4
-
5
- class << Benchmark
6
- # Benchmark realtime in milliseconds.
7
- #
8
- # Benchmark.realtime { User.all }
9
- # # => 8.0e-05
10
- #
11
- # Benchmark.ms { User.all }
12
- # # => 0.074
13
- def ms(&block)
14
- 1000 * realtime(&block)
15
- end
16
- end
3
+ # Remove this file from activesupport/lib/active_support/core_ext.rb when deleting the deprecation.
4
+ ActiveSupport.deprecator.warn <<~TEXT
5
+ active_support/core_ext/benchmark.rb is deprecated and will be removed in Rails 8.2 without replacement.
6
+ TEXT
@@ -1,3 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/big_decimal/conversions"
3
+ require_relative "big_decimal/conversions"
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/core_ext/module/redefine_method"
4
+ require "active_support/class_attribute"
4
5
 
5
6
  class Class
6
7
  # Declare a class-level attribute whose value is inheritable by subclasses.
@@ -83,31 +84,39 @@ class Class
83
84
  #
84
85
  # class_attribute :settings, default: {}
85
86
  def class_attribute(*attrs, instance_accessor: true,
86
- instance_reader: instance_accessor, instance_writer: instance_accessor, instance_predicate: true, default: nil)
87
+ instance_reader: instance_accessor, instance_writer: instance_accessor, instance_predicate: true, default: nil
88
+ )
87
89
  class_methods, methods = [], []
88
90
  attrs.each do |name|
89
91
  unless name.is_a?(Symbol) || name.is_a?(String)
90
92
  raise TypeError, "#{name.inspect} is not a symbol nor a string"
91
93
  end
92
94
 
93
- class_methods << <<~RUBY # In case the method exists and is not public
94
- silence_redefinition_of_method def #{name}
95
- end
96
- RUBY
95
+ name = name.to_sym
96
+ namespaced_name = :"__class_attr_#{name}"
97
+ ::ActiveSupport::ClassAttribute.redefine(self, name, namespaced_name, default)
97
98
 
98
- methods << <<~RUBY if instance_reader
99
- silence_redefinition_of_method def #{name}
100
- defined?(@#{name}) ? @#{name} : self.class.#{name}
101
- end
102
- RUBY
99
+ class_methods << "def #{name}; #{namespaced_name}; end"
100
+ class_methods << "def #{name}=(value); self.#{namespaced_name} = value; end"
103
101
 
104
- class_methods << <<~RUBY
105
- silence_redefinition_of_method def #{name}=(value)
106
- redefine_method(:#{name}) { value } if singleton_class?
107
- redefine_singleton_method(:#{name}) { value }
108
- value
109
- end
110
- RUBY
102
+ if singleton_class?
103
+ methods << <<~RUBY if instance_reader
104
+ silence_redefinition_of_method(:#{name})
105
+ def #{name}
106
+ self.singleton_class.#{name}
107
+ end
108
+ RUBY
109
+ else
110
+ methods << <<~RUBY if instance_reader
111
+ silence_redefinition_of_method def #{name}
112
+ if defined?(@#{name})
113
+ @#{name}
114
+ else
115
+ self.class.#{name}
116
+ end
117
+ end
118
+ RUBY
119
+ end
111
120
 
112
121
  methods << <<~RUBY if instance_writer
113
122
  silence_redefinition_of_method(:#{name}=)
@@ -124,7 +133,5 @@ class Class
124
133
 
125
134
  location = caller_locations(1, 1).first
126
135
  class_eval(["class << self", *class_methods, "end", *methods].join(";").tr("\n", ";"), location.path, location.lineno)
127
-
128
- attrs.each { |name| public_send("#{name}=", default) }
129
136
  end
130
137
  end
@@ -1,43 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/ruby_features"
4
3
  require "active_support/descendants_tracker"
5
4
 
6
5
  class Class
7
- if ActiveSupport::RubyFeatures::CLASS_SUBCLASSES
8
- # Returns an array with all classes that are < than its receiver.
9
- #
10
- # class C; end
11
- # C.descendants # => []
12
- #
13
- # class B < C; end
14
- # C.descendants # => [B]
15
- #
16
- # class A < B; end
17
- # C.descendants # => [B, A]
18
- #
19
- # class D < C; end
20
- # C.descendants # => [B, A, D]
21
- def descendants
22
- subclasses.concat(subclasses.flat_map(&:descendants))
23
- end
24
- else
25
- def descendants
26
- ObjectSpace.each_object(singleton_class).reject do |k|
27
- k.singleton_class? || k == self
28
- end
29
- end
30
-
31
- # Returns an array with the direct children of +self+.
32
- #
33
- # class Foo; end
34
- # class Bar < Foo; end
35
- # class Baz < Bar; end
36
- #
37
- # Foo.subclasses # => [Bar]
38
- def subclasses
39
- descendants.select { |descendant| descendant.superclass == self }
40
- end
6
+ # Returns an array with all classes that are < than its receiver.
7
+ #
8
+ # class C; end
9
+ # C.descendants # => []
10
+ #
11
+ # class B < C; end
12
+ # C.descendants # => [B]
13
+ #
14
+ # class A < B; end
15
+ # C.descendants # => [B, A]
16
+ #
17
+ # class D < C; end
18
+ # C.descendants # => [B, A, D]
19
+ def descendants
20
+ subclasses.concat(subclasses.flat_map(&:descendants))
41
21
  end
42
22
 
43
23
  prepend ActiveSupport::DescendantsTracker::ReloadedClassesFiltering
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/class/attribute"
4
- require "active_support/core_ext/class/subclasses"
3
+ require_relative "class/attribute"
4
+ require_relative "class/subclasses"
@@ -11,4 +11,8 @@ class Date # :nodoc:
11
11
  def blank?
12
12
  false
13
13
  end
14
+
15
+ def present?
16
+ true
17
+ end
14
18
  end
@@ -17,6 +17,7 @@ class Date
17
17
  date.strftime("%B #{day_format}, %Y") # => "April 25th, 2007"
18
18
  },
19
19
  rfc822: "%d %b %Y",
20
+ rfc2822: "%d %b %Y",
20
21
  iso8601: lambda { |date| date.iso8601 }
21
22
  }
22
23
 
@@ -34,6 +35,7 @@ class Date
34
35
  # date.to_fs(:long) # => "November 10, 2007"
35
36
  # date.to_fs(:long_ordinal) # => "November 10th, 2007"
36
37
  # date.to_fs(:rfc822) # => "10 Nov 2007"
38
+ # date.to_fs(:rfc2822) # => "10 Nov 2007"
37
39
  # date.to_fs(:iso8601) # => "2007-11-10"
38
40
  #
39
41
  # == Adding your own date formats to to_fs
@@ -56,8 +58,6 @@ class Date
56
58
  end
57
59
  end
58
60
  alias_method :to_formatted_s, :to_fs
59
- alias_method :to_default_s, :to_s
60
- deprecate to_default_s: :to_s, deprecator: ActiveSupport.deprecator
61
61
 
62
62
  # Overrides the default inspect method with a human readable one, e.g., "Mon, 21 Feb 2005"
63
63
  def readable_inspect
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/date/acts_like"
4
- require "active_support/core_ext/date/blank"
5
- require "active_support/core_ext/date/calculations"
6
- require "active_support/core_ext/date/conversions"
7
- require "active_support/core_ext/date/zones"
3
+ require_relative "date/acts_like"
4
+ require_relative "date/blank"
5
+ require_relative "date/calculations"
6
+ require_relative "date/conversions"
7
+ require_relative "date/zones"
@@ -1,18 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/core_ext/module/attribute_accessors"
4
+ require "active_support/core_ext/module/redefine_method"
4
5
 
5
6
  module DateAndTime
6
7
  module Compatibility
7
- # If true, +to_time+ preserves the timezone offset of receiver.
8
- #
9
- # NOTE: With Ruby 2.4+ the default for +to_time+ changed from
10
- # converting to the local system time, to preserving the offset
11
- # of the receiver. For backwards compatibility we're overriding
12
- # this behavior, but new apps will have an initializer that sets
13
- # this to true, because the new behavior is preferred.
14
- mattr_accessor :preserve_timezone, instance_writer: false, default: false
15
-
16
8
  # Change the output of <tt>ActiveSupport::TimeZone.utc_to_local</tt>.
17
9
  #
18
10
  # When +true+, it returns local times with a UTC offset, with +false+ local
@@ -11,4 +11,8 @@ class DateTime # :nodoc:
11
11
  def blank?
12
12
  false
13
13
  end
14
+
15
+ def present?
16
+ true
17
+ end
14
18
  end
@@ -8,11 +8,9 @@ class DateTime
8
8
 
9
9
  silence_redefinition_of_method :to_time
10
10
 
11
- # Either return an instance of +Time+ with the same UTC offset
12
- # as +self+ or an instance of +Time+ representing the same time
13
- # in the local system timezone depending on the setting of
14
- # on the setting of +ActiveSupport.to_time_preserves_timezone+.
11
+ # Return an instance of +Time+ with the same UTC offset
12
+ # as +self+.
15
13
  def to_time
16
- preserve_timezone ? getlocal(utc_offset) : getlocal
14
+ getlocal(utc_offset)
17
15
  end
18
16
  end
@@ -11,7 +11,8 @@ class DateTime
11
11
  #
12
12
  # This method is aliased to <tt>to_formatted_s</tt>.
13
13
  #
14
- # === Examples
14
+ # ==== Examples
15
+ #
15
16
  # datetime = DateTime.civil(2007, 12, 4, 0, 0, 0, 0) # => Tue, 04 Dec 2007 00:00:00 +0000
16
17
  #
17
18
  # datetime.to_fs(:db) # => "2007-12-04 00:00:00"
@@ -23,7 +24,8 @@ class DateTime
23
24
  # datetime.to_fs(:rfc822) # => "Tue, 04 Dec 2007 00:00:00 +0000"
24
25
  # datetime.to_fs(:iso8601) # => "2007-12-04T00:00:00+00:00"
25
26
  #
26
- # == Adding your own datetime formats to to_fs
27
+ # ==== Adding your own datetime formats to +to_fs+
28
+ #
27
29
  # DateTime formats are shared with Time. You can add your own to the
28
30
  # Time::DATE_FORMATS hash. Use the format name as the hash key and
29
31
  # either a strftime string or Proc instance that takes a time or
@@ -40,10 +42,6 @@ class DateTime
40
42
  end
41
43
  end
42
44
  alias_method :to_formatted_s, :to_fs
43
- if instance_methods(false).include?(:to_s)
44
- alias_method :to_default_s, :to_s
45
- deprecate to_default_s: :to_s, deprecator: ActiveSupport.deprecator
46
- end
47
45
 
48
46
 
49
47
  # Returns a formatted string of the offset from UTC, or an alternative
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/date_time/acts_like"
4
- require "active_support/core_ext/date_time/blank"
5
- require "active_support/core_ext/date_time/calculations"
6
- require "active_support/core_ext/date_time/compatibility"
7
- require "active_support/core_ext/date_time/conversions"
3
+ require_relative "date_time/acts_like"
4
+ require_relative "date_time/blank"
5
+ require_relative "date_time/calculations"
6
+ require_relative "date_time/compatibility"
7
+ require_relative "date_time/conversions"
@@ -53,6 +53,12 @@ module Digest
53
53
  SecureRandom.uuid
54
54
  end
55
55
 
56
+ # Returns the nil UUID. This is a special form of UUID that is specified to
57
+ # have all 128 bits set to zero.
58
+ def self.nil_uuid
59
+ "00000000-0000-0000-0000-000000000000"
60
+ end
61
+
56
62
  def self.pack_uuid_namespace(namespace)
57
63
  if [DNS_NAMESPACE, OID_NAMESPACE, URL_NAMESPACE, X500_NAMESPACE].include?(namespace)
58
64
  namespace
@@ -1,3 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/digest/uuid"
3
+ require_relative "digest/uuid"
@@ -192,22 +192,39 @@ module Enumerable
192
192
  # # => [ Person.find(1), Person.find(5), Person.find(3) ]
193
193
  #
194
194
  # If the +series+ include keys that have no corresponding element in the Enumerable, these are ignored.
195
- # If the Enumerable has additional elements that aren't named in the +series+, these are not included in the result.
196
- def in_order_of(key, series)
197
- group_by(&key).values_at(*series).flatten(1).compact
195
+ # If the Enumerable has additional elements that aren't named in the +series+, these are not included in the result, unless
196
+ # the +filter+ option is set to +false+.
197
+ def in_order_of(key, series, filter: true)
198
+ if filter
199
+ group_by(&key).values_at(*series).flatten(1).compact
200
+ else
201
+ sort_by { |v| series.index(v.public_send(key)) || series.size }.compact
202
+ end
198
203
  end
199
204
 
200
205
  # Returns the sole item in the enumerable. If there are no items, or more
201
- # than one item, raises +Enumerable::SoleItemExpectedError+.
206
+ # than one item, raises Enumerable::SoleItemExpectedError.
202
207
  #
203
208
  # ["x"].sole # => "x"
204
209
  # Set.new.sole # => Enumerable::SoleItemExpectedError: no item found
205
210
  # { a: 1, b: 2 }.sole # => Enumerable::SoleItemExpectedError: multiple items found
206
211
  def sole
207
- case count
208
- when 1 then return first # rubocop:disable Style/RedundantReturn
209
- when 0 then raise ActiveSupport::EnumerableCoreExt::SoleItemExpectedError, "no item found"
210
- when 2.. then raise ActiveSupport::EnumerableCoreExt::SoleItemExpectedError, "multiple items found"
212
+ result = nil
213
+ found = false
214
+
215
+ each do |*element|
216
+ if found
217
+ raise SoleItemExpectedError, "multiple items found"
218
+ end
219
+
220
+ result = element.size == 1 ? element[0] : element
221
+ found = true
222
+ end
223
+
224
+ if found
225
+ result
226
+ else
227
+ raise SoleItemExpectedError, "no item found"
211
228
  end
212
229
  end
213
230
  end
@@ -12,7 +12,7 @@ module ActiveSupport
12
12
  if s.html_safe?
13
13
  s
14
14
  else
15
- super(ActiveSupport::Multibyte::Unicode.tidy_bytes(s))
15
+ super(s)
16
16
  end
17
17
  end
18
18
  alias :unwrapped_html_escape :html_escape # :nodoc:
@@ -61,7 +61,7 @@ class ERB
61
61
  # html_escape_once('&lt;&lt; Accept & Checkout')
62
62
  # # => "&lt;&lt; Accept &amp; Checkout"
63
63
  def html_escape_once(s)
64
- ActiveSupport::Multibyte::Unicode.tidy_bytes(s.to_s).gsub(HTML_ESCAPE_ONCE_REGEXP, HTML_ESCAPE).html_safe
64
+ s.to_s.gsub(HTML_ESCAPE_ONCE_REGEXP, HTML_ESCAPE).html_safe
65
65
  end
66
66
 
67
67
  module_function :html_escape_once
@@ -169,12 +169,12 @@ class ERB
169
169
  while !source.eos?
170
170
  pos = source.pos
171
171
  source.scan_until(/(?:#{start_re}|#{finish_re})/)
172
- raise NotImplementedError if source.matched.nil?
172
+ return [[:PLAIN, source.string]] unless source.matched?
173
173
  len = source.pos - source.matched.bytesize - pos
174
174
 
175
175
  case source.matched
176
176
  when start_re
177
- tokens << [:TEXT, source.string[pos, len]] if len > 0
177
+ tokens << [:TEXT, source.string.byteslice(pos, len)] if len > 0
178
178
  tokens << [:OPEN, source.matched]
179
179
  if source.scan(/(.*?)(?=#{finish_re}|\z)/m)
180
180
  tokens << [:CODE, source.matched] unless source.matched.empty?
@@ -183,11 +183,16 @@ class ERB
183
183
  raise NotImplementedError
184
184
  end
185
185
  when finish_re
186
- tokens << [:CODE, source.string[pos, len]] if len > 0
186
+ tokens << [:CODE, source.string.byteslice(pos, len)] if len > 0
187
187
  tokens << [:CLOSE, source.matched]
188
188
  else
189
189
  raise NotImplementedError, source.matched
190
190
  end
191
+
192
+ unless source.eos? || source.exist?(start_re) || source.exist?(finish_re)
193
+ tokens << [:TEXT, source.rest]
194
+ source.terminate
195
+ end
191
196
  end
192
197
 
193
198
  tokens
@@ -1,3 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/file/atomic"
3
+ require_relative "file/atomic"
@@ -36,6 +36,7 @@ class Hash
36
36
  #--
37
37
  # Implemented by ActiveSupport::DeepMergeable#deep_merge!.
38
38
 
39
+ ##
39
40
  def deep_merge?(other) # :nodoc:
40
41
  other.is_a?(Hash)
41
42
  end
@@ -1,18 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Hash
4
- # Returns a hash that includes everything except given keys.
5
- # hash = { a: true, b: false, c: nil }
6
- # hash.except(:c) # => { a: true, b: false }
7
- # hash.except(:a, :b) # => { c: nil }
8
- # hash # => { a: true, b: false, c: nil }
9
- #
10
- # This is useful for limiting a set of parameters to everything but a few known toggles:
11
- # @person.update(params[:person].except(:admin))
12
- def except(*keys)
13
- slice(*self.keys - keys)
14
- end unless method_defined?(:except)
15
-
16
4
  # Removes the given keys from hash and returns it.
17
5
  # hash = { a: true, b: false, c: nil }
18
6
  # hash.except!(:c) # => { a: true, b: false }