activesupport 7.2.2.1 → 8.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +41 -237
  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/cache/file_store.rb +12 -2
  7. data/lib/active_support/cache/memory_store.rb +6 -2
  8. data/lib/active_support/cache/redis_cache_store.rb +5 -2
  9. data/lib/active_support/cache.rb +14 -9
  10. data/lib/active_support/callbacks.rb +1 -2
  11. data/lib/active_support/class_attribute.rb +26 -0
  12. data/lib/active_support/code_generator.rb +9 -0
  13. data/lib/active_support/concurrency/share_lock.rb +0 -1
  14. data/lib/active_support/configuration_file.rb +15 -6
  15. data/lib/active_support/core_ext/benchmark.rb +6 -9
  16. data/lib/active_support/core_ext/class/attribute.rb +10 -19
  17. data/lib/active_support/core_ext/date/conversions.rb +2 -0
  18. data/lib/active_support/core_ext/date_and_time/compatibility.rb +2 -2
  19. data/lib/active_support/core_ext/enumerable.rb +8 -3
  20. data/lib/active_support/core_ext/hash/except.rb +0 -12
  21. data/lib/active_support/core_ext/object/json.rb +18 -14
  22. data/lib/active_support/core_ext/string/multibyte.rb +1 -1
  23. data/lib/active_support/core_ext/time/calculations.rb +14 -2
  24. data/lib/active_support/core_ext/time/conversions.rb +2 -0
  25. data/lib/active_support/core_ext/time/zones.rb +1 -1
  26. data/lib/active_support/deprecation.rb +1 -1
  27. data/lib/active_support/encrypted_configuration.rb +20 -2
  28. data/lib/active_support/error_reporter.rb +25 -1
  29. data/lib/active_support/gem_version.rb +4 -4
  30. data/lib/active_support/hash_with_indifferent_access.rb +16 -12
  31. data/lib/active_support/i18n_railtie.rb +19 -10
  32. data/lib/active_support/isolated_execution_state.rb +0 -1
  33. data/lib/active_support/json/encoding.rb +2 -2
  34. data/lib/active_support/number_helper.rb +22 -0
  35. data/lib/active_support/railtie.rb +4 -0
  36. data/lib/active_support/tagged_logging.rb +5 -0
  37. data/lib/active_support/testing/assertions.rb +72 -21
  38. data/lib/active_support/testing/isolation.rb +0 -2
  39. data/lib/active_support/testing/time_helpers.rb +2 -1
  40. data/lib/active_support/time_with_zone.rb +22 -13
  41. data/lib/active_support/values/time_zone.rb +17 -15
  42. data/lib/active_support.rb +10 -2
  43. metadata +23 -7
@@ -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,36 @@ module ActiveSupport
276
297
 
277
298
  raise
278
299
  end
300
+
301
+ def _callable_to_source_string(callable)
302
+ if defined?(RubyVM::AbstractSyntaxTree) && callable.is_a?(Proc)
303
+ ast = begin
304
+ RubyVM::AbstractSyntaxTree.of(callable, keep_script_lines: true)
305
+ rescue SystemCallError
306
+ # Failed to get the source somehow
307
+ return callable
308
+ end
309
+ return callable unless ast
310
+
311
+ source = ast.source
312
+ source.strip!
313
+
314
+ # We ignore procs defined with do/end as they are likely multi-line anyway.
315
+ if source.start_with?("{")
316
+ source.delete_suffix!("}")
317
+ source.delete_prefix!("{")
318
+ source.strip!
319
+ # It won't read nice if the callable contains multiple
320
+ # lines, and it should be a rare occurence anyway.
321
+ # Same if it takes arguments.
322
+ if !source.include?("\n") && !source.start_with?("|")
323
+ return source
324
+ end
325
+ end
326
+ end
327
+
328
+ callable
329
+ end
279
330
  end
280
331
  end
281
332
  end
@@ -5,8 +5,6 @@ require "active_support/testing/parallelize_executor"
5
5
  module ActiveSupport
6
6
  module Testing
7
7
  module Isolation
8
- require "thread"
9
-
10
8
  SubprocessCrashed = Class.new(StandardError)
11
9
 
12
10
  def self.included(klass) # :nodoc:
@@ -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
@@ -58,10 +58,12 @@ module ActiveSupport
58
58
  eager_autoload do
59
59
  autoload :BacktraceCleaner
60
60
  autoload :ProxyObject
61
+ autoload :Benchmark
61
62
  autoload :Benchmarkable
62
63
  autoload :Cache
