activesupport 7.1.1 → 7.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ecb3bcd9549f6429e9a7b2e3e54bd529a71608135834c95ecad50ed60dd8935a
4
- data.tar.gz: 23c6ef54d1fbef9a19494322bae6ed4f4719d1a9f0b60e3f507dc1ccd4cf9adf
3
+ metadata.gz: 6db71966858e675d32617069b0df8dc17b1c5dfe8123c87ae96a28fdb6e2f5e6
4
+ data.tar.gz: 81ffe410567130147cd0c6f74943d40404a4031b2cf30f12bfaa2ee698cd5a57
5
5
  SHA512:
6
- metadata.gz: abdba26b48e19b8f107f9110e2934f315f8f4fcf87340309f4786faf0998903a21e791d362e106550439088016039c692e00c90b380b5b7602b497244ea30419
7
- data.tar.gz: 8f256ca213eea9aed13061094dca338c5886ba2bd3454036cd39649938399cc41ec74ff09ec28beabc21b9a57713c98e60125b13306e63a56aa908ad269b2316
6
+ metadata.gz: 99a9131ff9f97e739719621df9ba0a33d3b2fad9b1315397382235f29d33ee130f701d0c0ed767eacf01ccb31607eb26d7f5bb95f37ad86ac57f18817cd9b253
7
+ data.tar.gz: ffa6a0ffe90b88c87f65d85ddb32390d20f8c34ab2517f797c34d325839cbf434a0202650cdd54f118bee9a299cf478f83af4222c313f2746e267bbd19003914
data/CHANGELOG.md CHANGED
@@ -1,3 +1,70 @@
1
+ ## Rails 7.1.2 (November 10, 2023) ##
2
+
3
+ * Fix `:expires_in` option for `RedisCacheStore#write_multi`.
4
+
5
+ *fatkodima*
6
+
7
+ * Fix deserialization of non-string "purpose" field in Message serializer
8
+
9
+ *Jacopo Beschi*
10
+
11
+ * Prevent global cache options being overwritten when setting dynamic options
12
+ inside a `ActiveSupport::Cache::Store#fetch` block.
13
+
14
+ *Yasha Krasnou*
15
+
16
+ * Fix missing `require` resulting in `NoMethodError` when running
17
+ `bin/rails secrets:show` or `bin/rails secrets:edit`.
18
+
19
+ *Stephen Ierodiaconou*
20
+
21
+ * Ensure `{down,up}case_first` returns non-frozen string.
22
+
23
+ *Jonathan Hefner*
24
+
25
+ * Fix `#to_fs(:human_size)` to correctly work with negative numbers.
26
+
27
+ *Earlopain*
28
+
29
+ * Fix `BroadcastLogger#dup` so that it duplicates the logger's `broadcasts`.
30
+
31
+ *Andrew Novoselac*
32
+
33
+ * Fix issue where `bootstrap.rb` overwrites the `level` of a `BroadcastLogger`'s `broadcasts`.
34
+
35
+ *Andrew Novoselac*
36
+
37
+ * Fix `ActiveSupport::Cache` to handle outdated Marshal payload from Rails 6.1 format.
38
+
39
+ Active Support's Cache is supposed to treat a Marshal payload that can no longer be
40
+ deserialized as a cache miss. It fail to do so for compressed payload in the Rails 6.1
41
+ legacy format.
42
+
43
+ *Jean Boussier*
44
+
45
+ * Fix `OrderedOptions#dig` for array indexes.
46
+
47
+ *fatkodima*
48
+
49
+ * Fix time travel helpers to work when nested using with separate classes.
50
+
51
+ *fatkodima*
52
+
53
+ * Fix `delete_matched` for file cache store to work with keys longer than the
54
+ max filename size.
55
+
56
+ *fatkodima* and *Jonathan Hefner*
57
+
58
+ * Fix compatibility with the `semantic_logger` gem.
59
+
60
+ The `semantic_logger` gem doesn't behave exactly like stdlib logger in that
61
+ `SemanticLogger#level` returns a Symbol while stdlib `Logger#level` returns an Integer.
62
+
63
+ This caused the various `LogSubscriber` classes in Rails to break when assigned a
64
+ `SemanticLogger` instance.
65
+
66
+ *Jean Boussier*, *ojab*
67
+
1
68
  ## Rails 7.1.1 (October 11, 2023) ##
