activesupport 7.0.3.1 → 7.0.4

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.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f4e3f1179b029500503dbf9f399d00a8072610e1b0de00817c8892ed03af34bf
4
- data.tar.gz: d627490cc53ce2be525df66b9a4e46869c53daa9458eaaa3d9cb5828d9dd327c
3
+ metadata.gz: 342ae35dc85cf68674201fd516c85b208adccc0c930e888d301d0ed5fa9e2cad
4
+ data.tar.gz: 8c611de7bc5d9ea07c57a1848abb556e9090009db790404fa1da49278a49d0b3
5
5
  SHA512:
6
- metadata.gz: 00bda131342cb0bca89db7291d96c24db0d247f56fa4b9a0f6375a2a29025f947b863e46a411acbec5c01133efec2ce3a0b44f8bc1f402e490e4d814d5f6e388
7
- data.tar.gz: ca0ca139495bada0d5b2efe2da3d5b7bcd68506fa571ae4cc1a505a5487a39a7ca388e78f8e5091b1523b60a6634f5d6e2f02600181bc65dbb0ffd87c4c0f354
6
+ metadata.gz: 68144c1574e6fe740072399749fef96a992ad390c5877a63110758a7184256882e118d9dc5290150b2b623a391a37ab8c2648e49782ae2f9b3c42cb9e21837c4
7
+ data.tar.gz: 6906af5f3a19a04f13ec6ca1c8f492259018181ad3bcb63eb75bdb8cf2fe7316a6dd787125de809cfc04a7dd72ff310f673001f69865b0753fcc571966b8b573
data/CHANGELOG.md CHANGED
@@ -1,3 +1,20 @@
1
+ ## Rails 7.0.4 (September 09, 2022) ##
2
+
3
+ * Redis cache store is now compatible with redis-rb 5.0.
4
+
5
+ *Jean Boussier*
6
+
7
+ * Fix `NoMethodError` on custom `ActiveSupport::Deprecation` behavior.
8
+
9
+ `ActiveSupport::Deprecation.behavior=` was supposed to accept any object
10
+ that responds to `call`, but in fact its internal implementation assumed that
11
+ this object could respond to `arity`, so it was restricted to only `Proc` objects.
12
+
13
+ This change removes this `arity` restriction of custom behaviors.
14
+
15
+ *Ryo Nakamura*
16
+
17
+
1
18
  ## Rails 7.0.3.1 (July 12, 2022) ##
2
19
 
3
20
  * No changes.
@@ -128,6 +128,22 @@ module ActiveSupport
128
128
  end
129
129
  end
130
130
 
131
+ ##
132
+ # :method: write
133
+ # :call-seq: write(name, value, options = nil)
134
+ #
135
+ # Behaves the same as ActiveSupport::Cache::Store#write, but supports
136
+ # additional options specific to memcached.
137
+ #
138
+ # ==== Additional Options
139
+ #
140
+ # * <tt>raw: true</tt> - Sends the value directly to the server as raw
141
+ # bytes. The value must be a string or number. You can use memcached
142
+ # direct operations like +increment+ and +decrement+ only on raw values.
143
+ #
144
+ # * <tt>unless_exist: true</tt> - Prevents overwriting an existing cache
145
+ # entry.
146
+
131
147
  # Increment a cached value. This method uses the memcached incr atomic
132
148
  # operator and can only be used on values written with the +:raw+ option.
133
149
  # Calling it on a value not stored with +:raw+ will initialize that value
@@ -5,13 +5,17 @@ begin
5
5
  require "redis"
6
6
  require "redis/distributed"
7
7
  rescue LoadError
8
- warn "The Redis cache store requires the redis gem, version 4.0.1 or later. Please add it to your Gemfile: `gem \"redis\", \"~> 4.0\"`"
8
+ warn "The Redis cache store requires the redis gem, version 4.0.1 or later. Please add it to your Gemfile: `gem \"redis\", \">= 4.0.1\"`"
9
9
  raise
10
10
  end
11
11
 
12
12
  # Prefer the hiredis driver but don't require it.
13
13
  begin
14
- require "redis/connection/hiredis"
14
+ if ::Redis::VERSION < "5"
15
+ require "redis/connection/hiredis"
16
+ else
17
+ require "hiredis-client"
18
+ end
15
19
  rescue LoadError