63
64
  autoload :Callbacks
64
65
  autoload :Configurable
66
+ autoload :ClassAttribute
65
67
  autoload :Deprecation
66
68
  autoload :Delegation
67
69
  autoload :Digest
@@ -115,9 +117,15 @@ module ActiveSupport
115
117
  end
116
118
 
117
119
  def self.to_time_preserves_timezone=(value)
118
- unless value
120
+ if !value
119
121
  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."
122
+ "`to_time` will always preserve the receiver timezone rather than system local time in Rails 8.0. " \
123
+ "To opt in to the new behavior, set `config.active_support.to_time_preserves_timezone = :zone`."
124
+ )
125
+ elsif value != :zone
126
+ ActiveSupport.deprecator.warn(
127
+ "`to_time` will always preserve the full timezone rather than offset of the receiver in Rails 8.0. " \
128
+ "To opt in to the new behavior, set `config.active_support.to_time_preserves_timezone = :zone`."
121
129
  )
122
130
  end
123
131
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activesupport
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.2.2.1
4
+ version: 8.0.0.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-12-10 00:00:00.000000000 Z
11
+ date: 2024-09-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: i18n
@@ -168,6 +168,20 @@ dependencies:
168
168
  - - ">="
169
169
  - !ruby/object:Gem::Version
170
170
  version: '0.3'
171
+ - !ruby/object:Gem::Dependency
172
+ name: uri
173
+ requirement: !ruby/object:Gem::Requirement
174
+ requirements:
175
+ - - ">="
176
+ - !ruby/object:Gem::Version
177
+ version: 0.13.1
178
+ type: :runtime
179
+ prerelease: false
180
+ version_requirements: !ruby/object:Gem::Requirement
181
+ requirements:
182
+ - - ">="
183
+ - !ruby/object:Gem::Version
184
+ version: 0.13.1
171
185
  - !ruby/object:Gem::Dependency
172
186
  name: benchmark
173
187
  requirement: !ruby/object:Gem::Requirement
@@ -198,6 +212,7 @@ files:
198
212
  - lib/active_support/all.rb
199
213
  - lib/active_support/array_inquirer.rb
200
214
  - lib/active_support/backtrace_cleaner.rb
215
+ - lib/active_support/benchmark.rb
201
216
  - lib/active_support/benchmarkable.rb
202
217
  - lib/active_support/broadcast_logger.rb
203
218
  - lib/active_support/builder.rb
@@ -213,6 +228,7 @@ files:
213
228
  - lib/active_support/cache/strategy/local_cache.rb
214
229
  - lib/active_support/cache/strategy/local_cache_middleware.rb
215
230
  - lib/active_support/callbacks.rb
231
+ - lib/active_support/class_attribute.rb
216
232
  - lib/active_support/code_generator.rb
217
233
  - lib/active_support/concern.rb
218
234
  - lib/active_support/concurrency/load_interlock_aware_monitor.rb
@@ -480,10 +496,10 @@ licenses:
480
496
  - MIT
481
497
  metadata:
482
498
  bug_tracker_uri: https://github.com/rails/rails/issues
483
- changelog_uri: https://github.com/rails/rails/blob/v7.2.2.1/activesupport/CHANGELOG.md
484
- documentation_uri: https://api.rubyonrails.org/v7.2.2.1/
499
+ changelog_uri: https://github.com/rails/rails/blob/v8.0.0.beta1/activesupport/CHANGELOG.md
500
+ documentation_uri: https://api.rubyonrails.org/v8.0.0.beta1/
485
501
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
486
- source_code_uri: https://github.com/rails/rails/tree/v7.2.2.1/activesupport
502
+ source_code_uri: https://github.com/rails/rails/tree/v8.0.0.beta1/activesupport
487
503
  rubygems_mfa_required: 'true'
488
504
  post_install_message:
489
505
  rdoc_options:
@@ -495,14 +511,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
495
511
  requirements:
496
512
  - - ">="
497
513
  - !ruby/object:Gem::Version
498
- version: 3.1.0
514
+ version: 3.2.0
499
515
  required_rubygems_version: !ruby/object:Gem::Requirement
500
516
  requirements:
501
517
  - - ">="
502
518
  - !ruby/object:Gem::Version
503
519
  version: '0'
504
520
  requirements: []
505
- rubygems_version: 3.5.22
521
+ rubygems_version: 3.5.16
506
522
  signing_key:
507
523
  specification_version: 4
508
524
  summary: A toolkit of support libraries and Ruby core extensions extracted from the