activesupport 7.0.2.4 → 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.

Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +27 -0
  3. data/lib/active_support/backtrace_cleaner.rb +2 -2
  4. data/lib/active_support/cache/mem_cache_store.rb +21 -5
  5. data/lib/active_support/cache/memory_store.rb +1 -1
  6. data/lib/active_support/cache/redis_cache_store.rb +17 -11
  7. data/lib/active_support/cache/strategy/local_cache.rb +3 -0
  8. data/lib/active_support/cache.rb +122 -114
  9. data/lib/active_support/callbacks.rb +5 -5
  10. data/lib/active_support/configurable.rb +2 -2
  11. data/lib/active_support/core_ext/array/conversions.rb +0 -1
  12. data/lib/active_support/core_ext/array/inquiry.rb +2 -2
  13. data/lib/active_support/core_ext/date/calculations.rb +5 -5
  14. data/lib/active_support/core_ext/date/conversions.rb +3 -3
  15. data/lib/active_support/core_ext/date_and_time/calculations.rb +4 -4
  16. data/lib/active_support/core_ext/date_and_time/compatibility.rb +1 -1
  17. data/lib/active_support/core_ext/enumerable.rb +26 -9
  18. data/lib/active_support/core_ext/hash/conversions.rb +0 -1
  19. data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -3
  20. data/lib/active_support/core_ext/kernel/singleton_class.rb +1 -1
  21. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +4 -4
  22. data/lib/active_support/core_ext/numeric/conversions.rb +1 -1
  23. data/lib/active_support/core_ext/object/json.rb +1 -1
  24. data/lib/active_support/core_ext/range/overlaps.rb +1 -1
  25. data/lib/active_support/core_ext/securerandom.rb +1 -1
  26. data/lib/active_support/core_ext/string/conversions.rb +2 -2
  27. data/lib/active_support/core_ext/string/inquiry.rb +1 -1
  28. data/lib/active_support/core_ext/string/output_safety.rb +3 -3
  29. data/lib/active_support/core_ext/time/calculations.rb +2 -2
  30. data/lib/active_support/core_ext/time/zones.rb +3 -3
  31. data/lib/active_support/deprecation/behaviors.rb +4 -4
  32. data/lib/active_support/deprecation/proxy_wrappers.rb +1 -1
  33. data/lib/active_support/deprecation.rb +1 -1
  34. data/lib/active_support/encrypted_file.rb +12 -0
  35. data/lib/active_support/error_reporter.rb +2 -2
  36. data/lib/active_support/evented_file_update_checker.rb +2 -4
  37. data/lib/active_support/gem_version.rb +3 -3
  38. data/lib/active_support/inflector/transliterate.rb +1 -1
  39. data/lib/active_support/isolated_execution_state.rb +8 -0
  40. data/lib/active_support/key_generator.rb +4 -4
  41. data/lib/active_support/lazy_load_hooks.rb +28 -4
  42. data/lib/active_support/log_subscriber/test_helper.rb +2 -2
  43. data/lib/active_support/log_subscriber.rb +2 -2
  44. data/lib/active_support/message_encryptor.rb +4 -3
  45. data/lib/active_support/notifications.rb +8 -2
  46. data/lib/active_support/option_merger.rb +2 -2
  47. data/lib/active_support/ordered_options.rb +1 -1
  48. data/lib/active_support/railtie.rb +5 -5
  49. data/lib/active_support/rescuable.rb +10 -10
  50. data/lib/active_support/secure_compare_rotator.rb +1 -1
  51. data/lib/active_support/test_case.rb +4 -0
  52. data/lib/active_support/testing/assertions.rb +1 -1
  53. data/lib/active_support/time_with_zone.rb +6 -7
  54. data/lib/active_support/values/time_zone.rb +5 -5
  55. data/lib/active_support/version.rb +1 -1
  56. metadata +6 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '02869b1bcaf37b6194486f794ee952cd0fc99be001f71f7aa6c2f883acbbb124'
4
- data.tar.gz: b2819e4848cfeb61f674e89f2dbc734c1e3a06003b85f9e28153a4b1cf5d1c42
3
+ metadata.gz: 342ae35dc85cf68674201fd516c85b208adccc0c930e888d301d0ed5fa9e2cad
4
+ data.tar.gz: 8c611de7bc5d9ea07c57a1848abb556e9090009db790404fa1da49278a49d0b3
5
5
  SHA512:
6
- metadata.gz: 8949b44a0afb53bc581e1df773c8a991b6c6f0e2533e1d7198686ff1013cc0e24cd203f26edd07a21c7a54edb30b8b8f537d2e17987533a66ccf7b8239d7fde3
7
- data.tar.gz: 6199375f07c08dee86c37886c6b2e063d6cc8a65f326cb9697aefa97b85b4f4bce0ff4fe1f702c7b223c80e5fd1ef4c293f57dc35dd30a8e8159d74eafb1589d
6
+ metadata.gz: 68144c1574e6fe740072399749fef96a992ad390c5877a63110758a7184256882e118d9dc5290150b2b623a391a37ab8c2648e49782ae2f9b3c42cb9e21837c4
7
+ data.tar.gz: 6906af5f3a19a04f13ec6ca1c8f492259018181ad3bcb63eb75bdb8cf2fe7316a6dd787125de809cfc04a7dd72ff310f673001f69865b0753fcc571966b8b573
data/CHANGELOG.md CHANGED
@@ -1,3 +1,30 @@
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
+
18
+ ## Rails 7.0.3.1 (July 12, 2022) ##
19
+
20
+ * No changes.
21
+
22
+
23
+ ## Rails 7.0.3 (May 09, 2022) ##
24
+
25
+ * No changes.
26
+
27
+
1
28
  ## Rails 7.0.2.4 (April 26, 2022) ##
2
29
 
3
30
  * Fix and add protections for XSS in `ActionView::Helpers` and `ERB::Util`.
@@ -21,10 +21,10 @@ module ActiveSupport
21
21
  #
22
22
  # To reconfigure an existing BacktraceCleaner (like the default one in Rails)
23
23
  # and show as much data as possible, you can always call
24
- # <tt>BacktraceCleaner#remove_silencers!</tt>, which will restore the
24
+ # BacktraceCleaner#remove_silencers!, which will restore the
25
25
  # backtrace to a pristine state. If you need to reconfigure an existing
26
26
  # BacktraceCleaner so that it does not filter or modify the paths of any lines
27
- # of the backtrace, you can call <tt>BacktraceCleaner#remove_filters!</tt>
27
+ # of the backtrace, you can call BacktraceCleaner#remove_filters!
28
28
  # These two methods will give you a completely untouched backtrace.
29
29
  #
30
30
  # Inspired by the Quiet Backtrace gem by thoughtbot.
@@ -104,7 +104,7 @@ module ActiveSupport
104
104
  #
105
105
  # ActiveSupport::Cache::MemCacheStore.new("localhost", "server-downstairs.localnetwork:8229")
106
106
  #
107
- # If no addresses are provided, but ENV['MEMCACHE_SERVERS'] is defined, it will be used instead. Otherwise,
107
+ # If no addresses are provided, but <tt>ENV['MEMCACHE_SERVERS']</tt> is defined, it will be used instead. Otherwise,
108
108
  # MemCacheStore will connect to localhost:11211 (the default memcached port).
109
109
  def initialize(*addresses)
110
110
  addresses = addresses.flatten
@@ -128,9 +128,25 @@ 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
- # operator and can only be used on values written with the :raw option.
133
- # Calling it on a value not stored with :raw will initialize that value
148
+ # operator and can only be used on values written with the +:raw+ option.
149
+ # Calling it on a value not stored with +:raw+ will initialize that value
134
150
  # to zero.
135
151
  def increment(name, amount = 1, options = nil)
136
152
  options = merged_options(options)
@@ -142,8 +158,8 @@ module ActiveSupport
142
158
  end
143
159
 
144
160
  # Decrement a cached value. This method uses the memcached decr atomic
145
- # operator and can only be used on values written with the :raw option.
146
- # Calling it on a value not stored with :raw will initialize that value
161
+ # operator and can only be used on values written with the +:raw+ option.
162
+ # Calling it on a value not stored with +:raw+ will initialize that value
147
163
  # to zero.
148
164
  def decrement(name, amount = 1, options = nil)
149
165
  options = merged_options(options)
@@ -11,7 +11,7 @@ module ActiveSupport
11
11
  # to share cache data with each other and this may not be the most
12
12
  # appropriate cache in that scenario.
13
13
  #
14
- # This cache has a bounded size specified by the :size options to the
14
+ # This cache has a bounded size specified by the +:size+ options to the
15
15
  # initializer (default is 32Mb). When the cache exceeds the allotted size,
16
16
  # a cleanup will occur which tries to prune the cache down to three quarters