16
20
  end
17
21
 
@@ -92,9 +96,11 @@ module ActiveSupport
92
96
  elsif redis
93
97
  redis
94
98
  elsif urls.size > 1
95
- build_redis_distributed_client urls: urls, **redis_options
99
+ build_redis_distributed_client(urls: urls, **redis_options)
100
+ elsif urls.empty?
101
+ build_redis_client(**redis_options)
96
102
  else
97
- build_redis_client url: urls.first, **redis_options
103
+ build_redis_client(url: urls.first, **redis_options)
98
104
  end
99
105
  end
100
106
 
@@ -105,8 +111,8 @@ module ActiveSupport
105
111
  end
106
112
  end
107
113
 
108
- def build_redis_client(url:, **redis_options)
109
- ::Redis.new DEFAULT_REDIS_OPTIONS.merge(redis_options.merge(url: url))
114
+ def build_redis_client(**redis_options)
115
+ ::Redis.new(DEFAULT_REDIS_OPTIONS.merge(redis_options))
110
116
  end
111
117
  end
112
118
 
@@ -139,7 +139,7 @@ module ActiveSupport
139
139
  # popular cache store for large production websites.
140
140
  #
141
141
  # Some implementations may not support all methods beyond the basic cache
142
- # methods of +fetch+, +write+, +read+, +exist?+, and +delete+.
142
+ # methods of #fetch, #write, #read, #exist?, and #delete.
143
143
  #
144
144
  # ActiveSupport::Cache::Store can store any Ruby object that is supported by
145
145
  # its +coder+'s +dump+ and +load+ methods.
@@ -172,11 +172,6 @@ module ActiveSupport
172
172
  # cache.namespace = -> { @last_mod_time } # Set the namespace to a variable
173
173
  # @last_mod_time = Time.now # Invalidate the entire cache by changing namespace
174
174
  #
175
- # Cached data larger than 1kB are compressed by default. To turn off
176
- # compression, pass <tt>compress: false</tt> to the initializer or to
177
- # individual +fetch+ or +write+ method calls. The 1kB compression
178
- # threshold is configurable with the <tt>:compress_threshold</tt> option,
179
- # specified in bytes.
180
175
  class Store
181
176
  cattr_accessor :logger, instance_writer: true
182
177
 
@@ -200,9 +195,19 @@ module ActiveSupport
200
195
  end
201
196
  end
202
197
 
203
- # Creates a new cache. The options will be passed to any write method calls
204
- # except for <tt>:namespace</tt> which can be used to set the global
205
- # namespace for the cache.
198
+ # Creates a new cache.
199
+ #
200
+ # ==== Options
201
+ #
202
+ # * +:namespace+ - Sets the namespace for the cache. This option is
203
+ # especially useful if your application shares a cache with other
204
+ # applications.
205
+ # * +:coder+ - Replaces the default cache entry serialization mechanism
206
+ # with a custom one. The +coder+ must respond to +dump+ and +load+.
207
+ # Using a custom coder disables automatic compression.
208
+ #
209
+ # Any other specified options are treated as default options for the
210
+ # relevant cache operations, such as #read, #write, and #fetch.
206
211
  def initialize(options = nil)
207
212
  @options = options ? normalize_options(options) : {}
208
213
  @options[:compress] = true unless @options.key?(:compress)
@@ -244,111 +249,75 @@ module ActiveSupport
244
249
  # end
245
250
  # cache.fetch('city') # => "Duckburgh"
246
251
  #
247
- # You may also specify additional options via the +options+ argument.
248
- # Setting <tt>force: true</tt> forces a cache "miss," meaning we treat
249
- # the cache value as missing even if it's present. Passing a block is
250
- # required when +force+ is true so this always results in a cache write.
252
+ # ==== Options
251
253
  #
