activesupport 7.1.0.rc2 → 7.1.1

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: 5e7c1720f83cebc94a181cd94c65ea558ed9e10a4635545893dd5e1bf054f27a
4
- data.tar.gz: f61b99bf85b449f9b5262fd32388bf378e5ecd949e9f35da00569025d9c4edda
3
+ metadata.gz: ecb3bcd9549f6429e9a7b2e3e54bd529a71608135834c95ecad50ed60dd8935a
4
+ data.tar.gz: 23c6ef54d1fbef9a19494322bae6ed4f4719d1a9f0b60e3f507dc1ccd4cf9adf
5
5
  SHA512:
6
- metadata.gz: a363047116d2e984f879cbc39b674faa1deac4791ee325eb616aeb0b482c8c06ab134cabff46ddd6449fb768ff4ca2b06d5f7bf722eb7cb210d6f7c364d94980
7
- data.tar.gz: 47ca432654c35b2d8359c42d76e9dc517b8b797a5eac8efb74f5ae59fbcbbedef636a1c3df3891667bd2aefe0db7dd09ef1d1eab855438cef9c03d309f8f97e5
6
+ metadata.gz: abdba26b48e19b8f107f9110e2934f315f8f4fcf87340309f4786faf0998903a21e791d362e106550439088016039c692e00c90b380b5b7602b497244ea30419
7
+ data.tar.gz: 8f256ca213eea9aed13061094dca338c5886ba2bd3454036cd39649938399cc41ec74ff09ec28beabc21b9a57713c98e60125b13306e63a56aa908ad269b2316
data/CHANGELOG.md CHANGED
@@ -1,3 +1,29 @@
1
+ ## Rails 7.1.1 (October 11, 2023) ##
2
+
3
+ * Add support for keyword arguments when delegating calls to custom loggers from `ActiveSupport::BroadcastLogger`.
4
+
5
+ *Edouard Chin*
6
+
7
+ * `NumberHelper`: handle objects responding `to_d`.
8
+
9
+ *fatkodima*
10
+
11
+ * Fix RedisCacheStore to properly set the TTL when incrementing or decrementing.
12
+
13
+ This bug was only impacting Redis server older than 7.0.
14
+
15
+ *Thomas Countz*
16
+
17
+ * Fix MemoryStore to prevent race conditions when incrementing or decrementing.
18
+
19
+ *Pierre Jambet*
20
+
21
+
22
+ ## Rails 7.1.0 (October 05, 2023) ##
23
+
24
+ * No changes.
25
+
26
+
1
27
  ## Rails 7.1.0.rc2 (October 01, 2023) ##
2
28
 
3
29
  * Fix `AS::MessagePack` with `ENV["RAILS_MAX_THREADS"]`.
@@ -863,7 +889,7 @@
863
889
 
864
890
  *Trevor Turk*
865
891
 
866
- * `ActiveSupport::Cache:Store#fetch` now passes an options accessor to the block.
892
+ * `ActiveSupport::Cache::Store#fetch` now passes an options accessor to the block.
867
893
 
868
894
  It makes possible to override cache options:
869
895
 
@@ -51,6 +51,26 @@ module ActiveSupport
51
51
  #
52
52
  # broadcast = BroadcastLogger.new
53
53
  # broadcast.info("Hello world") # The log message will appear nowhere.
54
+ #
55
+ # If you are adding a custom logger with custom methods to the broadcast,
56
+ # the `BroadcastLogger` will proxy them and return the raw value, or an array
57
+ # of raw values, depending on how many loggers in the broadcasts responded to
58
+ # the method:
59
+ #
60
+ # class MyLogger < ::Logger
61
+ # def loggable?
62
+ # true
63
+ # end
64
+ # end
65
+ #
66
+ # logger = BroadcastLogger.new
67
+ # logger.loggable? # => A NoMethodError exception is raised because no loggers in the broadcasts could respond.
68
+ #
69
+ # logger.broadcast_to(MyLogger.new(STDOUT))
70
+ # logger.loggable? # => true
71
+ # logger.broadcast_to(MyLogger.new(STDOUT))
72
+ # puts logger.broadcasts # => [MyLogger, MyLogger]
73
+ # logger.loggable? # [true, true]
54
74
  class BroadcastLogger
55
75
  include ActiveSupport::LoggerSilence
56
76
 
@@ -203,16 +223,20 @@ module ActiveSupport
203
223
  @broadcasts.each { |logger| block.call(logger) }
204
224
  end
205
225
 
206
- def method_missing(name, *args)
226
+ def method_missing(name, *args, **kwargs, &block)
207
227
  loggers = @broadcasts.select { |logger| logger.respond_to?(name) }
208
228
 
209
229
  if loggers.none?
210
- super(name, *args)
230
+ super(name, *args, **kwargs, &block)
211
231
  elsif loggers.one?
212
- loggers.first.send(name, *args)
232
+ loggers.first.send(name, *args, **kwargs, &block)
213
233
  else
214
- loggers.map { |logger| logger.send(name, *args) }
234
+ loggers.map { |logger| logger.send(name, *args, **kwargs, &block) }
215
235
  end
216
236
  end
237
+
238
+ def respond_to_missing?(method, include_all)
239
+ @broadcasts.any? { |logger| logger.respond_to?(method, include_all) }
240
+ end
217
241
  end
218
242
  end
@@ -238,16 +238,18 @@ module ActiveSupport
238
238
  key = normalize_key(name, options)
239
239
  version = normalize_version(name, options)
240
240
 
241
- entry = read_entry(key, **options)
241
+ synchronize do
242
+ entry = read_entry(key, **options)
242
243
 
243
- if !entry || entry.expired? || entry.mismatched?(version)
244
- write(name, Integer(amount), options)
245
- amount
246
- else
247
- num = entry.value.to_i + amount
248
- entry = Entry.new(num, expires_at: entry.expires_at, version: entry.version)
249
- write_entry(key, entry)
250
- num
244
+ if !entry || entry.expired? || entry.mismatched?(version)
245
+ write(name, Integer(amount), options)
246
+ amount
247
+ else
248
+ num = entry.value.to_i + amount
249
+ entry = Entry.new(num, expires_at: entry.expires_at, version: entry.version)
250
+ write_entry(key, entry)
251
+ num
252
+ end
251
253
  end
252
254
  end
253
255
  end
@@ -438,18 +438,26 @@ module ActiveSupport
438
438
  redis.then do |c|
439
439
  c = c.node_for(key) if c.is_a?(Redis::Distributed)
440
440
 
441
- if options[:expires_in] && supports_expire_nx?
442
- c.pipelined do |pipeline|
443
- pipeline.incrby(key, amount)
444
- pipeline.call(:expire, key, options[:expires_in].to_i, "NX")
445
- end.first
441
+ expires_in = options[:expires_in]
442
+
443
+ if expires_in
444
+ if supports_expire_nx?
445
+ count, _ = c.pipelined do |pipeline|
446
+ pipeline.incrby(key, amount)
447
+ pipeline.call(:expire, key, expires_in.to_i, "NX")
448
+ end
449
+ else
450
+ count, ttl = c.pipelined do |pipeline|
451
+ pipeline.incrby(key, amount)
452
+ pipeline.ttl(key)
453
+ end
454
+ c.expire(key, expires_in.to_i) if ttl < 0
455
+ end
446
456
  else
447
457
  count = c.incrby(key, amount)
448
- if count != amount && options[:expires_in] && c.ttl(key) < 0
449
- c.expire(key, options[:expires_in].to_i)
450
- end
451
- count
452
458
  end
459
+
460
+ count
453
461
  end
454
462
  end
455
463
 
@@ -439,9 +439,9 @@ module ActiveSupport
439
439
  #
440
440
  # ==== Dynamic Options
441
441
  #
442
- # In some cases it may be necessary to to dynamically compute options based
443
- # on the cached value. For this purpose, a ActiveSupport::Cache::WriteOptions
444
- # instance is passed as a second argument to the block
442
+ # In some cases it may be necessary to dynamically compute options based
443
+ # on the cached value. To support this, an ActiveSupport::Cache::WriteOptions
444
+ # instance is passed as the second argument to the block. For example:
445
445
  #
446
446
  # cache.fetch("authentication-token:#{user.id}") do |key, options|
447
447
  # token = authenticate_to_service
@@ -449,12 +449,6 @@ module ActiveSupport
449
449
  # token
450
450
  # end
451
451
  #
452
- # Only some options can be set dynamically:
453
- #
454
- # - +:expires_in+
455
- # - +:expires_at+
456
- # - +:version+
457
- #
458
452
  def fetch(name, options = nil, &block)
459
453
  if block_given?
460
454
  options = merged_options(options)
@@ -29,7 +29,7 @@ require "active_support/core_ext/date/conversions"
29
29
  # It should be noted that when using ::JSON.{generate,dump} directly, ActiveSupport's encoder is
30
30
  # bypassed completely. This means that as_json won't be invoked and the JSON gem will simply
31
31
  # ignore any options it does not natively understand. This also means that ::JSON.{generate,dump}
32
- # should give exactly the same results with or without active support.
32
+ # should give exactly the same results with or without Active Support.
33
33
 
34
34
  module ActiveSupport
35
35
  module ToJsonWithActiveSupportEncoder # :nodoc:
@@ -60,8 +60,8 @@ module ActiveSupport
60
60
  # [+raise+] Raise ActiveSupport::DeprecationException.
61
61
  # [+stderr+] Log all deprecation warnings to <tt>$stderr</tt>.
62
62
  # [+log+] Log all deprecation warnings to +Rails.logger+.
63
- # [+notify+] Use +ActiveSupport::Notifications+ to notify +deprecation.rails+.
64
- # [+report+] Use +ActiveSupport::ErrorReporter+ to report deprecations.
63
+ # [+notify+] Use ActiveSupport::Notifications to notify +deprecation.rails+.
64
+ # [+report+] Use ActiveSupport::ErrorReporter to report deprecations.
65
65
  # [+silence+] Do nothing. On \Rails, set <tt>config.active_support.report_deprecations = false</tt> to disable all behaviors.
66
66
  #
67
67
  # Setting behaviors only affects deprecations that happen after boot time.
@@ -88,8 +88,8 @@ module ActiveSupport
88
88
  # [+raise+] Raise ActiveSupport::DeprecationException.
89
89
  # [+stderr+] Log all deprecation warnings to <tt>$stderr</tt>.
90
90
  # [+log+] Log all deprecation warnings to +Rails.logger+.
91
- # [+notify+] Use +ActiveSupport::Notifications+ to notify +deprecation.rails+.
92
- # [+report+] Use +ActiveSupport::ErrorReporter+ to report deprecations.
91
+ # [+notify+] Use ActiveSupport::Notifications to notify +deprecation.rails+.
92
+ # [+report+] Use ActiveSupport::ErrorReporter to report deprecations.
93
93
  # [+silence+] Do nothing.
94
94
  #
95
95
  # Setting behaviors only affects deprecations that happen after boot time.
@@ -9,8 +9,8 @@ module ActiveSupport
9
9
  module VERSION
10
10
  MAJOR = 7
11
11
  MINOR = 1
12
- TINY = 0
13
- PRE = "rc2"
12
+ TINY = 1
13
+ PRE = nil
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -130,6 +130,7 @@ module ActiveSupport
130
130
  # indicate whether old option sets are still in use or can be removed from
131
131
  # rotation.
132
132
 
133
+ ##
133
134
  private
134
135
  def build(salt, secret_generator:, secret_generator_options:, **options)
135
136
  secret_length = MessageEncryptor.key_len(*options[:cipher])
@@ -126,6 +126,7 @@ module ActiveSupport
126
126
  # indicate whether old option sets are still in use or can be removed from
127
127
  # rotation.
128
128
 
129
+ ##
129
130
  private
130
131
  def build(salt, secret_generator:, secret_generator_options:, **options)
131
132
  MessageVerifier.new(secret_generator.call(salt, **secret_generator_options), **options)
@@ -65,16 +65,16 @@ module ActiveSupport
65
65
  end
66
66
  end
67
67
 
68
- # Returns a "handle" for an event with the given +name+ and +payload+
68
+ # Returns a "handle" for an event with the given +name+ and +payload+.
69
69
  #
70
- # +#start+ and +#finish+ must each be called exactly once on the returned object.
70
+ # #start and #finish must each be called exactly once on the returned object.
71
71
  #
72
- # Where possible, it's best to use +#instrument+, which will record the
72
+ # Where possible, it's best to use #instrument, which will record the
73
73
  # start and finish of the event and correctly handle any exceptions.
74
74
  # +build_handle+ is a low-level API intended for cases where using
75
- # +#instrument+ isn't possible.
75
+ # +instrument+ isn't possible.
76
76
  #
77
- # See ActiveSupport::Notifications::Fanout::Handle
77
+ # See ActiveSupport::Notifications::Fanout::Handle.
78
78
  def build_handle(name, payload)
79
79
  @notifier.build_handle(name, @id, payload)
80
80
  end
@@ -146,21 +146,21 @@ module ActiveSupport
146
146
  @allocation_count_finish = now_allocations
147
147
  end
148
148
 
149
- # Returns the CPU time (in milliseconds) passed since the call to
150
- # +start!+ and the call to +finish!+
149
+ # Returns the CPU time (in milliseconds) passed between the call to
150
+ # #start! and the call to #finish!.
151
151
  def cpu_time
152
152
  @cpu_time_finish - @cpu_time_start
153
153
  end
154
154
 
155
- # Returns the idle time time (in milliseconds) passed since the call to
156
- # +start!+ and the call to +finish!+
155
+ # Returns the idle time time (in milliseconds) passed between the call to
156
+ # #start! and the call to #finish!.
157
157
  def idle_time
158
158
  diff = duration - cpu_time
159
159
  diff > 0.0 ? diff : 0.0
160
160
  end
161
161
 
162
- # Returns the number of allocations made since the call to +start!+ and
163
- # the call to +finish!+
162
+ # Returns the number of allocations made between the call to #start! and
163
+ # the call to #finish!.
164
164
  def allocations
165
165
  @allocation_count_finish - @allocation_count_start
166
166
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "bigdecimal"
4
+ require "bigdecimal/util"
3
5
  require "active_support/core_ext/big_decimal/conversions"
4
6
  require "active_support/core_ext/hash/keys"
5
7
  require "active_support/i18n"
@@ -128,7 +130,7 @@ module ActiveSupport
128
130
  def execute
129
131
  if !number
130
132
  nil
131
- elsif validate_float? && !valid_float?
133
+ elsif validate_float? && !valid_bigdecimal
132
134
  number
133
135
  else
134
136
  convert
@@ -173,8 +175,15 @@ module ActiveSupport
173
175
  key.split(".").reduce(DEFAULTS) { |defaults, k| defaults[k.to_sym] }
174
176
  end
175
177
 
176
- def valid_float?
177
- Float(number, exception: false)
178
+ def valid_bigdecimal
179
+ case number
180
+ when Float, Rational
181
+ number.to_d(0)
182
+ when String
183
+ BigDecimal(number, exception: false)
184
+ else
185
+ number.to_d rescue nil
186
+ end
178
187
  end
179
188
  end
180
189
  end
@@ -10,13 +10,13 @@ module ActiveSupport
10
10
  def convert
11
11
  format = options[:format]
12
12
 
13
- number_f = valid_float?
14
- if number_f
15
- if number_f.negative?
16
- number_f = number_f.abs
17
- format = options[:negative_format] if (number_f * 10**options[:precision]) >= 0.5
13
+ number_d = valid_bigdecimal
14
+ if number_d
15
+ if number_d.negative?
16
+ number_d = number_d.abs
17
+ format = options[:negative_format] if (number_d * 10**options[:precision]) >= 0.5
18
18
  end
19
- number_s = NumberToRoundedConverter.convert(number_f, options)
19
+ number_s = NumberToRoundedConverter.convert(number_d, options)
20
20
  else
21
21
  number_s = number.to_s.strip
22
22
  format = options[:negative_format] if number_s.sub!(/^-/, "")
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.0.rc2
4
+ version: 7.1.1
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-01 00:00:00.000000000 Z
11
+ date: 2023-10-11 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.0.rc2/activesupport/CHANGELOG.md
450
- documentation_uri: https://api.rubyonrails.org/v7.1.0.rc2/
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/
451
451
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
452
- source_code_uri: https://github.com/rails/rails/tree/v7.1.0.rc2/activesupport
452
+ source_code_uri: https://github.com/rails/rails/tree/v7.1.1/activesupport
453
453
  rubygems_mfa_required: 'true'
454
454
  post_install_message:
455
455
  rdoc_options:
@@ -464,9 +464,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
464
464
  version: 2.7.0
465
465
  required_rubygems_version: !ruby/object:Gem::Requirement
466
466
  requirements:
467
- - - ">"
467
+ - - ">="
468
468
  - !ruby/object:Gem::Version
469
- version: 1.3.1
469
+ version: '0'
470
470
  requirements: []
471
471
  rubygems_version: 3.4.18
472
472
  signing_key: