activesupport 7.2.1 → 8.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +67 -189
  3. data/lib/active_support/backtrace_cleaner.rb +1 -1
  4. data/lib/active_support/benchmark.rb +21 -0
  5. data/lib/active_support/benchmarkable.rb +3 -2
  6. data/lib/active_support/broadcast_logger.rb +14 -14
  7. data/lib/active_support/cache/file_store.rb +12 -2
  8. data/lib/active_support/cache/memory_store.rb +6 -2
  9. data/lib/active_support/cache/redis_cache_store.rb +5 -2
  10. data/lib/active_support/cache.rb +18 -13
  11. data/lib/active_support/callbacks.rb +1 -2
  12. data/lib/active_support/class_attribute.rb +26 -0
  13. data/lib/active_support/code_generator.rb +9 -0
  14. data/lib/active_support/concurrency/share_lock.rb +0 -1
  15. data/lib/active_support/configuration_file.rb +15 -6
  16. data/lib/active_support/core_ext/benchmark.rb +6 -9
  17. data/lib/active_support/core_ext/class/attribute.rb +10 -19
  18. data/lib/active_support/core_ext/date/conversions.rb +2 -0
  19. data/lib/active_support/core_ext/date_and_time/compatibility.rb +2 -2
  20. data/lib/active_support/core_ext/enumerable.rb +8 -3
  21. data/lib/active_support/core_ext/hash/except.rb +0 -12
  22. data/lib/active_support/core_ext/module/attr_internal.rb +3 -4
  23. data/lib/active_support/core_ext/object/json.rb +20 -12
  24. data/lib/active_support/core_ext/string/multibyte.rb +1 -1
  25. data/lib/active_support/core_ext/thread/backtrace/location.rb +2 -7
  26. data/lib/active_support/core_ext/time/calculations.rb +14 -2
  27. data/lib/active_support/core_ext/time/compatibility.rb +9 -1
  28. data/lib/active_support/core_ext/time/conversions.rb +2 -0
  29. data/lib/active_support/core_ext/time/zones.rb +1 -1
  30. data/lib/active_support/current_attributes.rb +7 -3
  31. data/lib/active_support/delegation.rb +0 -2
  32. data/lib/active_support/dependencies.rb +0 -1
  33. data/lib/active_support/deprecation/reporting.rb +2 -21
  34. data/lib/active_support/deprecation.rb +1 -1
  35. data/lib/active_support/duration.rb +14 -10
  36. data/lib/active_support/encrypted_configuration.rb +20 -2
  37. data/lib/active_support/encrypted_file.rb +1 -1
  38. data/lib/active_support/error_reporter.rb +25 -1
  39. data/lib/active_support/evented_file_update_checker.rb +0 -1
  40. data/lib/active_support/gem_version.rb +3 -3
  41. data/lib/active_support/hash_with_indifferent_access.rb +16 -16
  42. data/lib/active_support/i18n_railtie.rb +19 -11
  43. data/lib/active_support/isolated_execution_state.rb +0 -2
  44. data/lib/active_support/json/encoding.rb +2 -2
  45. data/lib/active_support/notifications/fanout.rb +0 -1
  46. data/lib/active_support/number_helper.rb +22 -0
  47. data/lib/active_support/railtie.rb +4 -0
  48. data/lib/active_support/tagged_logging.rb +5 -0
  49. data/lib/active_support/testing/assertions.rb +79 -21
  50. data/lib/active_support/testing/isolation.rb +2 -2
  51. data/lib/active_support/testing/parallelization/server.rb +3 -0
  52. data/lib/active_support/testing/strict_warnings.rb +3 -0
  53. data/lib/active_support/testing/time_helpers.rb +2 -1
  54. data/lib/active_support/time_with_zone.rb +22 -13
  55. data/lib/active_support/values/time_zone.rb +17 -15
  56. data/lib/active_support.rb +10 -3
  57. metadata +40 -11
  58. data/lib/active_support/proxy_object.rb +0 -20