2
69
 
3
70
  * Add support for keyword arguments when delegating calls to custom loggers from `ActiveSupport::BroadcastLogger`.
@@ -218,6 +218,14 @@ module ActiveSupport
218
218
  dispatch { |logger| logger.fatal! }
219
219
  end
220
220
 
221
+ def initialize_copy(other)
222
+ @broadcasts = []
223
+ @progname = other.progname.dup
224
+ @formatter = other.formatter.dup
225
+
226
+ broadcast_to(*other.broadcasts.map(&:dup))
227
+ end
228
+
221
229
  private
222
230
  def dispatch(&block)
223
231
  @broadcasts.each { |logger| block.call(logger) }
@@ -121,7 +121,13 @@ module ActiveSupport
121
121
 
122
122
  private
123
123
  def uncompress(value)
124
- Marshal.load(Zlib::Inflate.inflate(value))
124
+ marshal_load(Zlib::Inflate.inflate(value))
125
+ end
126
+
127
+ def marshal_load(payload)
128
+ Marshal.load(payload)
129
+ rescue ArgumentError => error
130
+ raise Cache::DeserializationError, error.message
125
131
  end
126
132
  end
127
133
  end
@@ -176,7 +176,7 @@ module ActiveSupport
176
176
 
177
177
  # Translate a file path into a key.
178
178
  def file_path_key(path)
179
- fname = path[cache_path.to_s.size..-1].split(File::SEPARATOR, 4).last
179
+ fname = path[cache_path.to_s.size..-1].split(File::SEPARATOR, 4).last.delete(File::SEPARATOR)
180
180
  URI.decode_www_form_component(fname, Encoding::UTF_8)
181
181
  end
182
182
 
@@ -270,14 +270,22 @@ module ActiveSupport
270
270
  def read_multi_entries(names, **options)
271
271
  keys_to_names = names.index_by { |name| normalize_key(name, options) }
272
272
 
273
- raw_values = @data.with { |c| c.get_multi(keys_to_names.keys) }
273
+ raw_values = begin
274
+ @data.with { |c| c.get_multi(keys_to_names.keys) }
275
+ rescue Dalli::UnmarshalError
276
+ {}
277
+ end
278
+
274
279
  values = {}
275
280
 
276
281
  raw_values.each do |key, value|
277
282
  entry = deserialize_entry(value, raw: options[:raw])
278
283
 
279
284
  unless entry.nil? || entry.expired? || entry.mismatched?(normalize_version(keys_to_names[key], options))
280
- values[keys_to_names[key]] = entry.value
285
+ begin
286
+ values[keys_to_names[key]] = entry.value
287
+ rescue DeserializationError
288
+ end
281
289
  end
282
290
  end
283
291
 
@@ -332,7 +332,10 @@ module ActiveSupport
332
332
  if value
333
333
  entry = deserialize_entry(value, raw: raw)
334
334
  unless entry.nil? || entry.expired? || entry.mismatched?(normalize_version(name, options))
335
- results[name] = entry.value
335
+ begin
336
+ results[name] = entry.value
337
+ rescue DeserializationError
338
+ end
336
339
  end
337
340
  end
338
341
  end
@@ -383,7 +386,7 @@ module ActiveSupport
383
386
  end
384
387
 
385
388
  # Nonstandard store provider API to write multiple values at once.
386
- def write_multi_entries(entries, expires_in: nil, race_condition_ttl: nil, **options)
389
+ def write_multi_entries(entries, **options)
387
390
  return if entries.empty?
388
391
 
389
392
  failsafe :write_multi_entries do