252
- # cache.write('today', 'Monday')
253
- # cache.fetch('today', force: true) { 'Tuesday' } # => 'Tuesday'
254
- # cache.fetch('today', force: true) # => ArgumentError
255
- #
256
- # The +:force+ option is useful when you're calling some other method to
257
- # ask whether you should force a cache write. Otherwise, it's clearer to
258
- # just call <tt>Cache#write</tt>.
259
- #
260
- # Setting <tt>skip_nil: true</tt> will not cache nil result:
261
- #
262
- # cache.fetch('foo') { nil }
263
- # cache.fetch('bar', skip_nil: true) { nil }
264
- # cache.exist?('foo') # => true
265
- # cache.exist?('bar') # => false
266
- #
267
- #
268
- # Setting <tt>compress: false</tt> disables compression of the cache entry.
269
- #
270
- # Setting <tt>:expires_in</tt> will set an expiration time on the cache.
271
- # All caches support auto-expiring content after a specified number of
272
- # seconds. This value can be specified as an option to the constructor
273
- # (in which case all entries will be affected), or it can be supplied to
274
- # the +fetch+ or +write+ method to affect just one entry.
275
- # <tt>:expire_in</tt> and <tt>:expired_in</tt> are aliases for
276
- # <tt>:expires_in</tt>.
277
- #
278
- # cache = ActiveSupport::Cache::MemoryStore.new(expires_in: 5.minutes)
279
- # cache.write(key, value, expires_in: 1.minute) # Set a lower value for one entry
280
- #
281
- # Setting <tt>:expires_at</tt> will set an absolute expiration time on the cache.
282
- # All caches support auto-expiring content after a specified number of
283
- # seconds. This value can only be supplied to the +fetch+ or +write+ method to
284
- # affect just one entry.
285
- #
286
- # cache = ActiveSupport::Cache::MemoryStore.new
287
- # cache.write(key, value, expires_at: Time.now.at_end_of_hour)
288
- #
289
- # Setting <tt>:version</tt> verifies the cache stored under <tt>name</tt>
290
- # is of the same version. nil is returned on mismatches despite contents.
291
- # This feature is used to support recyclable cache keys.
292
- #
293
- # Setting <tt>:race_condition_ttl</tt> is very useful in situations where
294
- # a cache entry is used very frequently and is under heavy load. If a
295
- # cache expires and due to heavy load several different processes will try
296
- # to read data natively and then they all will try to write to cache. To
297
- # avoid that case the first process to find an expired cache entry will
298
- # bump the cache expiration time by the value set in <tt>:race_condition_ttl</tt>.
299
- # Yes, this process is extending the time for a stale value by another few
300
- # seconds. Because of extended life of the previous cache, other processes
301
- # will continue to use slightly stale data for a just a bit longer. In the
302
- # meantime that first process will go ahead and will write into cache the
303
- # new value. After that all the processes will start getting the new value.
304
- # The key is to keep <tt>:race_condition_ttl</tt> small.
305
- #
306
- # If the process regenerating the entry errors out, the entry will be
307
- # regenerated after the specified number of seconds. Also note that the
308
- # life of stale cache is extended only if it expired recently. Otherwise
309
- # a new value is generated and <tt>:race_condition_ttl</tt> does not play
310
- # any role.
311
- #
312
- # # Set all values to expire after one minute.
313
- # cache = ActiveSupport::Cache::MemoryStore.new(expires_in: 1.minute)
314
- #
315
- # cache.write('foo', 'original value')
316
- # val_1 = nil
317
- # val_2 = nil
318
- # sleep 60
319
- #
320
- # Thread.new do
321
- # val_1 = cache.fetch('foo', race_condition_ttl: 10.seconds) do
322
- # sleep 1
323
- # 'new value 1'
324
- # end
325
- # end
254
+ # Internally, +fetch+ calls #read_entry, and calls #write_entry on a cache
255
+ # miss. Thus, +fetch+ supports the same options as #read and #write.
256
+ # Additionally, +fetch+ supports the following options:
326
257
  #
327
- # Thread.new do
328
- # val_2 = cache.fetch('foo', race_condition_ttl: 10.seconds) do
329
- # 'new value 2'
330
- # end
331
- # end
258
+ # * <tt>force: true</tt> - Forces a cache "miss," meaning we treat the
259
+ # cache value as missing even if it's present. Passing a block is
260
+ # required when +force+ is true so this always results in a cache write.
332
261
  #
333
- # cache.fetch('foo') # => "original value"
334
- # sleep 10 # First thread extended the life of cache by another 10 seconds
335
- # cache.fetch('foo') # => "new value 1"
336
- # val_1 # => "new value 1"
337
- # val_2 # => "original value"
262
+ # cache.write('today', 'Monday')
263
+ # cache.fetch('today', force: true) { 'Tuesday' } # => 'Tuesday'
264
+ # cache.fetch('today', force: true) # => ArgumentError
338
265
  #
339
- # Other options will be handled by the specific cache store implementation.
340
- # Internally, #fetch calls #read_entry, and calls #write_entry on a cache
341
- # miss. +options+ will be passed to the #read and #write calls.
266
+ # The +:force+ option is useful when you're calling some other method to
267
+ # ask whether you should force a cache write. Otherwise, it's clearer to
268
+ # just call +write+.
342
269
  #
343
- # For example, MemCacheStore's #write method supports the +:raw+
344
- # option, which tells the memcached server to store all values as strings.
345
- # We can use this option with #fetch too:
270
+ # * <tt>skip_nil: true</tt> - Prevents caching a nil result:
271
+ #
272
+ # cache.fetch('foo') { nil }
273
+ # cache.fetch('bar', skip_nil: true) { nil }
274
+ # cache.exist?('foo') # => true
275
+ # cache.exist?('bar') # => false
276
+ #
277
+ # * +:race_condition_ttl+ - Specifies the number of seconds during which
278
+ # an expired value can be reused while a new value is being generated.
279
+ # This can be used to prevent race conditions when cache entries expire,
280
+ # by preventing multiple processes from simultaneously regenerating the
281
+ # same entry (also known as the dog pile effect).
282
+ #
283
+ # When a process encounters a cache entry that has expired less than
284
+ # +:race_condition_ttl+ seconds ago, it will bump the expiration time by
285
+ # +:race_condition_ttl+ seconds before generating a new value. During
286
+ # this extended time window, while the process generates a new value,
287
+ # other processes will continue to use the old value. After the first
288
+ # process writes the new value, other processes will then use it.
289
+ #
290
+ # If the first process errors out while generating a new value, another
291
+ # process can try to generate a new value after the extended time window
292
+ # has elapsed.
293
+ #
294
+ # # Set all values to expire after one minute.
295
+ # cache = ActiveSupport::Cache::MemoryStore.new(expires_in: 1.minute)
296
+ #
297
+ # cache.write('foo', 'original value')
298
+ # val_1 = nil
299
+ # val_2 = nil
300
+ # sleep 60
301
+ #
302
+ # Thread.new do
303
+ # val_1 = cache.fetch('foo', race_condition_ttl: 10.seconds) do
304
+ # sleep 1
305
+ # 'new value 1'
306
+ # end
307
+ # end
308
+ #
309
+ # Thread.new do
310
+ # val_2 = cache.fetch('foo', race_condition_ttl: 10.seconds) do
311
+ # 'new value 2'
312
+ # end
313
+ # end
314
+ #
315
+ # cache.fetch('foo') # => "original value"
316
+ # sleep 10 # First thread extended the life of cache by another 10 seconds
317
+ # cache.fetch('foo') # => "new value 1"
318
+ # val_1 # => "new value 1"
319
+ # val_2 # => "original value"
346
320
  #
347
- # cache = ActiveSupport::Cache::MemCacheStore.new
348
- # cache.fetch("foo", force: true, raw: true) do
349
- # :bar
350
- # end
351
- # cache.fetch('foo') # => "bar"
352
321
  def fetch(name, options = nil, &block)
353
322
  if block_given?
354
323
  options = merged_options(options)
@@ -383,7 +352,13 @@ module ActiveSupport
383
352
  # <tt>:version</tt> options, both of these conditions are applied before
384
353
  # the data is returned.
385
354
  #
386
- # Options are passed to the underlying cache implementation.
355
+ # ==== Options
356
+ #
357
+ # * +:version+ - Specifies a version for the cache entry. If the cached
358
+ # version does not match the requested version, the read will be treated
359
+ # as a cache miss. This feature is used to support recyclable cache keys.
360
+ #
361
+ # Other options will be handled by the specific cache store implementation.
387
362
  def read(name, options = nil)
388
363
  options = merged_options(options)
389
364
  key = normalize_key(name, options)