@@ -313,10 +313,6 @@ module ActiveSupport
313
313
  end
314
314
  alias_method :without, :except
315
315
 
316
- def stringify_keys!; self end
317
- def deep_stringify_keys!; self end
318
- def stringify_keys; dup end
319
- def deep_stringify_keys; dup end
320
316
  undef :symbolize_keys!
321
317
  undef :deep_symbolize_keys!
322
318
  def symbolize_keys; to_hash.symbolize_keys! end
@@ -378,13 +374,10 @@ module ActiveSupport
378
374
 
379
375
  # Convert to a regular hash with string keys.
380
376
  def to_hash
381
- _new_hash = Hash.new
382
- set_defaults(_new_hash)
383
-
384
- each do |key, value|
385
- _new_hash[key] = convert_value(value, conversion: :to_hash)
386
- end
387
- _new_hash
377
+ copy = Hash[self]
378
+ copy.transform_values! { |v| convert_value_to_hash(v) }
379
+ set_defaults(copy)
380
+ copy
388
381
  end
389
382
 
390
383
  def to_proc
@@ -398,11 +391,7 @@ module ActiveSupport
398
391
 
399
392
  def convert_value(value, conversion: nil)
400
393
  if value.is_a? Hash
401
- if conversion == :to_hash
402
- value.to_hash
403
- else
404
- value.nested_under_indifferent_access
405
- end
394
+ value.nested_under_indifferent_access
406
395
  elsif value.is_a?(Array)
407
396
  if conversion != :assignment || value.frozen?
408
397
  value = value.dup
@@ -413,6 +402,17 @@ module ActiveSupport
413
402
  end
414
403
  end
415
404
 
405
+ def convert_value_to_hash(value)
406
+ if value.is_a? Hash
407
+ value.to_hash
408
+ elsif value.is_a?(Array)
409
+ value.map { |e| convert_value_to_hash(e) }
410
+ else
411
+ value
412
+ end
413
+ end
414
+
415
+
416
416
  def set_defaults(target)
417
417
  if default_proc
418
418
  target.default_proc = default_proc.dup
@@ -14,15 +14,18 @@ module I18n
14
14
 
15
15
  config.eager_load_namespaces << I18n
16
16
 
17
- # Set the i18n configuration after initialization since a lot of
18
- # configuration is still usually done in application initializers.
19
- config.after_initialize do |app|
17
+ # Make sure i18n is ready before eager loading, in case any eager loaded
18
+ # code needs it.
19
+ config.before_eager_load do |app|
20
20
  I18n::Railtie.initialize_i18n(app)
21
21
  end
22
22
 
23
- # Trigger i18n config before any eager loading has happened
24
- # so it's ready if any classes require it when eager loaded.
25
- config.before_eager_load do |app|
23
+ # i18n initialization needs to run after application initialization, since
24
+ # initializers may configure i18n.
25
+ #
26
+ # If the application eager loaded, this was done on before_eager_load. The
27
+ # hook is still OK, though, because initialize_i18n is idempotent.
28
+ config.after_initialize do |app|
26
29
  I18n::Railtie.initialize_i18n(app)
27
30
  end
28
31
 
@@ -49,7 +52,8 @@ module I18n
49
52
  when :load_path
50
53
  I18n.load_path += value
51
54
  when :raise_on_missing_translations
52
- setup_raise_on_missing_translations_config(app)
55
+ strict = value == :strict
56
+ setup_raise_on_missing_translations_config(app, strict)
53
57
  else
54
58
  I18n.public_send("#{setting}=", value)
55
59
  end
@@ -62,8 +66,9 @@ module I18n
62
66
 
63
67
  if app.config.reloading_enabled?
64
68
  directories = watched_dirs_with_extensions(reloadable_paths)
65
- reloader = app.config.file_watcher.new(I18n.load_path.dup, directories) do
66
- I18n.load_path.keep_if { |p| File.exist?(p) }
69
+ root_load_paths = I18n.load_path.select { |path| path.to_s.start_with?(Rails.root.to_s) }
70
+ reloader = app.config.file_watcher.new(root_load_paths, directories) do
71
+ I18n.load_path.delete_if { |path| path.to_s.start_with?(Rails.root.to_s) && !File.exist?(path) }
67
72
  I18n.load_path |= reloadable_paths.flat_map(&:existent)
68
73
  end
69
74
 
@@ -71,17 +76,20 @@ module I18n
71
76
  app.reloader.to_run do
72
77
  reloader.execute_if_updated { require_unload_lock! }
73
78
  end
74
- reloader.execute
75
79
  end
76
80
 
77
81
  @i18n_inited = true
78
82
  end
79
83
 
80
- def self.setup_raise_on_missing_translations_config(app)
84
+ def self.setup_raise_on_missing_translations_config(app, strict)
81
85
  ActiveSupport.on_load(:action_view) do
82
86
  ActionView::Helpers::TranslationHelper.raise_on_missing_translations = app.config.i18n.raise_on_missing_translations
83
87
  end
84
88
 
89
+ ActiveSupport.on_load(:active_model_translation) do
90
+ ActiveModel::Translation.raise_on_missing_translations = app.config.i18n.raise_on_missing_translations if strict
91
+ end
92
+
85
93
  if app.config.i18n.raise_on_missing_translations &&
86
94
  I18n.exception_handler.is_a?(I18n::ExceptionHandler) # Only override the i18n gem's default exception handler.
87
95
 
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "fiber"
4
-
5
3
  module ActiveSupport
6
4
  module IsolatedExecutionState # :nodoc:
7
5
  @isolation_level = nil
@@ -36,14 +36,14 @@ module ActiveSupport
36
36
  # Encode the given object into a JSON string
37
37
  def encode(value)
38
38
  unless options.empty?
39
- value = value.as_json(options.dup)
39
+ value = value.as_json(options.dup.freeze)
40
40
  end
41
41
  json = stringify(jsonify(value))
42
42
 
43
43
  # Rails does more escaping than the JSON gem natively does (we
44
44
  # escape \u2028 and \u2029 and optionally >, <, & to work around
45
45
  # certain browser problems).
46
- if Encoding.escape_html_entities_in_json
46
+ if @options.fetch(:escape_html_entities, Encoding.escape_html_entities_in_json)
47
47
  json.gsub!(">", '\u003e')
48
48
  json.gsub!("<", '\u003c')
49
49
  json.gsub!("&", '\u0026')
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "concurrent/map"
4
- require "set"
5
4
  require "active_support/core_ext/object/try"
6
5
 
7
6
  module ActiveSupport
@@ -1,6 +1,28 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveSupport
4
+ # = Number Helper
5
+ #
6
+ # Provides methods for formatting numbers into currencies, percentages,
7
+ # phone numbers, and more.
8
+ #
9
+ # Example usage in a class:
10
+ # class Topic
11
+ # include ActiveSupport::NumberHelper
12
+ #
13
+ # def price
14
+ # number_to_currency(@price)
15
+ # end
16
+ # end
17
+ #
18
+ # Example usage in a module:
19
+ # require "active_support/number_helper"
20
+ #
21
+ # module NumberFormatting
22
+ # def format_price(price)
23
+ # ActiveSupport::NumberHelper.number_to_currency(price)
24
+ # end
25
+ # end
4
26
  module NumberHelper
5
27
  extend ActiveSupport::Autoload
6
28
 
@@ -96,6 +96,10 @@ module ActiveSupport
96
96
  config.eager_load_namespaces << TZInfo
97
97
  end
98
98
 
99
+ initializer "active_support.to_time_preserves_timezone" do |app|
100
+ ActiveSupport.to_time_preserves_timezone = app.config.active_support.to_time_preserves_timezone
101
+ end
102
+
99
103
  # Sets the default week start
100
104
  # If assigned value is not a valid day symbol (e.g. :sunday, :monday, ...), an exception will be raised.
101
105
  initializer "active_support.initialize_beginning_of_week" do |app|
@@ -113,6 +113,11 @@ module ActiveSupport
113
113
  end
114
114
  end
115
115
 
116
+ # Returns an `ActiveSupport::Logger` that has already been wrapped with tagged logging concern.
117
+ def self.logger(*args, **kwargs)
118
+ new ActiveSupport::Logger.new(*args, **kwargs)
119
+ end
120
+
116
121
  def self.new(logger)
117
122
  logger = logger.clone
118
123
 
@@ -19,7 +19,7 @@ module ActiveSupport
19
19
  #
20
20
  # assert_not foo, 'foo should be false'
21
21
  def assert_not(object, message = nil)
22
- message ||= "Expected #{mu_pp(object)} to be nil or false"
22
+ message ||= -> { "Expected #{mu_pp(object)} to be nil or false" }
23
23
  assert !object, message
24
24
  end
25
25
 
@@ -118,9 +118,13 @@ module ActiveSupport
118
118
 
119
119
  expressions.zip(exps, before) do |(code, diff), exp, before_value|
120
120
  actual = exp.call
121
- error = "#{code.inspect} didn't change by #{diff}, but by #{actual - before_value}"
122
- error = "#{message}.\n#{error}" if message
123
- assert_equal(before_value + diff, actual, error)
121
+ rich_message = -> do
122
+ code_string = code.respond_to?(:call) ? _callable_to_source_string(code) : code
123
+ error = "`#{code_string}` didn't change by #{diff}, but by #{actual - before_value}"
124
+ error = "#{message}.\n#{error}" if message
125
+ error
126
+ end
127
+ assert_equal(before_value + diff, actual, rich_message)
124
128
  end
125
129
 
126
130
  retval
@@ -195,22 +199,32 @@ module ActiveSupport
195
199
  retval = _assert_nothing_raised_or_warn("assert_changes", &block)
196
200
 
197
201
  unless from == UNTRACKED
198
- error = "Expected change from #{from.inspect}, got #{before.inspect}"
199
- error = "#{message}.\n#{error}" if message
200
- assert from === before, error
202
+ rich_message = -> do
203
+ error = "Expected change from #{from.inspect}, got #{before.inspect}"
204
+ error = "#{message}.\n#{error}" if message
205
+ error
206
+ end
207
+ assert from === before, rich_message
201
208
  end
202
209
 
203
210
  after = exp.call
204
211
 
205
- error = "#{expression.inspect} didn't change"
206
- error = "#{error}. It was already #{to.inspect}" if before == to
207
- error = "#{message}.\n#{error}" if message
208
- refute_equal before, after, error
212
+ rich_message = -> do
213
+ code_string = expression.respond_to?(:call) ? _callable_to_source_string(expression) : expression
214
+ error = "`#{code_string}` didn't change"
215
+ error = "#{error}. It was already #{to.inspect}" if before == to
216
+ error = "#{message}.\n#{error}" if message
217
+ error
218
+ end
219
+ refute_equal before, after, rich_message
209
220
 
210
221
  unless to == UNTRACKED
211
- error = "Expected change to #{to.inspect}, got #{after.inspect}\n"
212
- error = "#{message}.\n#{error}" if message
213
- assert to === after, error
222
+ rich_message = -> do
223
+ error = "Expected change to #{to.inspect}, got #{after.inspect}\n"
224
+ error = "#{message}.\n#{error}" if message
225
+ error
226
+ end
227
+ assert to === after, rich_message
214
228
  end
215
229
 
216
230
  retval
@@ -242,20 +256,27 @@ module ActiveSupport
242
256
  retval = _assert_nothing_raised_or_warn("assert_no_changes", &block)
243
257
 
244
258
  unless from == UNTRACKED
245
- error = "Expected initial value of #{from.inspect}, got #{before.inspect}"
246
- error = "#{message}.\n#{error}" if message
247
- assert from === before, error
259
+ rich_message = -> do
260
+ error = "Expected initial value of #{from.inspect}, got #{before.inspect}"
261
+ error = "#{message}.\n#{error}" if message
262
+ error
263
+ end
264
+ assert from === before, rich_message
248
265
  end
249
266
 
250
267
  after = exp.call
251
268
 
252
- error = "#{expression.inspect} changed"
253
- error = "#{message}.\n#{error}" if message
269
+ rich_message = -> do
270
+ code_string = expression.respond_to?(:call) ? _callable_to_source_string(expression) : expression
271
+ error = "`#{code_string}` changed"
272
+ error = "#{message}.\n#{error}" if message
273
+ error
274
+ end
254
275
 
255
276
  if before.nil?
256
- assert_nil after, error
277
+ assert_nil after, rich_message
257
278
  else
258
- assert_equal before, after, error
279
+ assert_equal before, after, rich_message
259
280
  end
260
281
 
261
282
  retval
@@ -276,6 +297,43 @@ module ActiveSupport
276
297
 
277
298
  raise
278
299
  end
300
+
301
+ def _callable_to_source_string(callable)
302
+ if defined?(RubyVM::InstructionSequence) && callable.is_a?(Proc)
303
+ iseq = RubyVM::InstructionSequence.of(callable)
304
+ source =
305
+ if iseq.script_lines
306
+ iseq.script_lines.join("\n")
307
+ elsif File.readable?(iseq.absolute_path)
308
+ File.read(iseq.absolute_path)
309
+ end
310
+
311
+ return callable unless source
312
+
313
+ location = iseq.to_a[4][:code_location]
314
+ return callable unless location
315
+
316
+ lines = source.lines[(location[0] - 1)..(location[2] - 1)]
317
+ lines[-1] = lines[-1].byteslice(...location[3])
318
+ lines[0] = lines[0].byteslice(location[1]...)
319
+ source = lines.join.strip
320
+
321
+ # We ignore procs defined with do/end as they are likely multi-line anyway.
322
+ if source.start_with?("{")
323
+ source.delete_suffix!("}")
324
+ source.delete_prefix!("{")
325
+ source.strip!
326
+ # It won't read nice if the callable contains multiple
327
+ # lines, and it should be a rare occurrence anyway.
328
+ # Same if it takes arguments.
329
+ if !source.include?("\n") && !source.start_with?("|")
330
+ return source
331
+ end
332
+ end
333
+ end
334
+
335
+ callable
336
+ end
279
337
  end
280
338
  end
281
339
  end
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/testing/parallelize_executor"
4
+
3
5
  module ActiveSupport
4
6
  module Testing
5
7
  module Isolation
6
- require "thread"
7
-
8
8
  SubprocessCrashed = Class.new(StandardError)
9
9
 
10
10
  def self.included(klass) # :nodoc:
@@ -6,6 +6,8 @@ require "drb/unix" unless Gem.win_platform?
6
6
  module ActiveSupport
7
7
  module Testing
8
8
  class Parallelization # :nodoc:
9
+ PrerecordResultClass = Struct.new(:name)
10
+
9
11
  class Server
10
12
  include DRb::DRbUndumped
11
13
 
@@ -21,6 +23,7 @@ module ActiveSupport
21
23
  @in_flight.delete([result.klass, result.name])
22
24
 
23
25
  reporter.synchronize do
26
+ reporter.prerecord(PrerecordResultClass.new(result.klass), result.name)
24
27
  reporter.record(result)
25
28
  end
26
29
  end
@@ -14,6 +14,9 @@ module ActiveSupport
14
14
  # Expected non-verbose warning emitted by Rails.
15
15
  /Ignoring .*\.yml because it has expired/,
16
16
  /Failed to validate the schema cache because/,
17
+
18
+ # TODO: We need to decide what to do with this.
19
+ /Status code :unprocessable_entity is deprecated/,
17
20
  )