17
17
  # of the maximum size by removing the least recently used entries.
@@ -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 +145,7 @@ module ActiveSupport
139
145
  #
140
146
  # Race condition TTL is not set by default. This can be used to avoid
141
147
  # "thundering herd" cache writes when hot cache entries are expired.
142
- # See <tt>ActiveSupport::Cache::Store#fetch</tt> for more.
148
+ # See ActiveSupport::Cache::Store#fetch for more.
143
149
  def initialize(namespace: nil, compress: true, compress_threshold: 1.kilobyte, coder: default_coder, expires_in: nil, race_condition_ttl: nil, error_handler: DEFAULT_ERROR_HANDLER, **redis_options)
144
150
  @redis_options = redis_options
145
151
 
@@ -225,8 +231,8 @@ module ActiveSupport
225
231
  # Cache Store API implementation.
226
232
  #
227
233
  # Increment a cached value. This method uses the Redis incr atomic
228
- # operator and can only be used on values written with the :raw option.
229
- # Calling it on a value not stored with :raw will initialize that value
234
+ # operator and can only be used on values written with the +:raw+ option.
235
+ # Calling it on a value not stored with +:raw+ will initialize that value
230
236
  # to zero.
231
237
  #
232
238
  # Failsafe: Raises errors.
@@ -248,8 +254,8 @@ module ActiveSupport
248
254
  # Cache Store API implementation.
249
255
  #
250
256
  # Decrement a cached value. This method uses the Redis decr atomic
251
- # operator and can only be used on values written with the :raw option.
252
- # Calling it on a value not stored with :raw will initialize that value
257
+ # operator and can only be used on values written with the +:raw+ option.
258
+ # Calling it on a value not stored with +:raw+ will initialize that value
253
259
  # to zero.
254
260
  #
255
261
  # Failsafe: Raises errors.
@@ -123,6 +123,9 @@ module ActiveSupport
123
123
  return super unless local_cache
124
124
 
125
125
  local_entries = local_cache.read_multi_entries(keys)
126
+ local_entries.transform_values! do |payload|
127
+ deserialize_entry(payload).value
128
+ end
126
129
  missed_keys = keys - local_entries.keys
127
130
 
128
131
  if missed_keys.any?
@@ -139,9 +139,10 @@ 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
- # ActiveSupport::Cache::Store can store any serializable Ruby object.
144
+ # ActiveSupport::Cache::Store can store any Ruby object that is supported by
145
+ # its +coder+'s +dump+ and +load+ methods.
145
146
  #
146
147
  # cache = ActiveSupport::Cache::MemoryStore.new
147
148
  #
@@ -149,6 +150,8 @@ module ActiveSupport
149
150
  # cache.write('city', "Duckburgh")
150
151
  # cache.read('city') # => "Duckburgh"
151
152
  #
153
+ # cache.write('not serializable', Proc.new {}) # => TypeError
154
+ #
152
155
  # Keys are always translated into Strings and are case sensitive. When an
153
156
  # object is specified as a key and has a +cache_key+ method defined, this
154
157
  # method will be called to define the key. Otherwise, the +to_param+
@@ -169,11 +172,6 @@ module ActiveSupport
169
172
  # cache.namespace = -> { @last_mod_time } # Set the namespace to a variable
170
173
  # @last_mod_time = Time.now # Invalidate the entire cache by changing namespace
171
174
  #
172
- # Cached data larger than 1kB are compressed by default. To turn off
173
- # compression, pass <tt>compress: false</tt> to the initializer or to
174
- # individual +fetch+ or +write+ method calls. The 1kB compression
175
- # threshold is configurable with the <tt>:compress_threshold</tt> option,
176
- # specified in bytes.
177
175
  class Store
178
176
  cattr_accessor :logger, instance_writer: true
179
177
 
@@ -197,9 +195,19 @@ module ActiveSupport
197
195
  end
198
196
  end
199
197
 
200
- # Creates a new cache. The options will be passed to any write method calls
201
- # except for <tt>:namespace</tt> which can be used to set the global
202
- # 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.
203
211
  def initialize(options = nil)
204
212
  @options = options ? normalize_options(options) : {}
205
213
  @options[:compress] = true unless @options.key?(:compress)
@@ -241,111 +249,75 @@ module ActiveSupport
241
249
  # end
242
250
  # cache.fetch('city') # => "Duckburgh"
243
251
  #
244
- # You may also specify additional options via the +options+ argument.
245
- # Setting <tt>force: true</tt> forces a cache "miss," meaning we treat
246
- # the cache value as missing even if it's present. Passing a block is
247
- # required when +force+ is true so this always results in a cache write.
252
+ # ==== Options
248
253
  #
249
- # cache.write('today', 'Monday')
250
- # cache.fetch('today', force: true) { 'Tuesday' } # => 'Tuesday'
251
- # cache.fetch('today', force: true) # => ArgumentError
252
- #
253
- # The +:force+ option is useful when you're calling some other method to
254
- # ask whether you should force a cache write. Otherwise, it's clearer to
255
- # just call <tt>Cache#write</tt>.
256
- #
257
- # Setting <tt>skip_nil: true</tt> will not cache nil result:
258
- #
259
- # cache.fetch('foo') { nil }
260
- # cache.fetch('bar', skip_nil: true) { nil }
261
- # cache.exist?('foo') # => true
262
- # cache.exist?('bar') # => false
263
- #
264
- #
265
- # Setting <tt>compress: false</tt> disables compression of the cache entry.
266
- #
267
- # Setting <tt>:expires_in</tt> will set an expiration time on the cache.
268
- # All caches support auto-expiring content after a specified number of
269
- # seconds. This value can be specified as an option to the constructor
270
- # (in which case all entries will be affected), or it can be supplied to
271
- # the +fetch+ or +write+ method to affect just one entry.
272
- # <tt>:expire_in</tt> and <tt>:expired_in</tt> are aliases for
273
- # <tt>:expires_in</tt>.
274
- #
275
- # cache = ActiveSupport::Cache::MemoryStore.new(expires_in: 5.minutes)
276
- # cache.write(key, value, expires_in: 1.minute) # Set a lower value for one entry
277
- #
278
- # Setting <tt>:expires_at</tt> will set an absolute expiration time on the cache.
279
- # All caches support auto-expiring content after a specified number of
280
- # seconds. This value can only be supplied to the +fetch+ or +write+ method to
281
- # affect just one entry.
282
- #
283
- # cache = ActiveSupport::Cache::MemoryStore.new
284
- # cache.write(key, value, expires_at: Time.now.at_end_of_hour)
285
- #
286
- # Setting <tt>:version</tt> verifies the cache stored under <tt>name</tt>
287
- # is of the same version. nil is returned on mismatches despite contents.
288
- # This feature is used to support recyclable cache keys.
289
- #
290
- # Setting <tt>:race_condition_ttl</tt> is very useful in situations where
291
- # a cache entry is used very frequently and is under heavy load. If a
292
- # cache expires and due to heavy load several different processes will try
293
- # to read data natively and then they all will try to write to cache. To
294
- # avoid that case the first process to find an expired cache entry will
295
- # bump the cache expiration time by the value set in <tt>:race_condition_ttl</tt>.
296
- # Yes, this process is extending the time for a stale value by another few
297
- # seconds. Because of extended life of the previous cache, other processes
298
- # will continue to use slightly stale data for a just a bit longer. In the
299
- # meantime that first process will go ahead and will write into cache the
300
- # new value. After that all the processes will start getting the new value.
301
- # The key is to keep <tt>:race_condition_ttl</tt> small.
302
- #
303
- # If the process regenerating the entry errors out, the entry will be
304
- # regenerated after the specified number of seconds. Also note that the
305
- # life of stale cache is extended only if it expired recently. Otherwise
306
- # a new value is generated and <tt>:race_condition_ttl</tt> does not play
307
- # any role.
308
- #
309
- # # Set all values to expire after one minute.
310
- # cache = ActiveSupport::Cache::MemoryStore.new(expires_in: 1.minute)
311
- #
312
- # cache.write('foo', 'original value')
313
- # val_1 = nil
314
- # val_2 = nil
315
- # sleep 60
316
- #
317
- # Thread.new do
318
- # val_1 = cache.fetch('foo', race_condition_ttl: 10.seconds) do
319
- # sleep 1
320
- # 'new value 1'
321
- # end
322
- # 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:
323
257
  #
324
- # Thread.new do
325
- # val_2 = cache.fetch('foo', race_condition_ttl: 10.seconds) do
326
- # 'new value 2'
327
- # end
328
- # 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.
329
261
  #
330
- # cache.fetch('foo') # => "original value"
331
- # sleep 10 # First thread extended the life of cache by another 10 seconds
332
- # cache.fetch('foo') # => "new value 1"
333
- # val_1 # => "new value 1"
334
- # val_2 # => "original value"
262
+ # cache.write('today', 'Monday')
263
+ # cache.fetch('today', force: true) { 'Tuesday' } # => 'Tuesday'
264
+ # cache.fetch('today', force: true) # => ArgumentError
335
265
  #
336
- # Other options will be handled by the specific cache store implementation.
337
- # Internally, #fetch calls #read_entry, and calls #write_entry on a cache
338
- # 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+.
339
269
  #
340
- # For example, MemCacheStore's #write method supports the +:raw+
341
- # option, which tells the memcached server to store all values as strings.
342
- # 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"
343
320
  #
344
- # cache = ActiveSupport::Cache::MemCacheStore.new
345
- # cache.fetch("foo", force: true, raw: true) do
346
- # :bar
347
- # end
348
- # cache.fetch('foo') # => "bar"
349
321
  def fetch(name, options = nil, &block)
350
322
  if block_given?
351
323
  options = merged_options(options)
@@ -380,7 +352,13 @@ module ActiveSupport
380
352
  # <tt>:version</tt> options, both of these conditions are applied before
381
353
  # the data is returned.
382
354
  #
383
- # 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.
384
362
  def read(name, options = nil)
385
363
  options = merged_options(options)
386
364
  key = normalize_key(name, options)
@@ -488,9 +466,39 @@ module ActiveSupport
488
466
  end
489
467
  end
490
468
 
491
- # 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.
492
471
  #
493
- # 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.
494
502
  def write(name, value, options = nil)
495
503
  options = merged_options(options)
496
504
 
@@ -566,7 +574,7 @@ module ActiveSupport
566
574
  raise NotImplementedError.new("#{self.class.name} does not support decrement")
567
575
  end
568
576
 
569
- # Cleanups the cache by removing expired entries.
577
+ # Cleans up the cache by removing expired entries.
570
578
  #
571
579
  # Options are passed to the underlying cache implementation.
572
580
  #
@@ -835,7 +843,7 @@ module ActiveSupport
835
843
  when 7.0
836
844
  Rails70Coder
837
845
  else
838
- raise ArgumentError, "Unknown ActiveSupport::Cache.format_version #{Cache.format_version.inspect}"
846
+ raise ArgumentError, "Unknown ActiveSupport::Cache.format_version: #{Cache.format_version.inspect}"
839
847
  end
840
848
  end
841
849
  end
@@ -16,19 +16,19 @@ module ActiveSupport
16
16
  # needing to override or redefine methods of the base class.
17
17
  #
18
18
  # Mixing in this module allows you to define the events in the object's
19
- # life cycle that will support callbacks (via +ClassMethods.define_callbacks+),
19
+ # life cycle that will support callbacks (via ClassMethods#define_callbacks),
20
20
  # set the instance methods, procs, or callback objects to be called (via
21
- # +ClassMethods.set_callback+), and run the installed callbacks at the
21
+ # ClassMethods#set_callback), and run the installed callbacks at the
22
22
  # appropriate times (via +run_callbacks+).
23
23
  #
24
24
  # By default callbacks are halted by throwing +:abort+.
25
- # See +ClassMethods.define_callbacks+ for details.
25
+ # See ClassMethods#define_callbacks for details.
26
26
  #
27
27
  # Three kinds of callbacks are supported: before callbacks, run before a
28
28
  # certain event; after callbacks, run after the event; and around callbacks,
29
29
  # blocks that surround the event, triggering it when they yield. Callback code
30
30
  # can be contained in instance methods, procs or lambdas, or callback objects
31
- # that respond to certain predetermined methods. See +ClassMethods.set_callback+
31
+ # that respond to certain predetermined methods. See ClassMethods#set_callback
32
32
  # for details.
33
33
  #
34
34
  # class Record
@@ -600,7 +600,7 @@ module ActiveSupport
600
600
  end
601
601
  end
602
602
 
603
- class CallbackChain # :nodoc:#
603
+ class CallbackChain # :nodoc:
604
604
  include Enumerable
605
605
 
606
606
  attr_reader :name, :config
@@ -5,7 +5,7 @@ require "active_support/ordered_options"
5
5
 
6
6
  module ActiveSupport
7
7
  # Configurable provides a <tt>config</tt> method to store and retrieve
8
- # configuration options as an <tt>OrderedOptions</tt>.
8
+ # configuration options as an OrderedOptions.
9
9
  module Configurable
10
10
  extend ActiveSupport::Concern
11
11
 
@@ -127,7 +127,7 @@ module ActiveSupport
127
127
  private :config_accessor
128
128
  end
129
129
 
130
- # Reads and writes attributes from a configuration <tt>OrderedOptions</tt>.
130
+ # Reads and writes attributes from a configuration OrderedOptions.
131
131
  #
132
132
  # require "active_support/configurable"
133
133
  #
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/xml_mini"
4
3
  require "active_support/core_ext/hash/keys"
5
4
  require "active_support/core_ext/string/inflections"
6
5
  require "active_support/core_ext/object/to_param"
@@ -3,8 +3,8 @@
3
3
  require "active_support/array_inquirer"
4
4
 
5
5
  class Array
6
- # Wraps the array in an +ArrayInquirer+ object, which gives a friendlier way
7
- # to check its string-like contents.
6
+ # Wraps the array in an ActiveSupport::ArrayInquirer object, which gives a
7
+ # friendlier way to check its string-like contents.
8
8
  #
9
9
  # pets = [:cat, :dog].inquiry
10
10
  #
@@ -13,22 +13,22 @@ class Date
13
13
  class << self
14
14
  attr_accessor :beginning_of_week_default
15
15
 
16
- # Returns the week start (e.g. :monday) for the current request, if this has been set (via Date.beginning_of_week=).
16
+ # Returns the week start (e.g. +:monday+) for the current request, if this has been set (via Date.beginning_of_week=).
17
17
  # If <tt>Date.beginning_of_week</tt> has not been set for the current request, returns the week start specified in <tt>config.beginning_of_week</tt>.
18
- # If no config.beginning_of_week was specified, returns :monday.
18
+ # If no +config.beginning_of_week+ was specified, returns +:monday+.
19
19
  def beginning_of_week
20
20
  ::ActiveSupport::IsolatedExecutionState[:beginning_of_week] || beginning_of_week_default || :monday
21
21
  end
22
22
 
23
- # Sets <tt>Date.beginning_of_week</tt> to a week start (e.g. :monday) for current request/thread.
23
+ # Sets <tt>Date.beginning_of_week</tt> to a week start (e.g. +:monday+) for current request/thread.
24
24
  #
25
25
  # This method accepts any of the following day symbols:
26
- # :monday, :tuesday, :wednesday, :thursday, :friday, :saturday, :sunday
26
+ # +:monday+, +:tuesday+, +:wednesday+, +:thursday+, +:friday+, +:saturday+, +:sunday+
27
27
  def beginning_of_week=(week_start)
28
28
  ::ActiveSupport::IsolatedExecutionState[:beginning_of_week] = find_beginning_of_week!(week_start)
29
29
  end
30
30
 
31
- # Returns week start day symbol (e.g. :monday), or raises an +ArgumentError+ for invalid day symbol.
31
+ # Returns week start day symbol (e.g. +:monday+), or raises an +ArgumentError+ for invalid day symbol.
32
32
  def find_beginning_of_week!(week_start)
33
33
  raise ArgumentError, "Invalid beginning of week: #{week_start}" unless ::Date::DAYS_INTO_WEEK.key?(week_start)
34
34
  week_start
@@ -68,7 +68,7 @@ class Date
68
68
  silence_redefinition_of_method :to_time
69
69
 
70
70
  # Converts a Date instance to a Time, where the time is set to the beginning of the day.
71
- # The timezone can be either :local or :utc (default :local).
71
+ # The timezone can be either +:local+ or +:utc+ (default +:local+).
72
72
  #
73
73
  # date = Date.new(2007, 11, 10) # => Sat, 10 Nov 2007
74
74
  #
@@ -77,8 +77,8 @@ class Date
77
77
  #
78
78
  # date.to_time(:utc) # => 2007-11-10 00:00:00 UTC
79
79
  #
80
- # NOTE: The :local timezone is Ruby's *process* timezone, i.e. ENV['TZ'].
81
- # If the *application's* timezone is needed, then use +in_time_zone+ instead.
80
+ # NOTE: The +:local+ timezone is Ruby's *process* timezone, i.e. <tt>ENV['TZ']</tt>.
81
+ # If the <b>application's</b> timezone is needed, then use +in_time_zone+ instead.
82
82
  def to_time(form = :local)
83
83
  raise ArgumentError, "Expected :local or :utc, got #{form.inspect}." unless [:local, :utc].include?(form)
84
84
  ::Time.public_send(form, year, month, day)