@@ -459,7 +459,17 @@ module ActiveSupport
459
459
  instrument(:read, name, options) do |payload|
460
460
  cached_entry = read_entry(key, **options, event: payload)
461
461
  entry = handle_expired_entry(cached_entry, key, options)
462
- entry = nil if entry && entry.mismatched?(normalize_version(name, options))
462
+ if entry
463
+ if entry.mismatched?(normalize_version(name, options))
464
+ entry = nil
465
+ else
466
+ begin
467
+ entry.value
468
+ rescue DeserializationError
469
+ entry = nil
470
+ end
471
+ end
472
+ end
463
473
  payload[:super_operation] = :fetch if payload
464
474
  payload[:hit] = !!entry if payload
465
475
  end
@@ -511,7 +521,12 @@ module ActiveSupport
511
521
  nil
512
522
  else
513
523
  payload[:hit] = true if payload
514
- entry.value
524
+ begin
525
+ entry.value
526
+ rescue DeserializationError
527
+ payload[:hit] = false
528
+ nil
529
+ end
515
530
  end
516
531
  else
517
532
  payload[:hit] = false if payload
@@ -1038,6 +1053,8 @@ module ActiveSupport
1038
1053
  end
1039
1054
 
1040
1055
  def save_block_result_to_cache(name, options)
1056
+ options = options.dup
1057
+
1041
1058
  result = instrument(:generate, name, options) do
1042
1059
  yield(name, WriteOptions.new(options))
1043
1060
  end
@@ -52,7 +52,7 @@ class Date
52
52
  strftime(formatter)
53
53
  end
54
54
  else
55
- to_default_s
55
+ to_s
56
56
  end
57
57
  end
58
58
  alias_method :to_formatted_s, :to_fs
@@ -3,7 +3,7 @@
3
3
  require "active_support/concern"
4
4
 
5
5
  class Module
6
- # = Bite-sized separation of concerns
6
+ # == Bite-sized separation of concerns
7
7
  #
8
8
  # We often find ourselves with a medium-sized chunk of behavior that we'd
9
9
  # like to extract, but only mix in to a single class.
@@ -18,9 +18,9 @@ class Module
18
18
  # with a comment, as a least-bad alternative. Using modules in separate files
19
19
  # means tedious sifting to get a big-picture view.
20
20
  #
21
- # = Dissatisfying ways to separate small concerns
21
+ # == Dissatisfying ways to separate small concerns
22
22
  #
23
- # == Using comments:
23
+ # === Using comments:
24
24
  #
25
25
  # class Todo < ApplicationRecord
26
26
  # # Other todo implementation
@@ -37,7 +37,7 @@ class Module
37
37
  # end
38
38
  # end
39
39
  #
40
- # == With an inline module:
40
+ # === With an inline module:
41
41
  #
42
42
  # Noisy syntax.
43
43
  #
@@ -61,7 +61,7 @@ class Module
61
61
  # include EventTracking
62
62
  # end
63
63
  #
64
- # == Mix-in noise exiled to its own file:
64
+ # === Mix-in noise exiled to its own file:
65
65
  #
66
66
  # Once our chunk of behavior starts pushing the scroll-to-understand-it
67
67
  # boundary, we give in and move it to a separate file. At this size, the
@@ -75,7 +75,7 @@ class Module
75
75
  # include TodoEventTracking
76
76
  # end
77
77
  #
78
- # = Introducing Module#concerning
78
+ # == Introducing Module#concerning
79
79
  #
80
80
  # By quieting the mix-in noise, we arrive at a natural, low-ceremony way to
81
81
  # separate bite-sized concerns.
@@ -9,7 +9,7 @@ module ActiveSupport
9
9
  module VERSION
10
10
  MAJOR = 7
11
11
  MINOR = 1
12
- TINY = 1
12
+ TINY = 2
13
13
  PRE = nil
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
@@ -164,7 +164,7 @@ module ActiveSupport
164
164
  # upcase_first('w') # => "W"