18
21
 
19
22
  SUPPRESSED_WARNINGS = Regexp.union(
@@ -166,9 +166,10 @@ module ActiveSupport
166
166
  else
167
167
  now = date_or_time
168
168
  now = now.to_time unless now.is_a?(Time)
169
- now = now.change(usec: 0) unless with_usec
170
169
  end
171
170
 
171
+ now = now.change(usec: 0) unless with_usec
172
+
172
173
  # +now+ must be in local system timezone, because +Time.at(now)+
173
174
  # and +now.to_date+ (see stubs below) will use +now+'s timezone too!
174
175
  now = now.getlocal
@@ -85,7 +85,7 @@ module ActiveSupport
85
85
  end
86
86
  alias_method :getlocal, :localtime
87
87
 
88
- # Returns true if the current time is within Daylight Savings Time for the
88
+ # Returns true if the current time is within Daylight Savings \Time for the
89
89
  # specified time zone.
90
90
  #
91
91
  # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
@@ -138,7 +138,7 @@ module ActiveSupport
138
138
  #
139
139
  # Time.zone.now.inspect # => "Thu, 04 Dec 2014 11:00:25.624541392 EST -05:00"
140
140
  def inspect
141
- "#{time.strftime('%a, %d %b %Y %H:%M:%S.%9N')} #{zone} #{formatted_offset}"
141
+ "#{time.strftime('%F %H:%M:%S.%9N')} #{zone} #{formatted_offset}"
142
142
  end
143
143
 
144
144
  # Returns a string of the object's date and time in the ISO 8601 standard
@@ -157,11 +157,11 @@ module ActiveSupport
157
157
  # to +false+.
158
158
  #
159
159
  # # With ActiveSupport::JSON::Encoding.use_standard_json_time_format = true
160
- # Time.utc(2005,2,1,15,15,10).in_time_zone("Hawaii").to_json
160
+ # Time.utc(2005,2,1,15,15,10).in_time_zone("Hawaii").as_json
161
161
  # # => "2005-02-01T05:15:10.000-10:00"
162
162
  #
163
163
  # # With ActiveSupport::JSON::Encoding.use_standard_json_time_format = false
164
- # Time.utc(2005,2,1,15,15,10).in_time_zone("Hawaii").to_json
164
+ # Time.utc(2005,2,1,15,15,10).in_time_zone("Hawaii").as_json
165
165
  # # => "2005/02/01 05:15:10 -1000"
166
166
  def as_json(options = nil)
167
167
  if ActiveSupport::JSON::Encoding.use_standard_json_time_format
@@ -215,8 +215,7 @@ module ActiveSupport
215
215
  elsif formatter = ::Time::DATE_FORMATS[format]
216
216
  formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
217
217
  else
218
- # Change to to_s when deprecation is gone.
219
- "#{time.strftime("%Y-%m-%d %H:%M:%S")} #{formatted_offset(false, 'UTC')}"
218
+ to_s
220
219
  end
221
220
  end
222
221
  alias_method :to_formatted_s, :to_fs
@@ -300,7 +299,16 @@ module ActiveSupport
300
299
  if duration_of_variable_length?(other)
301
300
  method_missing(:+, other)
302
301
  else
303
- result = utc.acts_like?(:date) ? utc.since(other) : utc + other rescue utc.since(other)
302
+ begin
303
+ result = utc + other
304
+ rescue TypeError
305
+ result = utc.to_datetime.since(other)
306
+ ActiveSupport.deprecator.warn(
307
+ "Adding an instance of #{other.class} to an instance of #{self.class} is deprecated. This behavior will raise " \
308
+ "a `TypeError` in Rails 8.1."
309
+ )
310
+ result.in_time_zone(time_zone)
311
+ end
304
312
  result.in_time_zone(time_zone)
305
313
  end
306
314
  end
@@ -336,7 +344,7 @@ module ActiveSupport
336
344
  elsif duration_of_variable_length?(other)
337
345
  method_missing(:-, other)
338
346
  else
339
- result = utc.acts_like?(:date) ? utc.ago(other) : utc - other rescue utc.ago(other)
347
+ result = utc - other
340
348
  result.in_time_zone(time_zone)
341
349
  end
342
350
  end
@@ -479,11 +487,13 @@ module ActiveSupport
479
487
  @to_datetime ||= utc.to_datetime.new_offset(Rational(utc_offset, 86_400))
480
488
  end
481
489
 
482
- # Returns an instance of +Time+, either with the same UTC offset
483
- # as +self+ or in the local system timezone depending on the setting
484
- # of +ActiveSupport.to_time_preserves_timezone+.
490
+ # Returns an instance of +Time+, either with the same timezone as +self+,
491
+ # with the same UTC offset as +self+ or in the local system timezone
492
+ # depending on the setting of +ActiveSupport.to_time_preserves_timezone+.
485
493
  def to_time
486
- if preserve_timezone
494
+ if preserve_timezone == :zone
495
+ @to_time_with_timezone ||= getlocal(time_zone)
496
+ elsif preserve_timezone
487
497
  @to_time_with_instance_offset ||= getlocal(utc_offset)
488
498
  else
489
499
  @to_time_with_system_offset ||= getlocal
@@ -535,7 +545,6 @@ module ActiveSupport
535
545
  # Ensure proxy class responds to all methods that underlying time instance
536
546
  # responds to.
537
547
  def respond_to_missing?(sym, include_priv)
538
- return false if sym.to_sym == :acts_like_date?
539
548
  time.respond_to?(sym, include_priv)
540
549
  end
541
550
 
@@ -12,7 +12,7 @@ module ActiveSupport
12
12
  # * Limit the set of zones provided by TZInfo to a meaningful subset of 134
13
13
  # zones.
14
14
  # * Retrieve and display zones with a friendlier name
15
- # (e.g., "Eastern Time (US & Canada)" instead of "America/New_York").
15
+ # (e.g., "Eastern \Time (US & Canada)" instead of "America/New_York").
16
16
  # * Lazily load +TZInfo::Timezone+ instances only when they're needed.
17
17
  # * Create ActiveSupport::TimeWithZone instances via TimeZone's +local+,
18
18
  # +parse+, +at+, and +now+ methods.
@@ -208,9 +208,7 @@ module ActiveSupport
208
208
  TZInfo::Timezone.get(MAPPING[name] || name)
209
209
  end
210
210
 
211
- # :stopdoc:
212
- alias_method :create, :new
213
- # :startdoc:
211
+ alias_method :create, :new # :nodoc:
214
212
 
215
213
  # Returns a TimeZone instance with the given name, or +nil+ if no
216
214
  # such TimeZone instance exists. (This exists to support the use of
@@ -357,7 +355,7 @@ module ActiveSupport
357
355
  "(GMT#{formatted_offset}) #{name}"
358
356
  end
359
357
 
360
- # Method for creating new ActiveSupport::TimeWithZone instance in time zone
358
+ # \Method for creating new ActiveSupport::TimeWithZone instance in time zone
361
359
  # of +self+ from given values.
362
360
  #
363
361
  # Time.zone = 'Hawaii' # => "Hawaii"
@@ -367,7 +365,7 @@ module ActiveSupport
367
365
  ActiveSupport::TimeWithZone.new(nil, self, time)
368
366
  end
369
367
 
370
- # Method for creating new ActiveSupport::TimeWithZone instance in time zone
368
+ # \Method for creating new ActiveSupport::TimeWithZone instance in time zone
371
369
  # of +self+ from number of seconds since the Unix epoch.
372
370
  #
373
371
  # Time.zone = 'Hawaii' # => "Hawaii"
@@ -382,7 +380,7 @@ module ActiveSupport
382
380
  Time.at(*args).utc.in_time_zone(self)
383
381
  end
384
382
 
385
- # Method for creating new ActiveSupport::TimeWithZone instance in time zone
383
+ # \Method for creating new ActiveSupport::TimeWithZone instance in time zone
386
384
  # of +self+ from an ISO 8601 string.
387
385
  #
388
386
  # Time.zone = 'Hawaii' # => "Hawaii"
@@ -434,7 +432,7 @@ module ActiveSupport
434
432
  raise ArgumentError, "invalid date"
435
433
  end
436
434
 
437
- # Method for creating new ActiveSupport::TimeWithZone instance in time zone
435
+ # \Method for creating new ActiveSupport::TimeWithZone instance in time zone
438
436
  # of +self+ from parsed string.
439
437
  #
440
438
  # Time.zone = 'Hawaii' # => "Hawaii"
@@ -456,7 +454,7 @@ module ActiveSupport
456
454
  parts_to_time(Date._parse(str, false), now)
457
455
  end
458
456
 
459
- # Method for creating new ActiveSupport::TimeWithZone instance in time zone
457
+ # \Method for creating new ActiveSupport::TimeWithZone instance in time zone
460
458
  # of +self+ from an RFC 3339 string.
461
459
  #
462
460
  # Time.zone = 'Hawaii' # => "Hawaii"
@@ -554,15 +552,11 @@ module ActiveSupport
554
552
  tzinfo.local_to_utc(time, dst)
555
553
  end
556
554
 
557
- # Available so that TimeZone instances respond like +TZInfo::Timezone+
558
- # instances.
559
- def period_for_utc(time)
555
+ def period_for_utc(time) # :nodoc:
560
556
  tzinfo.period_for_utc(time)
561
557
  end
562
558
 
563
- # Available so that TimeZone instances respond like +TZInfo::Timezone+
564
- # instances.
565
- def period_for_local(time, dst = true)
559
+ def period_for_local(time, dst = true) # :nodoc:
566
560
  tzinfo.period_for_local(time, dst) { |periods| periods.last }
567
561
  end
568
562
 
@@ -570,6 +564,14 @@ module ActiveSupport
570
564
  tzinfo.periods_for_local(time)
571
565
  end
572
566
 
567
+ def abbr(time) # :nodoc:
568
+ tzinfo.abbr(time)
569
+ end
570
+
571
+ def dst?(time) # :nodoc:
572
+ tzinfo.dst?(time)
573
+ end
574
+
573
575
  def init_with(coder) # :nodoc:
574
576
  initialize(coder["name"])
575
577
  end
@@ -57,11 +57,12 @@ module ActiveSupport
57
57
 
58
58
  eager_autoload do
59
59
  autoload :BacktraceCleaner
60
- autoload :ProxyObject
60
+ autoload :Benchmark
61
61
  autoload :Benchmarkable
62
62
  autoload :Cache
63
63
  autoload :Callbacks
64
64
  autoload :Configurable
65
+ autoload :ClassAttribute
65
66
  autoload :Deprecation
66
67
  autoload :Delegation
67
68
  autoload :Digest
@@ -115,9 +116,15 @@ module ActiveSupport
115
116
  end
116
117
 
117
118
  def self.to_time_preserves_timezone=(value)
118
- unless value
119
+ if !value
119
120
  ActiveSupport.deprecator.warn(
120
- "Support for the pre-Ruby 2.4 behavior of to_time has been deprecated and will be removed in Rails 8.0."
121
+ "`to_time` will always preserve the receiver timezone rather than system local time in Rails 8.1. " \
122
+ "To opt in to the new behavior, set `config.active_support.to_time_preserves_timezone = :zone`."
123
+ )
124
+ elsif value != :zone
125
+ ActiveSupport.deprecator.warn(
126
+ "`to_time` will always preserve the full timezone rather than offset of the receiver in Rails 8.1. " \
127
+ "To opt in to the new behavior, set `config.active_support.to_time_preserves_timezone = :zone`."
121
128
  )
122
129
  end
123
130