@@ -491,9 +466,39 @@ module ActiveSupport
491
466
  end
492
467
  end
493
468
 
494
- # Writes the value to the cache, with the key.
469
+ # Writes the value to the cache with the key. The value must be supported
470
+ # by the +coder+'s +dump+ and +load+ methods.
495
471
  #
496
- # Options are passed to the underlying cache implementation.
472
+ # By default, cache entries larger than 1kB are compressed. Compression
473
+ # allows more data to be stored in the same memory footprint, leading to
474
+ # fewer cache evictions and higher hit rates.
475
+ #
476
+ # ==== Options
477
+ #
478
+ # * <tt>compress: false</tt> - Disables compression of the cache entry.
479
+ #
480
+ # * +:compress_threshold+ - The compression threshold, specified in bytes.
481
+ # \Cache entries larger than this threshold will be compressed. Defaults
482
+ # to +1.kilobyte+.
483
+ #
484
+ # * +:expires_in+ - Sets a relative expiration time for the cache entry,
485
+ # specified in seconds. +:expire_in+ and +:expired_in+ are aliases for
486
+ # +:expires_in+.
487
+ #
488
+ # cache = ActiveSupport::Cache::MemoryStore.new(expires_in: 5.minutes)
489
+ # cache.write(key, value, expires_in: 1.minute) # Set a lower value for one entry
490
+ #
491
+ # * +:expires_at+ - Sets an absolute expiration time for the cache entry.
492
+ #
493
+ # cache = ActiveSupport::Cache::MemoryStore.new
494
+ # cache.write(key, value, expires_at: Time.now.at_end_of_hour)
495
+ #
496
+ # * +:version+ - Specifies a version for the cache entry. When reading
497
+ # from the cache, if the cached version does not match the requested
498
+ # version, the read will be treated as a cache miss. This feature is
499
+ # used to support recyclable cache keys.
500
+ #
501
+ # Other options will be handled by the specific cache store implementation.
497
502
  def write(name, value, options = nil)
498
503
  options = merged_options(options)
499
504
 
@@ -569,7 +574,7 @@ module ActiveSupport
569
574
  raise NotImplementedError.new("#{self.class.name} does not support decrement")
570
575
  end
571
576
 
572
- # Cleanups the cache by removing expired entries.
577
+ # Cleans up the cache by removing expired entries.
573
578
  #
574
579
  # Options are passed to the underlying cache implementation.
575
580
  #
@@ -838,7 +843,7 @@ module ActiveSupport
838
843
  when 7.0
839
844
  Rails70Coder
840
845
  else
841
- raise ArgumentError, "Unknown ActiveSupport::Cache.format_version #{Cache.format_version.inspect}"
846
+ raise ArgumentError, "Unknown ActiveSupport::Cache.format_version: #{Cache.format_version.inspect}"
842
847
  end
843
848
  end
844
849
  end
@@ -114,10 +114,10 @@ module ActiveSupport
114
114
  raise ArgumentError, "#{behavior.inspect} is not a valid deprecation behavior."
115
115
  end
116
116
 
117
- if behavior.arity == 4 || behavior.arity == -1
118
- behavior
119
- else
117
+ if behavior.respond_to?(:arity) && behavior.arity == 2
120
118
  -> message, callstack, _, _ { behavior.call(message, callstack) }
119
+ else
120
+ behavior
121
121
  end
122
122
  end
123
123
  end
@@ -45,10 +45,22 @@ module ActiveSupport
45
45
  @env_key, @raise_if_missing_key = env_key, raise_if_missing_key
46
46
  end
47
47
 
48
+ # Returns the encryption key, first trying the environment variable
49
+ # specified by +env_key+, then trying the key file specified by +key_path+.
50
+ # If +raise_if_missing_key+ is true, raises MissingKeyError if the
51
+ # environment variable is not set and the key file does not exist.
48
52
  def key
49
53
  read_env_key || read_key_file || handle_missing_key
50
54
  end
51
55
 
56
+ # Reads the file and returns the decrypted content.
57
+ #
58
+ # Raises:
59
+ # - MissingKeyError if the key is missing and +raise_if_missing_key+ is true.
60
+ # - MissingContentError if the encrypted file does not exist or otherwise
61
+ # if the key is missing.
62
+ # - ActiveSupport::MessageEncryptor::InvalidMessage if the content cannot be
63
+ # decrypted or verified.
52
64
  def read
53
65
  if !key.nil? && content_path.exist?
54
66
  decrypt content_path.binread
@@ -9,8 +9,8 @@ module ActiveSupport
9
9
  module VERSION
10
10
  MAJOR = 7
11
11
  MINOR = 0
12
- TINY = 3
13
- PRE = "1"
12
+ TINY = 4
13
+ PRE = nil
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -26,6 +26,18 @@ module ActiveSupport
26
26
  # run_load_hooks will then execute all the hooks that were registered
27
27
  # with the on_load method. In the case of the above example, it will
28
28
  # execute the block of code that is in the +initializer+.
29
+ #
30
+ # Registering a hook that has already run results in that hook executing
31
+ # immediately. This allows hooks to be nested for code that relies on
32
+ # multiple lazily loaded components:
33
+ #
34
+ # initializer "action_text.renderer" do
35
+ # ActiveSupport.on_load(:action_controller_base) do
36
+ # ActiveSupport.on_load(:action_text_content) do
37
+ # self.default_renderer = Class.new(ActionController::Base).renderer
38
+ # end
39
+ # end
40
+ # end
29
41
  module LazyLoadHooks
30
42
  def self.extended(base) # :nodoc:
31
43
  base.class_eval do
@@ -36,7 +48,8 @@ module ActiveSupport
36
48
  end
37
49
 
38
50
  # Declares a block that will be executed when a Rails component is fully
39
- # loaded.
51
+ # loaded. If the component has already loaded, the block is executed
52
+ # immediately.
40
53
  #
41
54
  # Options:
42
55
  #
@@ -22,10 +22,6 @@ module ActiveSupport
22
22
  # Broadcasts logs to multiple loggers.
23
23
  def self.broadcast(logger) # :nodoc:
24
24
  Module.new do
25
- define_singleton_method(:extended) do |base|
26
- base.public_send(:broadcast_to, logger) if base.respond_to?(:broadcast_to)
27
- end
28
-
29
25
  define_method(:add) do |*args, &block|
30
26
  logger.add(*args, &block)
31
27
  super(*args, &block)
@@ -46,6 +42,11 @@ module ActiveSupport
46
42
  super(name)
47
43
  end
48
44
 
45
+ define_method(:formatter=) do |formatter|
46
+ logger.formatter = formatter
47
+ super(formatter)
48
+ end
49
+
49
50
  define_method(:level=) do |level|
50
51
  logger.level = level
51
52
  super(level)
@@ -244,6 +244,12 @@ module ActiveSupport
244
244
  notifier.subscribe(pattern, callback, monotonic: false, &block)
245
245
  end
246
246
 
247
+ # Performs the same functionality as #subscribe, but the +start+ and
248
+ # +finish+ block arguments are in monotonic time instead of wall-clock
249
+ # time. Monotonic time will not jump forward or backward (due to NTP or
250
+ # Daylights Savings). Use +monotonic_subscribe+ when accuracy of time
251
+ # duration is important. For example, computing elapsed time between
252
+ # two events.
247
253
  def monotonic_subscribe(pattern = nil, callback = nil, &block)
248
254
  notifier.subscribe(pattern, callback, monotonic: true, &block)
249
255
  end
@@ -15,8 +15,8 @@ module ActiveSupport
15
15
  private
16
16
  def method_missing(method, *arguments, &block)
17
17
  options = nil
18
- if arguments.first.is_a?(Proc)
19
- proc = arguments.pop
18
+ if arguments.size == 1 && arguments.first.is_a?(Proc)
19
+ proc = arguments.shift
20
20
  arguments << lambda { |*args| @options.deep_merge(proc.call(*args)) }
21
21
  elsif arguments.last.respond_to?(:to_hash)
22
22
  options = @options.deep_merge(arguments.pop)
@@ -30,20 +30,20 @@ module ActiveSupport
30
30
  # any.
31
31
  #
32
32
  # class ApplicationController < ActionController::Base
33
- # rescue_from User::NotAuthorized, with: :deny_access # self defined exception
34
- # rescue_from ActiveRecord::RecordInvalid, with: :show_errors
33
+ # rescue_from User::NotAuthorized, with: :deny_access
34
+ # rescue_from ActiveRecord::RecordInvalid, with: :show_record_errors
35
35
  #
36
- # rescue_from 'MyAppError::Base' do |exception|
37
- # render xml: exception, status: 500
36
+ # rescue_from "MyApp::BaseError" do |exception|
37
+ # redirect_to root_url, alert: exception.message
38
38
  # end
39
39
  #
40
40
  # private
41
41
  # def deny_access
42
- # ...
42
+ # head :forbidden
43
43
  # end
44
44
  #
45
- # def show_errors(exception)
46
- # exception.record.new_record? ? ...
45
+ # def show_record_errors(exception)
46
+ # redirect_back_or_to root_url, alert: exception.record.errors.full_messages.to_sentence
47
47
  # end
48
48
  # end
49
49
  #
@@ -79,7 +79,7 @@ module ActiveSupport
79
79
  # Be sure to re-raise unhandled exceptions if this is what you expect.
80
80
  #
81
81
  # begin
82
- #
82
+ # # ...
83
83
  # rescue => exception
84
84
  # rescue_with_handler(exception) || raise
85
85
  # end
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/core_ext/module/delegation"
4
- require "active_support/core_ext/module/redefine_method"
5
4
  require "active_support/core_ext/object/blank"
6
5
  require "logger"
7
6
  require "active_support/logger"
@@ -95,20 +94,6 @@ module ActiveSupport
95
94
 
96
95
  delegate :push_tags, :pop_tags, :clear_tags!, to: :formatter
97
96
 
98
- def broadcast_to(other_logger) # :nodoc:
99
- define_singleton_method(:formatter=) do |formatter|
100
- other_logger.formatter ||= formatter
101
-
102
- other_logger.formatter.singleton_class.redefine_method(:current_tags) do
103
- formatter.current_tags
104
- end
105
-
106
- super(formatter)
107
- end
108
-
109
- self.formatter = self.formatter.clone
110
- end
111
-
112
97
  def tagged(*tags)
113
98
  if block_given?
114
99
  formatter.tagged(*tags) { yield self }
@@ -147,5 +147,9 @@ module ActiveSupport
147
147
  alias :assert_not_same :refute_same
148
148
 
149
149
  ActiveSupport.run_load_hooks(:active_support_test_case, self)
150
+
151
+ def inspect # :nodoc:
152
+ Object.instance_method(:to_s).bind_call(self)
153
+ end
150
154
  end
151
155
  end
@@ -337,9 +337,8 @@ module ActiveSupport
337
337
  alias_method :in, :+
338
338
 
339
339
  # Subtracts an interval of time and returns a new TimeWithZone object unless
340
- # the other value +acts_like?+ time. Then it will return a Float of the difference
341
- # between the two times that represents the difference between the current
342
- # object's time and the +other+ time.
340
+ # the other value +acts_like?+ time. In which case, it will subtract the
341
+ # other time and return the difference in seconds as a Float.
343
342
  #
344
343
  # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
345
344
  # now = Time.zone.now # => Mon, 03 Nov 2014 00:26:28.725182881 EST -05:00
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.0.3.1
4
+ version: 7.0.4
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: 2022-07-12 00:00:00.000000000 Z
11
+ date: 2022-09-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: i18n
@@ -359,10 +359,10 @@ licenses:
359
359
  - MIT
360
360
  metadata:
361
361
  bug_tracker_uri: https://github.com/rails/rails/issues
362
- changelog_uri: https://github.com/rails/rails/blob/v7.0.3.1/activesupport/CHANGELOG.md
363
- documentation_uri: https://api.rubyonrails.org/v7.0.3.1/
362
+ changelog_uri: https://github.com/rails/rails/blob/v7.0.4/activesupport/CHANGELOG.md
363
+ documentation_uri: https://api.rubyonrails.org/v7.0.4/
364
364
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
365
- source_code_uri: https://github.com/rails/rails/tree/v7.0.3.1/activesupport
365
+ source_code_uri: https://github.com/rails/rails/tree/v7.0.4/activesupport
366
366
  rubygems_mfa_required: 'true'
367
367
  post_install_message:
368
368
  rdoc_options: