activesupport 6.1.4.3 → 7.0.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activesupport might be problematic. Click here for more details.

Files changed (129) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +151 -536
  3. data/MIT-LICENSE +1 -1
  4. data/lib/active_support/actionable_error.rb +1 -1
  5. data/lib/active_support/array_inquirer.rb +0 -2
  6. data/lib/active_support/benchmarkable.rb +2 -2
  7. data/lib/active_support/cache/file_store.rb +15 -9
  8. data/lib/active_support/cache/mem_cache_store.rb +119 -28
  9. data/lib/active_support/cache/memory_store.rb +21 -13
  10. data/lib/active_support/cache/null_store.rb +10 -2
  11. data/lib/active_support/cache/redis_cache_store.rb +39 -59
  12. data/lib/active_support/cache/strategy/local_cache.rb +29 -49
  13. data/lib/active_support/cache.rb +189 -45
  14. data/lib/active_support/callbacks.rb +35 -31
  15. data/lib/active_support/concern.rb +5 -5
  16. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +2 -4
  17. data/lib/active_support/concurrency/share_lock.rb +2 -2
  18. data/lib/active_support/configurable.rb +6 -3
  19. data/lib/active_support/configuration_file.rb +1 -1
  20. data/lib/active_support/core_ext/array/access.rb +1 -5
  21. data/lib/active_support/core_ext/array/conversions.rb +6 -6
  22. data/lib/active_support/core_ext/array/grouping.rb +6 -6
  23. data/lib/active_support/core_ext/big_decimal/conversions.rb +1 -1
  24. data/lib/active_support/core_ext/date/blank.rb +1 -1
  25. data/lib/active_support/core_ext/date/calculations.rb +2 -2
  26. data/lib/active_support/core_ext/date_time/blank.rb +1 -1
  27. data/lib/active_support/core_ext/digest/uuid.rb +13 -12
  28. data/lib/active_support/core_ext/enumerable.rb +64 -12
  29. data/lib/active_support/core_ext/file/atomic.rb +1 -1
  30. data/lib/active_support/core_ext/hash/keys.rb +1 -1
  31. data/lib/active_support/core_ext/kernel/reporting.rb +4 -4
  32. data/lib/active_support/core_ext/module/delegation.rb +2 -8
  33. data/lib/active_support/core_ext/name_error.rb +2 -8
  34. data/lib/active_support/core_ext/numeric/conversions.rb +2 -2
  35. data/lib/active_support/core_ext/object/blank.rb +2 -2
  36. data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
  37. data/lib/active_support/core_ext/object/duplicable.rb +11 -0
  38. data/lib/active_support/core_ext/object/json.rb +29 -24
  39. data/lib/active_support/core_ext/object/to_query.rb +2 -2
  40. data/lib/active_support/core_ext/object/try.rb +20 -20
  41. data/lib/active_support/core_ext/range/compare_range.rb +0 -25
  42. data/lib/active_support/core_ext/range/each.rb +1 -1
  43. data/lib/active_support/core_ext/range/include_time_with_zone.rb +1 -1
  44. data/lib/active_support/core_ext/string/filters.rb +1 -1
  45. data/lib/active_support/core_ext/string/inflections.rb +1 -1
  46. data/lib/active_support/core_ext/string/output_safety.rb +60 -36
  47. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +0 -8
  48. data/lib/active_support/core_ext/time/calculations.rb +6 -5
  49. data/lib/active_support/core_ext/time/zones.rb +2 -17
  50. data/lib/active_support/core_ext/uri.rb +1 -15
  51. data/lib/active_support/current_attributes.rb +17 -1
  52. data/lib/active_support/dependencies/interlock.rb +10 -18
  53. data/lib/active_support/dependencies/require_dependency.rb +28 -0
  54. data/lib/active_support/dependencies.rb +58 -788
  55. data/lib/active_support/deprecation/behaviors.rb +4 -1
  56. data/lib/active_support/deprecation/method_wrappers.rb +3 -3
  57. data/lib/active_support/deprecation/proxy_wrappers.rb +1 -1
  58. data/lib/active_support/deprecation.rb +1 -1
  59. data/lib/active_support/descendants_tracker.rb +12 -9
  60. data/lib/active_support/digest.rb +5 -3
  61. data/lib/active_support/duration/iso8601_parser.rb +3 -3
  62. data/lib/active_support/duration/iso8601_serializer.rb +9 -1
  63. data/lib/active_support/duration.rb +77 -48
  64. data/lib/active_support/encrypted_configuration.rb +11 -1
  65. data/lib/active_support/encrypted_file.rb +1 -1
  66. data/lib/active_support/environment_inquirer.rb +1 -1
  67. data/lib/active_support/evented_file_update_checker.rb +1 -1
  68. data/lib/active_support/fork_tracker.rb +2 -4
  69. data/lib/active_support/gem_version.rb +4 -4
  70. data/lib/active_support/hash_with_indifferent_access.rb +3 -1
  71. data/lib/active_support/i18n.rb +1 -0
  72. data/lib/active_support/inflector/inflections.rb +11 -4
  73. data/lib/active_support/inflector/methods.rb +23 -47
  74. data/lib/active_support/json/encoding.rb +3 -3
  75. data/lib/active_support/key_generator.rb +18 -1
  76. data/lib/active_support/locale/en.yml +1 -1
  77. data/lib/active_support/log_subscriber.rb +13 -3
  78. data/lib/active_support/logger_thread_safe_level.rb +5 -13
  79. data/lib/active_support/message_encryptor.rb +3 -3
  80. data/lib/active_support/message_verifier.rb +4 -4
  81. data/lib/active_support/messages/metadata.rb +2 -2
  82. data/lib/active_support/multibyte/chars.rb +10 -11
  83. data/lib/active_support/multibyte/unicode.rb +2 -2
  84. data/lib/active_support/multibyte.rb +1 -1
  85. data/lib/active_support/notifications/fanout.rb +31 -11
  86. data/lib/active_support/notifications/instrumenter.rb +17 -0
  87. data/lib/active_support/notifications.rb +10 -0
  88. data/lib/active_support/number_helper/number_converter.rb +1 -3
  89. data/lib/active_support/number_helper/number_to_currency_converter.rb +11 -6
  90. data/lib/active_support/number_helper/number_to_delimited_converter.rb +1 -1
  91. data/lib/active_support/number_helper/number_to_human_size_converter.rb +1 -1
  92. data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -1
  93. data/lib/active_support/number_helper/rounding_helper.rb +1 -5
  94. data/lib/active_support/number_helper.rb +0 -2
  95. data/lib/active_support/option_merger.rb +4 -16
  96. data/lib/active_support/ordered_hash.rb +1 -1
  97. data/lib/active_support/parameter_filter.rb +5 -0
  98. data/lib/active_support/per_thread_registry.rb +1 -0
  99. data/lib/active_support/railtie.rb +34 -11
  100. data/lib/active_support/rescuable.rb +2 -2
  101. data/lib/active_support/secure_compare_rotator.rb +1 -1
  102. data/lib/active_support/string_inquirer.rb +0 -2
  103. data/lib/active_support/subscriber.rb +5 -0
  104. data/lib/active_support/tagged_logging.rb +1 -1
  105. data/lib/active_support/test_case.rb +9 -21
  106. data/lib/active_support/testing/assertions.rb +35 -5
  107. data/lib/active_support/testing/deprecation.rb +1 -1
  108. data/lib/active_support/testing/isolation.rb +1 -1
  109. data/lib/active_support/testing/method_call_assertions.rb +5 -5
  110. data/lib/active_support/testing/parallelization/server.rb +4 -0
  111. data/lib/active_support/testing/parallelization/worker.rb +3 -0
  112. data/lib/active_support/testing/parallelization.rb +4 -0
  113. data/lib/active_support/testing/parallelize_executor.rb +76 -0
  114. data/lib/active_support/testing/stream.rb +3 -5
  115. data/lib/active_support/testing/tagged_logging.rb +1 -1
  116. data/lib/active_support/testing/time_helpers.rb +13 -2
  117. data/lib/active_support/time_with_zone.rb +19 -6
  118. data/lib/active_support/values/time_zone.rb +25 -9
  119. data/lib/active_support/xml_mini/jdom.rb +1 -1
  120. data/lib/active_support/xml_mini/libxml.rb +5 -5
  121. data/lib/active_support/xml_mini/libxmlsax.rb +1 -1
  122. data/lib/active_support/xml_mini/nokogiri.rb +4 -4
  123. data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
  124. data/lib/active_support/xml_mini/rexml.rb +1 -1
  125. data/lib/active_support/xml_mini.rb +2 -1
  126. data/lib/active_support.rb +14 -1
  127. metadata +14 -28
  128. data/lib/active_support/core_ext/marshal.rb +0 -26
  129. data/lib/active_support/dependencies/zeitwerk_integration.rb +0 -117