165
165
  # upcase_first('') # => ""
166
166
  def upcase_first(string)
167
- string.length > 0 ? string[0].upcase.concat(string[1..-1]) : ""
167
+ string.length > 0 ? string[0].upcase.concat(string[1..-1]) : +""
168
168
  end
169
169
 
170
170
  # Converts the first character in the string to lowercase.
@@ -173,7 +173,7 @@ module ActiveSupport
173
173
  # downcase_first('I') # => "i"
174
174
  # downcase_first('') # => ""
175
175
  def downcase_first(string)
176
- string.length > 0 ? string[0].downcase.concat(string[1..-1]) : ""
176
+ string.length > 0 ? string[0].downcase.concat(string[1..-1]) : +""
177
177
  end
178
178
 
179
179
  # Capitalizes all the words and replaces some characters in the string to
@@ -86,6 +86,12 @@ module ActiveSupport
86
86
  mattr_accessor :colorize_logging, default: true
87
87
  class_attribute :log_levels, instance_accessor: false, default: {} # :nodoc:
88
88
 
89
+ LEVEL_CHECKS = {
90
+ debug: -> (logger) { !logger.debug? },
91
+ info: -> (logger) { !logger.info? },
92
+ error: -> (logger) { !logger.error? },
93
+ }
94
+
89
95
  class << self
90
96
  def logger
91
97
  @logger ||= if defined?(Rails) && Rails.respond_to?(:logger)
@@ -122,7 +128,7 @@ module ActiveSupport
122
128
  end
123
129
 
124
130
  def subscribe_log_level(method, level)
125
- self.log_levels = log_levels.merge(method => ::Logger.const_get(level.upcase))
131
+ self.log_levels = log_levels.merge(method => LEVEL_CHECKS.fetch(level))
126
132
  set_event_levels
127
133
  end
128
134
  end
@@ -137,7 +143,7 @@ module ActiveSupport
137
143
  end
138
144
 
139
145
  def silenced?(event)
140
- logger.nil? || logger.level > @event_levels.fetch(event, Float::INFINITY)
146
+ logger.nil? || @event_levels[event]&.call(logger)
141
147
  end
142
148
 
143
149
  def call(event)
@@ -82,7 +82,7 @@ module ActiveSupport
82
82
  throw :invalid_message_content, "expired"
83
83
  end
84
84
 
85
- if hash["pur"] != purpose&.to_s
85
+ if hash["pur"].to_s != purpose.to_s
86
86
  throw :invalid_message_content, "mismatched purpose"
87
87
  end
88
88
 
@@ -18,26 +18,30 @@ module ActiveSupport
18
18
  end
19
19
 
20
20
  module FanoutIteration # :nodoc:
21
- def iterate_guarding_exceptions(listeners)
22
- exceptions = nil
23
-
24
- listeners.each do |s|
25
- yield s
26
- rescue Exception => e
27
- exceptions ||= []
28
- exceptions << e
29
- end
21
+ private
22
+ def iterate_guarding_exceptions(collection)
23
+ exceptions = nil
30
24
 
31
- if exceptions
32
- if exceptions.size == 1
33
- raise exceptions.first
34
- else
35
- raise InstrumentationSubscriberError.new(exceptions), cause: exceptions.first
25
+ collection.each do |s|
26
+ yield s
27
+ rescue Exception => e
28
+ exceptions ||= []
29
+ exceptions << e
36
30
  end
37
- end
38
31
 
39
- listeners
40
- end
32
+ if exceptions
33
+ exceptions = exceptions.flat_map do |exception|
34
+ exception.is_a?(InstrumentationSubscriberError) ? exception.exceptions : [exception]
35
+ end
36
+ if exceptions.size == 1
37
+ raise exceptions.first
38
+ else
39
+ raise InstrumentationSubscriberError.new(exceptions), cause: exceptions.first
40
+ end
41
+ end
42
+
43
+ collection
44
+ end
41
45
  end
42
46
 
43
47
  # This is a default queue implementation that ships with Notifications.
@@ -225,6 +229,8 @@ module ActiveSupport
225
229
  # handle.finish
226
230
  # end
227
231
  class Handle
232
+ include FanoutIteration
233
+
228
234
  def initialize(notifier, name, id, payload) # :nodoc:
229
235
  @name = name
230
236
  @id = id
@@ -239,7 +245,7 @@ module ActiveSupport
239
245
  ensure_state! :initialized
240
246
  @state = :started
241
247
 
242
- @groups.each do |group|
248
+ iterate_guarding_exceptions(@groups) do |group|
243
249
  group.start(@name, @id, @payload)
244
250
  end
245
251
  end
@@ -252,7 +258,7 @@ module ActiveSupport
252
258
  ensure_state! :started
253
259
  @state = :finished
254
260
 
255
- @groups.each do |group|
261
+ iterate_guarding_exceptions(@groups) do |group|
256
262
  group.finish(name, id, payload)
257
263
  end
258
264
  end
@@ -43,13 +43,13 @@ module ActiveSupport
43
43
 
44
44
  def exponent
45
45
  max = STORAGE_UNITS.size - 1
46
- exp = (Math.log(number) / Math.log(base)).to_i
46
+ exp = (Math.log(number.abs) / Math.log(base)).to_i
47
47
  exp = max if exp > max # avoid overflow for the highest unit
48
48
  exp
49
49
  end
50
50
 
51
51
  def smaller_than_base?
52
- number.to_i < base
52
+ number.to_i.abs < base
53
53
  end
54
54
 
55
55
  def base
@@ -42,8 +42,8 @@ module ActiveSupport
42
42
  super(key.to_sym)
43
43
  end
44
44
 
45
- def dig(*keys)
46
- super(*keys.flatten.map(&:to_sym))
45
+ def dig(key, *identifiers)
46
+ super(key.to_sym, *identifiers)
47
47
  end
48
48
 
49
49
  def method_missing(name, *args)
@@ -17,6 +17,7 @@ module ActiveSupport
17
17
  SUPPRESSED_WARNINGS = Regexp.union(
18
18
  # TODO: remove if https://github.com/mikel/mail/pull/1557 or similar fix
19
19
  %r{/lib/mail/parsers/.*statement not reached},
20
+ %r{/lib/mail/parsers/.*assigned but unused variable - disp_type_s},
20
21
  %r{/lib/mail/parsers/.*assigned but unused variable - testEof}
21
22
  )
22
23
 
@@ -25,7 +25,7 @@ module ActiveSupport
25
25
  unstub_object(stub)
26
26
  end
27
27
 
28
- new_name = "__simple_stub__#{method_name}"
28
+ new_name = "__simple_stub__#{method_name}__#{object_id}"
29
29
 
30
30
  @stubs[object.object_id][method_name] = Stub.new(object, method_name, new_name)
31
31
 
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.1.1
4
+ version: 7.1.2
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: 2023-10-11 00:00:00.000000000 Z
11
+ date: 2023-11-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: i18n
@@ -446,10 +446,10 @@ licenses:
446
446
  - MIT
447
447
  metadata:
448
448
  bug_tracker_uri: https://github.com/rails/rails/issues
449
- changelog_uri: https://github.com/rails/rails/blob/v7.1.1/activesupport/CHANGELOG.md
450
- documentation_uri: https://api.rubyonrails.org/v7.1.1/
449
+ changelog_uri: https://github.com/rails/rails/blob/v7.1.2/activesupport/CHANGELOG.md
450
+ documentation_uri: https://api.rubyonrails.org/v7.1.2/
451
451
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
452
- source_code_uri: https://github.com/rails/rails/tree/v7.1.1/activesupport
452
+ source_code_uri: https://github.com/rails/rails/tree/v7.1.2/activesupport
453
453
  rubygems_mfa_required: 'true'
454
454
  post_install_message:
455
455
  rdoc_options: