activesupport 7.0.0.rc1 → 7.0.1

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: fc2a50831138a53abf91816c46a1ada54c6457c2a6be685e46c32fdacae8706d
4
- data.tar.gz: 805b7df2562018d4991b711eda5badd29778b262cf82467f2d18c57bd69f8d2c
3
+ metadata.gz: f715e893b36942a3dd53bfdff6e441c8f2ec5aca48afe3b52b7b0592fd390f73
4
+ data.tar.gz: 796c266dacba0ee5373285437c0deb231a17dfa4ac1f071324061253d5f4c3cd
5
5
  SHA512:
6
- metadata.gz: fc5e281a4b9549b92170e17056b0bb12911327b839d7af8d021ef8173e7432deceea44a1444a2c954f489ce534ea0bce527add775be03298d3d3f8224ba0e2af
7
- data.tar.gz: fa401cf383e3bb17d03ae007d972b8f3b15f5b4565c05af3ee48895e60154a8c58e010096bfc50eb11a658102d1afbbad0d80b90744424783614d9146780b46b
6
+ metadata.gz: 9567947d9506c123e68d78647f4912c4e21a957d014d0a7fca8cd37c72b06319f4c4849bb30a36205d5b0de73ef0837b97b86f5b43b68fa8b5fd6281c80fc7d3
7
+ data.tar.gz: 6da1c1833eedd6810577887eb28385c1a97ac61a7982ac7589a05717b73f42ae838f43228d54b0eb991bf7c9927935eb01ca8cc9f79772c572f1bae609ca9f12
data/CHANGELOG.md CHANGED
@@ -1,3 +1,36 @@
1
+ ## Rails 7.0.1 (January 06, 2022) ##
2
+
3
+ * Fix `Class#descendants` and `DescendantsTracker#descendants` compatibility with Ruby 3.1.
4
+
5
+ [The native `Class#descendants` was reverted prior to Ruby 3.1 release](https://bugs.ruby-lang.org/issues/14394#note-33),
6
+ but `Class#subclasses` was kept, breaking the feature detection.
7
+
8
+ *Jean Boussier*
9
+
10
+
11
+ ## Rails 7.0.0 (December 15, 2021) ##
12
+
13
+ * Fix `ActiveSupport::Duration.build` to support negative values.
14
+
15
+ The algorithm to collect the `parts` of the `ActiveSupport::Duration`
16
+ ignored the sign of the `value` and accumulated incorrect part values. This
17
+ impacted `ActiveSupport::Duration#sum` (which is dependent on `parts`) but
18
+ not `ActiveSupport::Duration#eql?` (which is dependent on `value`).
19
+
20
+ *Caleb Buxton*, *Braden Staudacher*
21
+
22
+
23
+ ## Rails 7.0.0.rc3 (December 14, 2021) ##
24
+
25
+ * No changes.
26
+
27
+
28
+ ## Rails 7.0.0.rc2 (December 14, 2021) ##
29
+
30
+ * No changes.
31
+
32
+ ## Rails 7.0.0.rc1 (December 06, 2021) ##
33
+
1
34
  * Deprecate passing a format to `#to_s` in favor of `#to_formatted_s` in `Array`, `Range`, `Date`, `DateTime`, `Time`,
2
35
  `BigDecimal`, `Float` and, `Integer`.
3
36
 
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2005-2021 David Heinemeier Hansson
1
+ Copyright (c) 2005-2022 David Heinemeier Hansson
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
@@ -3,24 +3,30 @@
3
3
  require "active_support/ruby_features"
4
4
 
5
5
  class Class
6
- # Returns an array with all classes that are < than its receiver.
7
- #
8
- # class C; end
9
- # C.descendants # => []
10
- #
11
- # class B < C; end
12
- # C.descendants # => [B]
13
- #
14
- # class A < B; end
15
- # C.descendants # => [B, A]
16
- #
17
- # class D < C; end
18
- # C.descendants # => [B, A, D]
19
- def descendants
20
- ObjectSpace.each_object(singleton_class).reject do |k|
21
- k.singleton_class? || k == self
6
+ if ActiveSupport::RubyFeatures::CLASS_SUBCLASSES
7
+ def descendants
8
+ subclasses.concat(subclasses.flat_map(&:descendants))
22
9
  end
23
- end unless ActiveSupport::RubyFeatures::CLASS_SUBCLASSES
10
+ else
11
+ # Returns an array with all classes that are < than its receiver.
12
+ #
13
+ # class C; end
14
+ # C.descendants # => []
15
+ #
16
+ # class B < C; end
17
+ # C.descendants # => [B]
18
+ #
19
+ # class A < B; end
20
+ # C.descendants # => [B, A]
21
+ #
22
+ # class D < C; end
23
+ # C.descendants # => [B, A, D]
24
+ def descendants
25
+ ObjectSpace.each_object(singleton_class).reject do |k|
26
+ k.singleton_class? || k == self
27
+ end
28
+ end
29
+ end
24
30
 
25
31
  # Returns an array with the direct children of +self+.
26
32
  #
@@ -27,7 +27,7 @@ class Date
27
27
  # date = Date.new(2007, 11, 10) # => Sat, 10 Nov 2007
28
28
  #
29
29
  # date.to_formatted_s(:db) # => "2007-11-10"
30
- # date.to_formatted_s(:db) # => "2007-11-10"
30
+ # date.to_fs(:db) # => "2007-11-10"
31
31
  #
32
32
  # date.to_formatted_s(:short) # => "10 Nov"
33
33
  # date.to_formatted_s(:number) # => "20071110"
@@ -15,7 +15,7 @@ class DateTime
15
15
  # datetime = DateTime.civil(2007, 12, 4, 0, 0, 0, 0) # => Tue, 04 Dec 2007 00:00:00 +0000
16
16
  #
17
17
  # datetime.to_formatted_s(:db) # => "2007-12-04 00:00:00"
18
- # datetime.to_formatted_s(:db) # => "2007-12-04 00:00:00"
18
+ # datetime.to_fs(:db) # => "2007-12-04 00:00:00"
19
19
  # datetime.to_formatted_s(:number) # => "20071204000000"
20
20
  # datetime.to_formatted_s(:short) # => "04 Dec 00:00"
21
21
  # datetime.to_formatted_s(:long) # => "December 04, 2007 00:00"
@@ -1,11 +1,35 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Object
4
- # A duck-type assistant method. For example, Active Support extends Date
5
- # to define an <tt>acts_like_date?</tt> method, and extends Time to define
6
- # <tt>acts_like_time?</tt>. As a result, we can do <tt>x.acts_like?(:time)</tt> and
7
- # <tt>x.acts_like?(:date)</tt> to do duck-type-safe comparisons, since classes that
8
- # we want to act like Time simply need to define an <tt>acts_like_time?</tt> method.
4
+ # Provides a way to check whether some class acts like some other class based on the existence of
5
+ # an appropriately-named marker method.
6
+ #
7
+ # A class that provides the same interface as <tt>SomeClass</tt> may define a marker method named
8
+ # <tt>acts_like_some_class?</tt> to signal its compatibility to callers of
9
+ # <tt>acts_like?(:some_class)</tt>.
10
+ #
11
+ # For example, Active Support extends <tt>Date</tt> to define an <tt>acts_like_date?</tt> method,
12
+ # and extends <tt>Time</tt> to define <tt>acts_like_time?</tt>. As a result, developers can call
13
+ # <tt>x.acts_like?(:time)</tt> and <tt>x.acts_like?(:date)</tt> to test duck-type compatibility,
14
+ # and classes that are able to act like <tt>Time</tt> can also define an <tt>acts_like_time?</tt>
15
+ # method to interoperate.
16
+ #
17
+ # Note that the marker method is only expected to exist. It isn't called, so its body or return
18
+ # value are irrelevant.
19
+ #
20
+ # ==== Example: A class that provides the same interface as <tt>String</tt>
21
+ #
22
+ # This class may define:
23
+ #
24
+ # class Stringish
25
+ # def acts_like_string?
26
+ # end
27
+ # end
28
+ #
29
+ # Then client code can query for duck-type-safeness this way:
30
+ #
31
+ # Stringish.new.acts_like?(:string) # => true
32
+ #
9
33
  def acts_like?(duck)
10
34
  case duck
11
35
  when :time
@@ -4,7 +4,7 @@ class Pathname
4
4
  # Returns the receiver if the named file exists otherwise returns +nil+.
5
5
  # <tt>pathname.existence</tt> is equivalent to
6
6
  #
7
- # pathname.exists? ? pathname : nil
7
+ # pathname.exist? ? pathname : nil
8
8
  #
9
9
  # For example, something like
10
10
  #
@@ -32,7 +32,7 @@ class Time
32
32
  # time = Time.now # => 2007-01-18 06:10:17 -06:00
33
33
  #
34
34
  # time.to_formatted_s(:time) # => "06:10"
35
- # time.to_formatted_s(:time) # => "06:10"
35
+ # time.to_fs(:time) # => "06:10"
36
36
  #
37
37
  # time.to_formatted_s(:db) # => "2007-01-18 06:10:17"
38
38
  # time.to_formatted_s(:number) # => "20070118061017"
@@ -40,7 +40,7 @@ module ActiveSupport
40
40
  end
41
41
 
42
42
  def []=(object, _present)
43
- @map[object_id] = object
43
+ @map[object.object_id] = object
44
44
  end
45
45
  end
46
46
  WeakSet.new
@@ -51,7 +51,6 @@ module ActiveSupport
51
51
  unless @clear_disabled
52
52
  @clear_disabled = true
53
53
  remove_method(:subclasses)
54
- remove_method(:descendants)
55
54
  @@excluded_descendants = nil
56
55
  end
57
56
  end
@@ -87,9 +86,7 @@ module ActiveSupport
87
86
  end
88
87
 
89
88
  def descendants
90
- descendants = super
91
- descendants.reject! { |d| @@excluded_descendants[d] }
92
- descendants
89
+ subclasses.concat(subclasses.flat_map(&:descendants))
93
90
  end
94
91
 
95
92
  def direct_descendants
@@ -191,13 +191,14 @@ module ActiveSupport
191
191
  end
192
192
 
193
193
  parts = {}
194
- remainder = value.round(9)
194
+ remainder_sign = value <=> 0
195
+ remainder = value.round(9).abs
195
196
  variable = false
196
197
 
197
198
  PARTS.each do |part|
198
199
  unless part == :seconds
199
200
  part_in_seconds = PARTS_IN_SECONDS[part]
200
- parts[part] = remainder.div(part_in_seconds)
201
+ parts[part] = remainder.div(part_in_seconds) * remainder_sign
201
202
  remainder %= part_in_seconds
202
203
 
203
204
  unless parts[part].zero?
@@ -206,7 +207,7 @@ module ActiveSupport
206
207
  end
207
208
  end unless value == 0
208
209
 
209
- parts[:seconds] = remainder
210
+ parts[:seconds] = remainder * remainder_sign
210
211
 
211
212
  new(value, parts, variable)
212
213
  end
@@ -9,8 +9,8 @@ module ActiveSupport
9
9
  module VERSION
10
10
  MAJOR = 7
11
11
  MINOR = 0
12
- TINY = 0
13
- PRE = "rc1"
12
+ TINY = 1
13
+ PRE = nil
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "openssl"
3
4
  require "base64"
4
5
  require "active_support/core_ext/object/blank"
5
6
  require "active_support/security_utils"
@@ -103,10 +104,13 @@ module ActiveSupport
103
104
 
104
105
  class InvalidSignature < StandardError; end
105
106
 
107
+ SEPARATOR = "--" # :nodoc:
108
+ SEPARATOR_LENGTH = SEPARATOR.length # :nodoc:
109
+
106
110
  def initialize(secret, digest: nil, serializer: nil)
107
111
  raise ArgumentError, "Secret should not be nil." unless secret
108
112
  @secret = secret
109
- @digest = digest || "SHA1"
113
+ @digest = digest&.to_s || "SHA1"
110
114
  @serializer = serializer || Marshal
111
115
  end
112
116
 
@@ -120,10 +124,8 @@ module ActiveSupport
120
124
  # tampered_message = signed_message.chop # editing the message invalidates the signature
121
125
  # verifier.valid_message?(tampered_message) # => false
122
126
  def valid_message?(signed_message)
123
- return if signed_message.nil? || !signed_message.valid_encoding? || signed_message.blank?
124
-
125
- data, digest = signed_message.split("--")
126
- data.present? && digest.present? && ActiveSupport::SecurityUtils.secure_compare(digest, generate_digest(data))
127
+ data, digest = get_data_and_digest_from(signed_message)
128
+ digest_matches_data?(digest, data)
127
129
  end
128
130
 
129
131
  # Decodes the signed message using the +MessageVerifier+'s secret.
@@ -148,9 +150,9 @@ module ActiveSupport
148
150
  # incompatible_message = "test--dad7b06c94abba8d46a15fafaef56c327665d5ff"
149
151
  # verifier.verified(incompatible_message) # => TypeError: incompatible marshal file format
150
152
  def verified(signed_message, purpose: nil, **)
151
- if valid_message?(signed_message)
153
+ data, digest = get_data_and_digest_from(signed_message)
154
+ if digest_matches_data?(digest, data)
152
155
  begin
153
- data = signed_message.split("--")[0]
154
156
  message = Messages::Metadata.verify(decode(data), purpose)
155
157
  @serializer.load(message) if message
156
158
  rescue ArgumentError => argument_error
@@ -185,7 +187,7 @@ module ActiveSupport
185
187
  # verifier.generate 'a private message' # => "BAhJIhRwcml2YXRlLW1lc3NhZ2UGOgZFVA==--e2d724331ebdee96a10fb99b089508d1c72bd772"
186
188
  def generate(value, expires_at: nil, expires_in: nil, purpose: nil)
187
189
  data = encode(Messages::Metadata.wrap(@serializer.dump(value), expires_at: expires_at, expires_in: expires_in, purpose: purpose))
188
- "#{data}--#{generate_digest(data)}"
190
+ "#{data}#{SEPARATOR}#{generate_digest(data)}"
189
191
  end
190
192
 
191
193
  private
@@ -198,8 +200,38 @@ module ActiveSupport
198
200
  end
199
201
 
200
202
  def generate_digest(data)
201
- require "openssl" unless defined?(OpenSSL)
202
- OpenSSL::HMAC.hexdigest(OpenSSL::Digest.const_get(@digest).new, @secret, data)
203
+ OpenSSL::HMAC.hexdigest(@digest, @secret, data)
204
+ end
205
+
206
+ def digest_length_in_hex
207
+ # In hexadecimal (AKA base16) it takes 4 bits to represent a character,
208
+ # hence we multiply the digest's length (in bytes) by 8 to get it in
209
+ # bits and divide by 4 to get its number of characters it hex. Well, 8
210
+ # divided by 4 is 2.
211
+ @digest_length_in_hex ||= OpenSSL::Digest.new(@digest).digest_length * 2
212
+ end
213
+
214
+ def separator_index_for(signed_message)
215
+ index = signed_message.length - digest_length_in_hex - SEPARATOR_LENGTH
216
+ return if index.negative? || signed_message[index, SEPARATOR_LENGTH] != SEPARATOR
217
+
218
+ index
219
+ end
220
+
221
+ def get_data_and_digest_from(signed_message)
222
+ return if signed_message.nil? || !signed_message.valid_encoding? || signed_message.empty?
223
+
224
+ separator_index = separator_index_for(signed_message)
225
+ return if separator_index.nil?
226
+
227
+ data = signed_message[0...separator_index]
228
+ digest = signed_message[separator_index + SEPARATOR_LENGTH..-1]
229
+
230
+ [data, digest]
231
+ end
232
+
233
+ def digest_matches_data?(digest, data)
234
+ data.present? && digest.present? && ActiveSupport::SecurityUtils.secure_compare(digest, generate_digest(data))
203
235
  end
204
236
  end
205
237
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #--
4
- # Copyright (c) 2005-2021 David Heinemeier Hansson
4
+ # Copyright (c) 2005-2022 David Heinemeier Hansson
5
5
  #
6
6
  # Permission is hereby granted, free of charge, to any person obtaining
7
7
  # a copy of this software and associated documentation files (the
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.0.rc1
4
+ version: 7.0.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: 2021-12-06 00:00:00.000000000 Z
11
+ date: 2022-01-06 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.0.rc1/activesupport/CHANGELOG.md
363
- documentation_uri: https://api.rubyonrails.org/v7.0.0.rc1/
362
+ changelog_uri: https://github.com/rails/rails/blob/v7.0.1/activesupport/CHANGELOG.md
363
+ documentation_uri: https://api.rubyonrails.org/v7.0.1/
364
364
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
365
- source_code_uri: https://github.com/rails/rails/tree/v7.0.0.rc1/activesupport
365
+ source_code_uri: https://github.com/rails/rails/tree/v7.0.1/activesupport
366
366
  rubygems_mfa_required: 'true'
367
367
  post_install_message:
368
368
  rdoc_options:
@@ -377,11 +377,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
377
377
  version: 2.7.0
378
378
  required_rubygems_version: !ruby/object:Gem::Requirement
379
379
  requirements:
380
- - - ">"
380
+ - - ">="
381
381
  - !ruby/object:Gem::Version
382
- version: 1.3.1
382
+ version: '0'
383
383
  requirements: []
384
- rubygems_version: 3.2.22
384
+ rubygems_version: 3.2.32
385
385
  signing_key:
386
386
  specification_version: 4
387
387
  summary: A toolkit of support libraries and Ruby core extensions extracted from the