@@ -19,8 +19,7 @@ require "active_support/core_ext/date/conversions"
19
19
  # The JSON gem adds a few modules to Ruby core classes containing :to_json definition, overwriting
20
20
  # their default behavior. That said, we need to define the basic to_json method in all of them,
21
21
  # otherwise they will always use to_json gem implementation, which is backwards incompatible in
22
- # several cases (for instance, the JSON implementation for Hash does not work) with inheritance
23
- # and consequently classes as ActiveSupport::OrderedHash cannot be serialized to json.
22
+ # several cases (for instance, the JSON implementation for Hash does not work) with inheritance.
24
23
  #
25
24
  # On the other hand, we should avoid conflict with ::JSON.{generate,dump}(obj). Unfortunately, the
26
25
  # JSON gem's encoder relies on its own to_json implementation to encode objects. Since it always
@@ -50,8 +49,14 @@ end
50
49
  klass.prepend(ActiveSupport::ToJsonWithActiveSupportEncoder)
51
50
  end
52
51
 
52
+ class Module
53
+ def as_json(options = nil) # :nodoc:
54
+ name
55
+ end
56
+ end
57
+
53
58
  class Object
54
- def as_json(options = nil) #:nodoc:
59
+ def as_json(options = nil) # :nodoc:
55
60
  if respond_to?(:to_hash)
56
61
  to_hash.as_json(options)
57
62
  else
@@ -60,44 +65,44 @@ class Object
60
65
  end
61
66
  end
62
67
 
63
- class Struct #:nodoc:
68
+ class Struct # :nodoc:
64
69
  def as_json(options = nil)
65
70
  Hash[members.zip(values)].as_json(options)
66
71
  end
67
72
  end
68
73
 
69
74
  class TrueClass
70
- def as_json(options = nil) #:nodoc:
75
+ def as_json(options = nil) # :nodoc:
71
76
  self
72
77
  end
73
78
  end
74
79
 
75
80
  class FalseClass
76
- def as_json(options = nil) #:nodoc:
81
+ def as_json(options = nil) # :nodoc:
77
82
  self
78
83
  end
79
84
  end
80
85
 
81
86
  class NilClass
82
- def as_json(options = nil) #:nodoc:
87
+ def as_json(options = nil) # :nodoc:
83
88
  self
84
89
  end
85
90
  end
86
91
 
87
92
  class String
88
- def as_json(options = nil) #:nodoc:
93
+ def as_json(options = nil) # :nodoc:
89
94
  self
90
95
  end
91
96
  end
92
97
 
93
98
  class Symbol
94
- def as_json(options = nil) #:nodoc:
99
+ def as_json(options = nil) # :nodoc:
95
100
  to_s
96
101
  end
97
102
  end
98
103
 
99
104
  class Numeric
100
- def as_json(options = nil) #:nodoc:
105
+ def as_json(options = nil) # :nodoc:
101
106
  self
102
107
  end
103
108
  end
@@ -105,7 +110,7 @@ end
105
110
  class Float
106
111
  # Encoding Infinity or NaN to JSON should return "null". The default returns
107
112
  # "Infinity" or "NaN" which are not valid JSON.
108
- def as_json(options = nil) #:nodoc:
113
+ def as_json(options = nil) # :nodoc:
109
114
  finite? ? self : nil
110
115
  end
111
116
  end
@@ -120,43 +125,43 @@ class BigDecimal
120
125
  # if the other end knows by contract that the data is supposed to be a
121
126
  # BigDecimal, it still has the chance to post-process the string and get the
122
127
  # real value.
123
- def as_json(options = nil) #:nodoc:
128
+ def as_json(options = nil) # :nodoc:
124
129
  finite? ? to_s : nil
125
130
  end
126
131
  end
127
132
 
128
133
  class Regexp
129
- def as_json(options = nil) #:nodoc:
134
+ def as_json(options = nil) # :nodoc:
130
135
  to_s
131
136
  end
132
137
  end
133
138
 
134
139
  module Enumerable
135
- def as_json(options = nil) #:nodoc:
140
+ def as_json(options = nil) # :nodoc:
136
141
  to_a.as_json(options)
137
142
  end
138
143
  end
139
144
 
140
145
  class IO
141
- def as_json(options = nil) #:nodoc:
146
+ def as_json(options = nil) # :nodoc:
142
147
  to_s
143
148
  end
144
149
  end
145
150
 
146
151
  class Range
147
- def as_json(options = nil) #:nodoc:
152
+ def as_json(options = nil) # :nodoc:
148
153
  to_s
149
154
  end
150
155
  end
151
156
 
152
157
  class Array
153
- def as_json(options = nil) #:nodoc:
158
+ def as_json(options = nil) # :nodoc:
154
159
  map { |v| options ? v.as_json(options.dup) : v.as_json }
155
160
  end
156
161
  end
157
162
 
158
163
  class Hash
159
- def as_json(options = nil) #:nodoc:
164
+ def as_json(options = nil) # :nodoc:
160
165
  # create a subset of the hash by applying :only or :except
161
166
  subset = if options
162
167
  if attrs = options[:only]
@@ -179,7 +184,7 @@ class Hash
179
184
  end
180
185
 
181
186
  class Time
182
- def as_json(options = nil) #:nodoc:
187
+ def as_json(options = nil) # :nodoc:
183
188
  if ActiveSupport::JSON::Encoding.use_standard_json_time_format
184
189
  xmlschema(ActiveSupport::JSON::Encoding.time_precision)
185
190
  else
@@ -189,7 +194,7 @@ class Time
189
194
  end
190
195
 
191
196
  class Date
192
- def as_json(options = nil) #:nodoc:
197
+ def as_json(options = nil) # :nodoc:
193
198
  if ActiveSupport::JSON::Encoding.use_standard_json_time_format
194
199
  strftime("%Y-%m-%d")
195
200
  else
@@ -199,7 +204,7 @@ class Date
199
204
  end
200
205
 
201
206
  class DateTime
202
- def as_json(options = nil) #:nodoc:
207
+ def as_json(options = nil) # :nodoc:
203
208
  if ActiveSupport::JSON::Encoding.use_standard_json_time_format
204
209
  xmlschema(ActiveSupport::JSON::Encoding.time_precision)
205
210
  else
@@ -208,13 +213,13 @@ class DateTime
208
213
  end
209
214
  end
210
215
 
211
- class URI::Generic #:nodoc:
216
+ class URI::Generic # :nodoc:
212
217
  def as_json(options = nil)
213
218
  to_s
214
219
  end
215
220
  end
216
221
 
217
- class Pathname #:nodoc:
222
+ class Pathname # :nodoc:
218
223
  def as_json(options = nil)
219
224
  to_s
220
225
  end
@@ -226,7 +231,7 @@ class IPAddr # :nodoc:
226
231
  end
227
232
  end
228
233
 
229
- class Process::Status #:nodoc:
234
+ class Process::Status # :nodoc:
230
235
  def as_json(options = nil)
231
236
  { exitstatus: exitstatus, pid: pid }
232
237
  end
@@ -75,11 +75,11 @@ class Hash
75
75
  #
76
76
  # This method is also aliased as +to_param+.
77
77
  def to_query(namespace = nil)
78
- query = collect do |key, value|
78
+ query = filter_map do |key, value|
79
79
  unless (value.is_a?(Hash) || value.is_a?(Array)) && value.empty?
80
80
  value.to_query(namespace ? "#{namespace}[#{key}]" : key)
81
81
  end
82
- end.compact
82
+ end
83
83
 
84
84
  query.sort! unless namespace.to_s.include?("[]")
85
85
  query.join("&")
@@ -3,32 +3,32 @@
3
3
  require "delegate"
4
4
 
5
5
  module ActiveSupport
6
- module Tryable #:nodoc:
7
- def try(method_name = nil, *args, &b)
8
- if method_name.nil? && block_given?
9
- if b.arity == 0
10
- instance_eval(&b)
6
+ module Tryable # :nodoc:
7
+ def try(*args, &block)
8
+ if args.empty? && block_given?
9
+ if block.arity == 0
10
+ instance_eval(&block)
11
11
  else
12
12
  yield self
13
13
  end
14
- elsif respond_to?(method_name)
15
- public_send(method_name, *args, &b)
14
+ elsif respond_to?(args.first)
15
+ public_send(*args, &block)
16
16
  end
17
17
  end
18
- ruby2_keywords(:try) if respond_to?(:ruby2_keywords, true)
18
+ ruby2_keywords(:try)
19
19
 
20
- def try!(method_name = nil, *args, &b)
21
- if method_name.nil? && block_given?
22
- if b.arity == 0
23
- instance_eval(&b)
20
+ def try!(*args, &block)
21
+ if args.empty? && block_given?
22
+ if block.arity == 0
23
+ instance_eval(&block)
24
24
  else
25
25
  yield self
26
26
  end
27
27
  else
28
- public_send(method_name, *args, &b)
28
+ public_send(*args, &block)
29
29
  end
30
30
  end
31
- ruby2_keywords(:try!) if respond_to?(:ruby2_keywords, true)
31
+ ruby2_keywords(:try!)
32
32
  end
33
33
  end
34
34
 
@@ -39,7 +39,7 @@ class Object
39
39
  # :method: try
40
40
  #
41
41
  # :call-seq:
42
- # try(*a, &b)
42
+ # try(*args, &block)
43
43
  #
44
44
  # Invokes the public method whose name goes as first argument just like
45
45
  # +public_send+ does, except that if the receiver does not respond to it the
@@ -104,7 +104,7 @@ class Object
104
104
  # :method: try!
105
105
  #
106
106
  # :call-seq:
107
- # try!(*a, &b)
107
+ # try!(*args, &block)
108
108
  #
109
109
  # Same as #try, but raises a +NoMethodError+ exception if the receiver is
110
110
  # not +nil+ and does not implement the tried method.
@@ -121,7 +121,7 @@ class Delegator
121
121
  # :method: try
122
122
  #
123
123
  # :call-seq:
124
- # try(a*, &b)
124
+ # try(*args, &block)
125
125
  #
126
126
  # See Object#try
127
127
 
@@ -129,7 +129,7 @@ class Delegator
129
129
  # :method: try!
130
130
  #
131
131
  # :call-seq:
132
- # try!(a*, &b)
132
+ # try!(*args, &block)
133
133
  #
134
134
  # See Object#try!
135
135
  end
@@ -145,14 +145,14 @@ class NilClass
145
145
  #
146
146
  # With +try+
147
147
  # @person.try(:children).try(:first).try(:name)
148
- def try(_method_name = nil, *)
148
+ def try(*)
149
149
  nil
150
150
  end
151
151
 
152
152
  # Calling +try!+ on +nil+ always returns +nil+.
153
153
  #
154
154
  # nil.try!(:name) # => nil
155
- def try!(_method_name = nil, *)
155
+ def try!(*)
156
156
  nil
157
157
  end
158
158
  end
@@ -51,31 +51,6 @@ module ActiveSupport
51
51
  super
52
52
  end
53
53
  end
54
-
55
- # Extends the default Range#cover? to support range comparisons.
56
- # (1..5).cover?(1..5) # => true
57
- # (1..5).cover?(2..3) # => true
58
- # (1..5).cover?(1...6) # => true
59
- # (1..5).cover?(2..6) # => false
60
- #
61
- # The native Range#cover? behavior is untouched.
62
- # ('a'..'f').cover?('c') # => true
63
- # (5..9).cover?(11) # => false
64
- #
65
- # The given range must be fully bounded, with both start and end.
66
- def cover?(value)
67
- if value.is_a?(::Range)
68
- is_backwards_op = value.exclude_end? ? :>= : :>
69
- return false if value.begin && value.end && value.begin.public_send(is_backwards_op, value.end)
70
- # 1...10 covers 1..9 but it does not cover 1..10.
71
- # 1..10 covers 1...11 but it does not cover 1...12.
72
- operator = exclude_end? && !value.exclude_end? ? :< : :<=
73
- value_max = !exclude_end? && value.exclude_end? ? value.max : value.last
74
- super(value.first) && (self.end.nil? || value_max.public_send(operator, last))
75
- else
76
- super
77
- end
78
- end
79
54
  end
80
55
  end
81
56
 
@@ -3,7 +3,7 @@
3
3
  require "active_support/time_with_zone"
4
4
 
5
5
  module ActiveSupport
6
- module EachTimeWithZone #:nodoc:
6
+ module EachTimeWithZone # :nodoc:
7
7
  def each(&block)
8
8
  ensure_iteration_allowed
9
9
  super
@@ -4,7 +4,7 @@ require "active_support/time_with_zone"
4
4
  require "active_support/deprecation"
5
5
 
6
6
  module ActiveSupport
7
- module IncludeTimeWithZone #:nodoc:
7
+ module IncludeTimeWithZone # :nodoc:
8
8
  # Extends the default Range#include? to support ActiveSupport::TimeWithZone.
9
9
  #
10
10
  # (1.hour.ago..1.hour.from_now).include?(Time.current) # => true
@@ -106,7 +106,7 @@ class String
106
106
  self.class.new.tap do |cut|
107
107
  cut_at = truncate_at - omission.bytesize
108
108
 
109
- scan(/\X/) do |grapheme|
109
+ each_grapheme_cluster do |grapheme|
110
110
  if cut.bytesize + grapheme.bytesize <= cut_at
111
111
  cut << grapheme
112
112
  else
@@ -260,7 +260,7 @@ class String
260
260
  # 'author_id'.humanize # => "Author"
261
261
  # 'author_id'.humanize(capitalize: false) # => "author"
262
262
  # '_id'.humanize # => "Id"
263
- # 'author_id'.humanize(keep_id_suffix: true) # => "Author Id"
263
+ # 'author_id'.humanize(keep_id_suffix: true) # => "Author id"
264
264
  #
265
265
  # See ActiveSupport::Inflector.humanize.
266
266
  def humanize(capitalize: true, keep_id_suffix: false)
@@ -130,7 +130,7 @@ class Numeric
130
130
  end
131
131
  end
132
132
 
133
- module ActiveSupport #:nodoc:
133
+ module ActiveSupport # :nodoc:
134
134
  class SafeBuffer < String
135
135
  UNSAFE_STRING_METHODS = %w(
136
136
  capitalize chomp chop delete delete_prefix delete_suffix
@@ -184,27 +184,30 @@ module ActiveSupport #:nodoc:
184
184
  end
185
185
 
186
186
  def concat(value)
187
- super(html_escape_interpolated_argument(value))
187
+ unless value.nil?
188
+ super(implicit_html_escape_interpolated_argument(value))
189
+ end
190
+ self
188
191
  end
189
192
  alias << concat
190
193
 
191
194
  def insert(index, value)
192
- super(index, html_escape_interpolated_argument(value))
195
+ super(index, implicit_html_escape_interpolated_argument(value))
193
196
  end
194
197
 
195
198
  def prepend(value)
196
- super(html_escape_interpolated_argument(value))
199
+ super(implicit_html_escape_interpolated_argument(value))
197
200
  end
198
201
 
199
202
  def replace(value)
200
- super(html_escape_interpolated_argument(value))
203
+ super(implicit_html_escape_interpolated_argument(value))
201
204
  end
202
205
 
203
206
  def []=(*args)
204
207
  if args.length == 3
205
- super(args[0], args[1], html_escape_interpolated_argument(args[2]))
208
+ super(args[0], args[1], implicit_html_escape_interpolated_argument(args[2]))
206
209
  else
207
- super(args[0], html_escape_interpolated_argument(args[1]))
210
+ super(args[0], implicit_html_escape_interpolated_argument(args[1]))
208
211
  end
209
212
  end
210
213
 
@@ -222,9 +225,9 @@ module ActiveSupport #:nodoc:
222
225
  def %(args)
223
226
  case args
224
227
  when Hash
225
- escaped_args = args.transform_values { |arg| html_escape_interpolated_argument(arg) }
228
+ escaped_args = args.transform_values { |arg| explicit_html_escape_interpolated_argument(arg) }
226
229
  else
227
- escaped_args = Array(args).map { |arg| html_escape_interpolated_argument(arg) }
230
+ escaped_args = Array(args).map { |arg| explicit_html_escape_interpolated_argument(arg) }
228
231
  end
229
232
 
230
233
  self.class.new(super(escaped_args))
@@ -262,39 +265,60 @@ module ActiveSupport #:nodoc:
262
265
  end
263
266
 
264
267
  UNSAFE_STRING_METHODS_WITH_BACKREF.each do |unsafe_method|
265
- if unsafe_method.respond_to?(unsafe_method)
266
- class_eval <<-EOT, __FILE__, __LINE__ + 1
267
- def #{unsafe_method}(*args, &block) # def gsub(*args, &block)
268
- if block # if block
269
- to_str.#{unsafe_method}(*args) { |*params| # to_str.gsub(*args) { |*params|
270
- set_block_back_references(block, $~) # set_block_back_references(block, $~)
271
- block.call(*params) # block.call(*params)
272
- } # }
273
- else # else
274
- to_str.#{unsafe_method}(*args) # to_str.gsub(*args)
275
- end # end
276
- end # end
277
-
278
- def #{unsafe_method}!(*args, &block) # def gsub!(*args, &block)
279
- @html_safe = false # @html_safe = false
280
- if block # if block
281
- super(*args) { |*params| # super(*args) { |*params|
282
- set_block_back_references(block, $~) # set_block_back_references(block, $~)
283
- block.call(*params) # block.call(*params)
284
- } # }
285
- else # else
286
- super # super
287
- end # end
288
- end # end
289
- EOT
290
- end
268
+ class_eval <<-EOT, __FILE__, __LINE__ + 1
269
+ def #{unsafe_method}(*args, &block) # def gsub(*args, &block)
270
+ if block # if block
271
+ to_str.#{unsafe_method}(*args) { |*params| # to_str.gsub(*args) { |*params|
272
+ set_block_back_references(block, $~) # set_block_back_references(block, $~)
273
+ block.call(*params) # block.call(*params)
274
+ } # }
275
+ else # else
276
+ to_str.#{unsafe_method}(*args) # to_str.gsub(*args)
277
+ end # end
278
+ end # end
279
+
280
+ def #{unsafe_method}!(*args, &block) # def gsub!(*args, &block)
281
+ @html_safe = false # @html_safe = false
282
+ if block # if block
283
+ super(*args) { |*params| # super(*args) { |*params|
284
+ set_block_back_references(block, $~) # set_block_back_references(block, $~)
285
+ block.call(*params) # block.call(*params)
286
+ } # }
287
+ else # else
288
+ super # super
289
+ end # end
290
+ end # end
291
+ EOT
291
292
  end
292
293
 
293
294
  private
294
- def html_escape_interpolated_argument(arg)
295
+ def explicit_html_escape_interpolated_argument(arg)
295
296
  (!html_safe? || arg.html_safe?) ? arg : CGI.escapeHTML(arg.to_s)
296
297
  end
297
298
 
299
+ def implicit_html_escape_interpolated_argument(arg)
300
+ if !html_safe? || arg.html_safe?
301
+ arg
302
+ else
303
+ arg_string = begin
304
+ arg.to_str
305
+ rescue NoMethodError => error
306
+ if error.name == :to_str
307
+ str = arg.to_s
308
+ ActiveSupport::Deprecation.warn <<~MSG.squish
309
+ Implicit conversion of #{arg.class} into String by ActiveSupport::SafeBuffer
310
+ is deprecated and will be removed in Rails 7.1.
311
+ You must explicitly cast it to a String.
312
+ MSG
313
+ str
314
+ else
315
+ raise
316
+ end
317
+ end
318
+ CGI.escapeHTML(arg_string)
319
+ end
320
+ end
321
+
298
322
  def set_block_back_references(block, match_data)
299
323
  block.binding.eval("proc { |m| $~ = m }").call(match_data)
300
324
  rescue ArgumentError
@@ -1,14 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Symbol
4
- def start_with?(*prefixes)
5
- to_s.start_with?(*prefixes)
6
- end unless method_defined?(:start_with?)
7
-
8
- def end_with?(*suffixes)
9
- to_s.end_with?(*suffixes)
10
- end unless method_defined?(:end_with?)
11
-
12
4
  alias :starts_with? :start_with?
13
5
  alias :ends_with? :end_with?
14
6
  end
@@ -42,8 +42,8 @@ class Time
42
42
 
43
43
  # Layers additional behavior on Time.at so that ActiveSupport::TimeWithZone and DateTime
44
44
  # instances can be used when called with a single argument
45
- def at_with_coercion(*args)
46
- return at_without_coercion(*args) if args.size != 1
45
+ def at_with_coercion(*args, **kwargs)
46
+ return at_without_coercion(*args, **kwargs) if args.size != 1 || !kwargs.empty?
47
47
 
48
48
  # Time.at can be called with a time or numerical value
49
49
  time_or_number = args.first
@@ -56,7 +56,6 @@ class Time
56
56
  at_without_coercion(time_or_number)
57
57
  end
58
58
  end
59
- ruby2_keywords(:at_with_coercion) if respond_to?(:ruby2_keywords, true)
60
59
  alias_method :at_without_coercion, :at
61
60
  alias_method :at, :at_with_coercion
62
61
 
@@ -160,6 +159,8 @@ class Time
160
159
  ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, new_offset)
161
160
  elsif utc?
162
161
  ::Time.utc(new_year, new_month, new_day, new_hour, new_min, new_sec)
162
+ elsif zone&.respond_to?(:utc_to_local)
163
+ ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, zone)
163
164
  elsif zone
164
165
  ::Time.local(new_year, new_month, new_day, new_hour, new_min, new_sec)
165
166
  else
@@ -276,7 +277,7 @@ class Time
276
277
  end
277
278
  alias :at_end_of_minute :end_of_minute
278
279
 
279
- def plus_with_duration(other) #:nodoc:
280
+ def plus_with_duration(other) # :nodoc:
280
281
  if ActiveSupport::Duration === other
281
282
  other.since(self)
282
283
  else
@@ -286,7 +287,7 @@ class Time
286
287
  alias_method :plus_without_duration, :+
287
288
  alias_method :+, :plus_with_duration
288
289
 
289
- def minus_with_duration(other) #:nodoc:
290
+ def minus_with_duration(other) # :nodoc:
290
291
  if ActiveSupport::Duration === other
291
292
  other.until(self)
292
293
  else
@@ -80,24 +80,9 @@ class Time
80
80
  # Time.find_zone! false # => false
81
81
  # Time.find_zone! "NOT-A-TIMEZONE" # => ArgumentError: Invalid Timezone: NOT-A-TIMEZONE
82
82
  def find_zone!(time_zone)
83
- if !time_zone || time_zone.is_a?(ActiveSupport::TimeZone)
84
- time_zone
85
- else
86
- # Look up the timezone based on the identifier (unless we've been
87
- # passed a TZInfo::Timezone)
88
- unless time_zone.respond_to?(:period_for_local)
89
- time_zone = ActiveSupport::TimeZone[time_zone] || TZInfo::Timezone.get(time_zone)
90
- end
83
+ return time_zone unless time_zone
91
84
 
92
- # Return if a TimeZone instance, or wrap in a TimeZone instance if a TZInfo::Timezone
93
- if time_zone.is_a?(ActiveSupport::TimeZone)
94
- time_zone
95
- else
96
- ActiveSupport::TimeZone.create(time_zone.name, nil, time_zone)
97
- end
98
- end
99
- rescue TZInfo::InvalidTimezoneIdentifier
100
- raise ArgumentError, "Invalid Timezone: #{time_zone}"
85
+ ActiveSupport::TimeZone[time_zone] || raise(ArgumentError, "Invalid Timezone: #{time_zone}")
101
86
  end
102
87
 
103
88
  # Returns a TimeZone instance matching the time zone provided.
@@ -2,25 +2,11 @@
2
2
 
3
3
  require "uri"
4
4
 
5
- if RUBY_VERSION < "2.6.0"
6
- require "active_support/core_ext/module/redefine_method"
7
- URI::Parser.class_eval do
8
- silence_redefinition_of_method :unescape
9
- def unescape(str, escaped = /%[a-fA-F\d]{2}/)
10
- # TODO: Are we actually sure that ASCII == UTF-8?
11
- # YK: My initial experiments say yes, but let's be sure please
12
- enc = str.encoding
13
- enc = Encoding::UTF_8 if enc == Encoding::US_ASCII
14
- str.dup.force_encoding(Encoding::ASCII_8BIT).gsub(escaped) { |match| [match[1, 2].hex].pack("C") }.force_encoding(enc)
15
- end
16
- end
17
- end
18
-
19
5
  module URI
20
6
  class << self
21
7
  def parser
22
8
  ActiveSupport::Deprecation.warn(<<-MSG.squish)
23
- URI.parser is deprecated and will be removed in Rails 6.2.
9
+ URI.parser is deprecated and will be removed in Rails 7.0.
24
10
  Use `URI::DEFAULT_PARSER` instead.
25
11
  MSG
26
12
  URI::DEFAULT_PARSER
@@ -143,13 +143,24 @@ module ActiveSupport
143
143
  current_instances.clear
144
144
  end
145
145
 
146
+ def _use_thread_variables=(value) # :nodoc:
147
+ clear_all
148
+ @@use_thread_variables = value
149
+ end
150
+ @@use_thread_variables = false
151
+
146
152
  private
147
153
  def generated_attribute_methods
148
154
  @generated_attribute_methods ||= Module.new.tap { |mod| include mod }
149
155
  end
150
156
 
151
157
  def current_instances
152
- Thread.current[:current_attributes_instances] ||= {}
158
+ if @@use_thread_variables
159
+ Thread.current.thread_variable_get(:current_attributes_instances) ||
160
+ Thread.current.thread_variable_set(:current_attributes_instances, {})
161
+ else
162
+ Thread.current[:current_attributes_instances] ||= {}
163
+ end
153
164
  end
154
165
 
155
166
  def current_instances_key
@@ -164,6 +175,11 @@ module ActiveSupport
164
175
 
165
176
  send(name, *args, &block)
166
177
  end
178
+ ruby2_keywords(:method_missing)
179
+
180
+ def respond_to_missing?(name, _)
181
+ super || instance.respond_to?(name)
182
+ end
167
183
  end
168
184
 
169
185
  attr_accessor :attributes