activesupport 7.0.4.3 → 7.0.7.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +77 -0
  3. data/README.rdoc +2 -2
  4. data/lib/active_support/cache/strategy/local_cache.rb +1 -1
  5. data/lib/active_support/core_ext/date/calculations.rb +15 -0
  6. data/lib/active_support/core_ext/date/deprecated_conversions.rb +12 -1
  7. data/lib/active_support/core_ext/date_time/calculations.rb +4 -0
  8. data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +12 -1
  9. data/lib/active_support/core_ext/enumerable.rb +25 -20
  10. data/lib/active_support/core_ext/hash/deep_transform_values.rb +3 -3
  11. data/lib/active_support/core_ext/hash/keys.rb +3 -3
  12. data/lib/active_support/core_ext/integer/inflections.rb +12 -12
  13. data/lib/active_support/core_ext/object/duplicable.rb +5 -5
  14. data/lib/active_support/core_ext/object/to_query.rb +0 -2
  15. data/lib/active_support/core_ext/object/with_options.rb +5 -5
  16. data/lib/active_support/core_ext/range/deprecated_conversions.rb +8 -1
  17. data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -2
  18. data/lib/active_support/core_ext/string/inflections.rb +0 -4
  19. data/lib/active_support/core_ext/time/calculations.rb +4 -0
  20. data/lib/active_support/core_ext/time/deprecated_conversions.rb +12 -1
  21. data/lib/active_support/core_ext/time/zones.rb +3 -4
  22. data/lib/active_support/deprecation/disallowed.rb +3 -3
  23. data/lib/active_support/encrypted_configuration.rb +33 -2
  24. data/lib/active_support/encrypted_file.rb +8 -9
  25. data/lib/active_support/evented_file_update_checker.rb +17 -2
  26. data/lib/active_support/gem_version.rb +2 -2
  27. data/lib/active_support/inflector/methods.rb +5 -7
  28. data/lib/active_support/lazy_load_hooks.rb +1 -1
  29. data/lib/active_support/notifications.rb +2 -2
  30. data/lib/active_support/number_helper.rb +4 -3
  31. data/lib/active_support/parameter_filter.rb +19 -15
  32. data/lib/active_support/testing/isolation.rb +28 -27
  33. data/lib/active_support/time_with_zone.rb +10 -3
  34. metadata +6 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: af711c41eae644a4fba03556039ec8d30337836525e57b896af3fa895bd5826f
4
- data.tar.gz: 7c4eb0e42e2aaa1ba161eedd7657cdd8a458adfb456ac3df242a72dceceecc5c
3
+ metadata.gz: 04536a88c7cef8a70a74892d515e186b52035d5173af41840637b2ed9bad4d47
4
+ data.tar.gz: 68814229938ebce3a9500a6dac0d5db7ad70ba1b9ff75bf784c1006a72f66fb3
5
5
  SHA512:
6
- metadata.gz: f255bc83f2f93d1743014853471a053798dbad3e8162551a0c0593eb5c5ea8abef362abf37de6c298985e9413c32b5ad02294a84dad063da8c150f8ce34d3051
7
- data.tar.gz: 39f1750b28dc755ead136f17a4b999b9d6e46a5bdf8b733ded897c6ec163f49b8651df20682b6568aa7bd8bf82c127aa5b00fc354ca80a82ba72c642caa25dd2
6
+ metadata.gz: 6817bb1e03d8ff97bcfbc6dd933e622a1bb8c220de50c30d435e9e53f7f2dbb26f4bfa289fc3da8384d13d5bf7528539eff53299d28e0da83ce96500e2385e10
7
+ data.tar.gz: 90a083d63440b72339b96cbd0aeade50b73907fc41157666fccf1b4bd02b86865972d98388f591c749f371c2d4a353c7e8d489cbefdc2f548a4da3030ace8b4e
data/CHANGELOG.md CHANGED
@@ -1,3 +1,67 @@
1
+ ## Rails 7.0.7.2 (August 22, 2023) ##
2
+
3
+ * No changes.
4
+
5
+
6
+ ## Rails 7.0.7.1 (August 22, 2023) ##
7
+
8
+ * Use a temporary file for storing unencrypted files while editing
9
+
10
+ [CVE-2023-38037]
11
+
12
+
13
+ ## Rails 7.0.7 (August 09, 2023) ##
14
+
15
+ * Fix `Cache::NullStore` with local caching for repeated reads.
16
+
17
+ *fatkodima*
18
+
19
+ * Fix `to_s` with no arguments not respecting custom `:default` formats
20
+
21
+ *Hartley McGuire*
22
+
23
+ * Fix `ActiveSupport::Inflector.humanize(nil)` raising ``NoMethodError: undefined method `end_with?' for nil:NilClass``.
24
+
25
+ *James Robinson*
26
+
27
+ * Fix `Enumerable#sum` for `Enumerator#lazy`.
28
+
29
+ *fatkodima*, *Matthew Draper*, *Jonathan Hefner*
30
+
31
+ * Improve error message when EventedFileUpdateChecker is used without a
32
+ compatible version of the Listen gem
33
+
34
+ *Hartley McGuire*
35
+
36
+
37
+ ## Rails 7.0.6 (June 29, 2023) ##
38
+
39
+ * Fix `EncryptedConfiguration` returning incorrect values for some `Hash`
40
+ methods
41
+
42
+ *Hartley McGuire*
43
+
44
+ * Fix arguments being destructed `Enumerable#many?` with block.
45
+
46
+ *Andrew Novoselac*
47
+
48
+ * Fix humanize for strings ending with id.
49
+
50
+ *fatkodima*
51
+
52
+
53
+ ## Rails 7.0.5.1 (June 26, 2023) ##
54
+
55
+ * No changes.
56
+
57
+
58
+ ## Rails 7.0.5 (May 24, 2023) ##
59
+
60
+ * Fixes TimeWithZone ArgumentError.
61
+
62
+ *Niklas Häusele*
63
+
64
+
1
65
  ## Rails 7.0.4.3 (March 13, 2023) ##
2
66
 
3
67
  * Implement SafeBuffer#bytesplice
@@ -19,6 +83,19 @@
19
83
 
20
84
  ## Rails 7.0.4 (September 09, 2022) ##
21
85
 
86
+ * Ensure `ActiveSupport::Testing::Isolation::Forking` closes pipes
87
+
88
+ Previously, `Forking.run_in_isolation` opened two ends of a pipe. The fork
89
+ process closed the read end, wrote to it, and then terminated (which
90
+ presumably closed the file descriptors on its end). The parent process
91
+ closed the write end, read from it, and returned, never closing the read
92
+ end.
93
+
94
+ This resulted in an accumulation of open file descriptors, which could
95
+ cause errors if the limit is reached.
96
+
97
+ *Sam Bostock*
98
+
22
99
  * Redis cache store is now compatible with redis-rb 5.0.
23
100
 
24
101
  *Jean Boussier*
data/README.rdoc CHANGED
@@ -13,7 +13,7 @@ The latest version of Active Support can be installed with RubyGems:
13
13
 
14
14
  $ gem install activesupport
15
15
 
16
- Source code can be downloaded as part of the Rails project on GitHub:
16
+ Source code can be downloaded as part of the \Rails project on GitHub:
17
17
 
18
18
  * https://github.com/rails/rails/tree/main/activesupport
19
19
 
@@ -31,7 +31,7 @@ API documentation is at:
31
31
 
32
32
  * https://api.rubyonrails.org
33
33
 
34
- Bug reports for the Ruby on Rails project can be filed here:
34
+ Bug reports for the Ruby on \Rails project can be filed here:
35
35
 
36
36
  * https://github.com/rails/rails/issues
37
37
 
@@ -124,7 +124,7 @@ module ActiveSupport
124
124
 
125
125
  local_entries = local_cache.read_multi_entries(keys)
126
126
  local_entries.transform_values! do |payload|
127
- deserialize_entry(payload).value
127
+ deserialize_entry(payload)&.value
128
128
  end
129
129
  missed_keys = keys - local_entries.keys
130
130
 
@@ -109,6 +109,21 @@ class Date
109
109
 
110
110
  # Provides precise Date calculations for years, months, and days. The +options+ parameter takes a hash with
111
111
  # any of these keys: <tt>:years</tt>, <tt>:months</tt>, <tt>:weeks</tt>, <tt>:days</tt>.
112
+ #
113
+ # The increments are applied in order of time units from largest to smallest.
114
+ # In other words, the date is incremented first by +:years+, then by
115
+ # +:months+, then by +:weeks+, then by +:days+. This order can affect the
116
+ # result around the end of a month. For example, incrementing first by months
117
+ # then by days:
118
+ #
119
+ # Date.new(2004, 9, 30).advance(months: 1, days: 1)
120
+ # # => Sun, 31 Oct 2004
121
+ #
122
+ # Whereas incrementing first by days then by months yields a different result:
123
+ #
124
+ # Date.new(2004, 9, 30).advance(days: 1).advance(months: 1)
125
+ # # => Mon, 01 Nov 2004
126
+ #
112
127
  def advance(options)
113
128
  d = self
114
129
 
@@ -15,7 +15,18 @@ class Date
15
15
  strftime(formatter)
16
16
  end
17
17
  elsif format == NOT_SET
18
- to_default_s
18
+ if formatter = DATE_FORMATS[:default]
19
+ ActiveSupport::Deprecation.warn(
20
+ "Using a :default format for Date#to_s is deprecated. Please use Date#to_fs instead."
21
+ )
22
+ if formatter.respond_to?(:call)
23
+ formatter.call(self).to_s
24
+ else
25
+ strftime(formatter)
26
+ end
27
+ else
28
+ to_default_s
29
+ end
19
30
  else
20
31
  ActiveSupport::Deprecation.warn(
21
32
  "Date#to_s(#{format.inspect}) is deprecated. Please use Date#to_fs(#{format.inspect}) instead."
@@ -75,6 +75,10 @@ class DateTime
75
75
  # The +options+ parameter takes a hash with any of these keys: <tt>:years</tt>,
76
76
  # <tt>:months</tt>, <tt>:weeks</tt>, <tt>:days</tt>, <tt>:hours</tt>,
77
77
  # <tt>:minutes</tt>, <tt>:seconds</tt>.
78
+ #
79
+ # Just like Date#advance, increments are applied in order of time units from
80
+ # largest to smallest. This order can affect the result around the end of a
81
+ # month.
78
82
  def advance(options)
79
83
  unless options[:weeks].nil?
80
84
  options[:weeks], partial_weeks = options[:weeks].divmod(1)
@@ -11,7 +11,18 @@ class DateTime
11
11
  )
12
12
  formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
13
13
  elsif format == NOT_SET
14
- to_default_s
14
+ if formatter = ::Time::DATE_FORMATS[:default]
15
+ ActiveSupport::Deprecation.warn(
16
+ "Using a :default format for DateTime#to_s is deprecated. Please use DateTime#to_fs instead."
17
+ )
18
+ if formatter.respond_to?(:call)
19
+ formatter.call(self).to_s
20
+ else
21
+ strftime(formatter)
22
+ end
23
+ else
24
+ to_default_s
25
+ end
15
26
  else
16
27
  ActiveSupport::Deprecation.warn(
17
28
  "DateTime#to_s(#{format.inspect}) is deprecated. Please use DateTime#to_fs(#{format.inspect}) instead."
@@ -55,12 +55,12 @@ module Enumerable
55
55
 
56
56
  # Calculates a sum from the elements.
57
57
  #
58
- # payments.sum { |p| p.price * p.tax_rate }
59
- # payments.sum(&:price)
58
+ # payments.sum { |p| p.price * p.tax_rate }
59
+ # payments.sum(&:price)
60
60
  #
61
61
  # The latter is a shortcut for:
62
62
  #
63
- # payments.inject(0) { |sum, p| sum + p.price }
63
+ # payments.inject(0) { |sum, p| sum + p.price }
64
64
  #
65
65
  # It can also calculate the sum without the use of a block.
66
66
  #
@@ -76,19 +76,24 @@ module Enumerable
76
76
  _original_sum_with_required_identity(identity, &block)
77
77
  elsif block_given?
78
78
  map(&block).sum
79
- # we check `first(1) == []` to check if we have an
80
- # empty Enumerable; checking `empty?` would return
81
- # true for `[nil]`, which we want to deprecate to
82
- # keep consistent with Ruby
83
- elsif first.is_a?(Numeric) || first(1) == []
84
- identity ||= 0
85
- _original_sum_with_required_identity(identity, &block)
86
79
  else
87
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
88
- Rails 7.0 has deprecated Enumerable.sum in favor of Ruby's native implementation available since 2.4.
89
- Sum of non-numeric elements requires an initial argument.
90
- MSG
91
- inject(:+) || 0
80
+ first = true
81
+
82
+ reduce(nil) do |sum, value|
83
+ if first
84
+ first = false
85
+
86
+ unless value.is_a?(Numeric) || value.respond_to?(:coerce)
87
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
88
+ Rails 7.0 has deprecated Enumerable.sum in favor of Ruby's native implementation available since 2.4.
89
+ Sum of non-numeric elements requires an initial argument.
90
+ MSG
91
+ end
92
+ value
93
+ else
94
+ sum + value
95
+ end
96
+ end || 0
92
97
  end
93
98
  end
94
99
 
@@ -144,8 +149,8 @@ module Enumerable
144
149
  def many?
145
150
  cnt = 0
146
151
  if block_given?
147
- any? do |element|
148
- cnt += 1 if yield element
152
+ any? do |*args|
153
+ cnt += 1 if yield(*args)
149
154
  cnt > 1
150
155
  end
151
156
  else
@@ -225,8 +230,8 @@ module Enumerable
225
230
  # [1, "", nil, 2, " ", [], {}, false, true].compact_blank
226
231
  # # => [1, 2, true]
227
232
  #
228
- # Set.new([nil, "", 1, 2])
229
- # # => [2, 1] (or [1, 2])
233
+ # Set.new([nil, "", 1, false]).compact_blank
234
+ # # => [1]
230
235
  #
231
236
  # When called on a +Hash+, returns a new +Hash+ without the blank values.
232
237
  #
@@ -245,7 +250,7 @@ module Enumerable
245
250
  # If the +series+ include keys that have no corresponding element in the Enumerable, these are ignored.
246
251
  # If the Enumerable has additional elements that aren't named in the +series+, these are not included in the result.
247
252
  def in_order_of(key, series)
248
- index_by(&key).values_at(*series).compact
253
+ group_by(&key).values_at(*series).flatten(1).compact
249
254
  end
250
255
 
251
256
  # Returns the sole item in the enumerable. If there are no items, or more
@@ -5,10 +5,10 @@ class Hash
5
5
  # This includes the values from the root hash and from all
6
6
  # nested hashes and arrays.
7
7
  #
8
- # hash = { person: { name: 'Rob', age: '28' } }
8
+ # hash = { person: { name: 'Rob', age: '28' } }
9
9
  #
10
- # hash.deep_transform_values{ |value| value.to_s.upcase }
11
- # # => {person: {name: "ROB", age: "28"}}
10
+ # hash.deep_transform_values{ |value| value.to_s.upcase }
11
+ # # => {person: {name: "ROB", age: "28"}}
12
12
  def deep_transform_values(&block)
13
13
  _deep_transform_values_in_object(self, &block)
14
14
  end
@@ -58,10 +58,10 @@ class Hash
58
58
  # This includes the keys from the root hash and from all
59
59
  # nested hashes and arrays.
60
60
  #
61
- # hash = { person: { name: 'Rob', age: '28' } }
61
+ # hash = { person: { name: 'Rob', age: '28' } }
62
62
  #
63
- # hash.deep_transform_keys{ |key| key.to_s.upcase }
64
- # # => {"PERSON"=>{"NAME"=>"Rob", "AGE"=>"28"}}
63
+ # hash.deep_transform_keys{ |key| key.to_s.upcase }
64
+ # # => {"PERSON"=>{"NAME"=>"Rob", "AGE"=>"28"}}
65
65
  def deep_transform_keys(&block)
66
66
  _deep_transform_keys_in_object(self, &block)
67
67
  end
@@ -6,12 +6,12 @@ class Integer
6
6
  # Ordinalize turns a number into an ordinal string used to denote the
7
7
  # position in an ordered sequence such as 1st, 2nd, 3rd, 4th.
8
8
  #
9
- # 1.ordinalize # => "1st"
10
- # 2.ordinalize # => "2nd"
11
- # 1002.ordinalize # => "1002nd"
12
- # 1003.ordinalize # => "1003rd"
13
- # -11.ordinalize # => "-11th"
14
- # -1001.ordinalize # => "-1001st"
9
+ # 1.ordinalize # => "1st"
10
+ # 2.ordinalize # => "2nd"
11
+ # 1002.ordinalize # => "1002nd"
12
+ # 1003.ordinalize # => "1003rd"
13
+ # -11.ordinalize # => "-11th"
14
+ # -1001.ordinalize # => "-1001st"
15
15
  def ordinalize
16
16
  ActiveSupport::Inflector.ordinalize(self)
17
17
  end
@@ -19,12 +19,12 @@ class Integer
19
19
  # Ordinal returns the suffix used to denote the position
20
20
  # in an ordered sequence such as 1st, 2nd, 3rd, 4th.
21
21
  #
22
- # 1.ordinal # => "st"
23
- # 2.ordinal # => "nd"
24
- # 1002.ordinal # => "nd"
25
- # 1003.ordinal # => "rd"
26
- # -11.ordinal # => "th"
27
- # -1001.ordinal # => "st"
22
+ # 1.ordinal # => "st"
23
+ # 2.ordinal # => "nd"
24
+ # 1002.ordinal # => "nd"
25
+ # 1003.ordinal # => "rd"
26
+ # -11.ordinal # => "th"
27
+ # -1001.ordinal # => "st"
28
28
  def ordinal
29
29
  ActiveSupport::Inflector.ordinal(self)
30
30
  end
@@ -31,8 +31,8 @@ end
31
31
  class Method
32
32
  # Methods are not duplicable:
33
33
  #
34
- # method(:puts).duplicable? # => false
35
- # method(:puts).dup # => TypeError: allocator undefined for Method
34
+ # method(:puts).duplicable? # => false
35
+ # method(:puts).dup # => TypeError: allocator undefined for Method
36
36
  def duplicable?
37
37
  false
38
38
  end
@@ -41,8 +41,8 @@ end
41
41
  class UnboundMethod
42
42
  # Unbound methods are not duplicable:
43
43
  #
44
- # method(:puts).unbind.duplicable? # => false
45
- # method(:puts).unbind.dup # => TypeError: allocator undefined for UnboundMethod
44
+ # method(:puts).unbind.duplicable? # => false
45
+ # method(:puts).unbind.dup # => TypeError: allocator undefined for UnboundMethod
46
46
  def duplicable?
47
47
  false
48
48
  end
@@ -53,7 +53,7 @@ require "singleton"
53
53
  module Singleton
54
54
  # Singleton instances are not duplicable:
55
55
  #
56
- # Class.new.include(Singleton).instance.dup # TypeError (can't dup instance of singleton
56
+ # Class.new.include(Singleton).instance.dup # TypeError (can't dup instance of singleton
57
57
  def duplicable?
58
58
  false
59
59
  end
@@ -72,8 +72,6 @@ class Hash
72
72
  #
73
73
  # The string pairs "key=value" that conform the query string
74
74
  # are sorted lexicographically in ascending order.
75
- #
76
- # This method is also aliased as +to_param+.
77
75
  def to_query(namespace = nil)
78
76
  query = filter_map do |key, value|
79
77
  unless (value.is_a?(Hash) || value.is_a?(Array)) && value.empty?
@@ -64,7 +64,7 @@ class Object
64
64
  #
65
65
  # Hence the inherited default for +if+ key is ignored.
66
66
  #
67
- # NOTE: You cannot call class methods implicitly inside of with_options.
67
+ # NOTE: You cannot call class methods implicitly inside of +with_options+.
68
68
  # You can access these methods using the class name instead:
69
69
  #
70
70
  # class Phone < ActiveRecord::Base
@@ -83,11 +83,11 @@ class Object
83
83
  # end
84
84
  # end
85
85
  #
86
- # # styled.link_to "I'm red", "/"
87
- # # #=> <a href="/" style="color: red;">I'm red</a>
86
+ # styled.link_to "I'm red", "/"
87
+ # # => <a href="/" style="color: red;">I'm red</a>
88
88
  #
89
- # # styled.button_tag "I'm red too!"
90
- # # #=> <button style="color: red;">I'm red too!</button>
89
+ # styled.button_tag "I'm red too!"
90
+ # # => <button style="color: red;">I'm red too!</button>
91
91
  #
92
92
  def with_options(options, &block)
93
93
  option_merger = ActiveSupport::OptionMerger.new(self, options)
@@ -10,7 +10,14 @@ module ActiveSupport
10
10
  )
11
11
  formatter.call(first, last)
12
12
  elsif format == NOT_SET
13
- super()
13
+ if formatter = RangeWithFormat::RANGE_FORMATS[:default]
14
+ ActiveSupport::Deprecation.warn(
15
+ "Using a :default format for Range#to_s is deprecated. Please use Range#to_fs instead."
16
+ )
17
+ formatter.call(first, last)
18
+ else
19
+ super()
20
+ end
14
21
  else
15
22
  ActiveSupport::Deprecation.warn(
16
23
  "Range#to_s(#{format.inspect}) is deprecated. Please use Range#to_fs(#{format.inspect}) instead."
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # frozen_string_literal: true
4
-
5
3
  ActiveSupport::Deprecation.warn(<<-MSG.squish)
6
4
  `active_support/core_ext/range/include_time_with_zone` is deprecated and will be removed in Rails 7.1.
7
5
  MSG
@@ -97,8 +97,6 @@ class String
97
97
  # 'active_record/errors'.camelize # => "ActiveRecord::Errors"
98
98
  # 'active_record/errors'.camelize(:lower) # => "activeRecord::Errors"
99
99
  #
100
- # +camelize+ is also aliased as +camelcase+.
101
- #
102
100
  # See ActiveSupport::Inflector.camelize.
103
101
  def camelize(first_letter = :upper)
104
102
  case first_letter
@@ -124,8 +122,6 @@ class String
124
122
  # 'x-men: the last stand'.titleize # => "X Men: The Last Stand"
125
123
  # 'string_ending_with_id'.titleize(keep_id_suffix: true) # => "String Ending With Id"
126
124
  #
127
- # +titleize+ is also aliased as +titlecase+.
128
- #
129
125
  # See ActiveSupport::Inflector.titleize.
130
126
  def titleize(keep_id_suffix: false)
131
127
  ActiveSupport::Inflector.titleize(self, keep_id_suffix: keep_id_suffix)
@@ -179,6 +179,10 @@ class Time
179
179
  # Time.new(2015, 8, 1, 14, 35, 0).advance(hours: 1) # => 2015-08-01 15:35:00 -0700
180
180
  # Time.new(2015, 8, 1, 14, 35, 0).advance(days: 1) # => 2015-08-02 14:35:00 -0700
181
181
  # Time.new(2015, 8, 1, 14, 35, 0).advance(weeks: 1) # => 2015-08-08 14:35:00 -0700
182
+ #
183
+ # Just like Date#advance, increments are applied in order of time units from
184
+ # largest to smallest. This order can affect the result around the end of a
185
+ # month.
182
186
  def advance(options)
183
187
  unless options[:weeks].nil?
184
188
  options[:weeks], partial_weeks = options[:weeks].divmod(1)
@@ -11,7 +11,18 @@ class Time
11
11
  )
12
12
  formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
13
13
  elsif format == NOT_SET
14
- to_default_s
14
+ if formatter = ::Time::DATE_FORMATS[:default]
15
+ ActiveSupport::Deprecation.warn(
16
+ "Using a :default format for Time#to_s is deprecated. Please use Time#to_fs instead."
17
+ )
18
+ if formatter.respond_to?(:call)
19
+ formatter.call(self).to_s
20
+ else
21
+ strftime(formatter)
22
+ end
23
+ else
24
+ to_default_s
25
+ end
15
26
  else
16
27
  ActiveSupport::Deprecation.warn(
17
28
  "Time#to_s(#{format.inspect}) is deprecated. Please use Time#to_fs(#{format.inspect}) instead."
@@ -49,10 +49,9 @@ class Time
49
49
  # around_action :set_time_zone
50
50
  #
51
51
  # private
52
- #
53
- # def set_time_zone
54
- # Time.use_zone(current_user.timezone) { yield }
55
- # end
52
+ # def set_time_zone
53
+ # Time.use_zone(current_user.timezone) { yield }
54
+ # end
56
55
  # end
57
56
  #
58
57
  # NOTE: This won't affect any ActiveSupport::TimeWithZone
@@ -5,15 +5,15 @@ module ActiveSupport
5
5
  module Disallowed
6
6
  # Sets the criteria used to identify deprecation messages which should be
7
7
  # disallowed. Can be an array containing strings, symbols, or regular
8
- # expressions. (Symbols are treated as strings). These are compared against
8
+ # expressions. (Symbols are treated as strings.) These are compared against
9
9
  # the text of the generated deprecation warning.
10
10
  #
11
11
  # Additionally the scalar symbol +:all+ may be used to treat all
12
12
  # deprecations as disallowed.
13
13
  #
14
14
  # Deprecations matching a substring or regular expression will be handled
15
- # using the configured +ActiveSupport::Deprecation.disallowed_behavior+
16
- # rather than +ActiveSupport::Deprecation.behavior+
15
+ # using the configured Behavior#disallowed_behavior rather than
16
+ # Behavior#behavior.
17
17
  attr_writer :disallowed_warnings
18
18
 
19
19
  # Returns the configured criteria used to identify deprecation messages
@@ -7,6 +7,28 @@ require "active_support/core_ext/object/inclusion"
7
7
  require "active_support/core_ext/module/delegation"
8
8
 
9
9
  module ActiveSupport
10
+ # Provides convenience methods on top of EncryptedFile to access values stored
11
+ # as encrypted YAML.
12
+ #
13
+ # Values can be accessed via +Hash+ methods, such as +fetch+ and +dig+, or via
14
+ # dynamic accessor methods, similar to OrderedOptions.
15
+ #
16
+ # my_config = ActiveSupport::EncryptedConfiguration.new(...)
17
+ # my_config.read # => "some_secret: 123\nsome_namespace:\n another_secret: 456"
18
+ #
19
+ # my_config[:some_secret]
20
+ # # => 123
21
+ # my_config.some_secret
22
+ # # => 123
23
+ # my_config.dig(:some_namespace, :another_secret)
24
+ # # => 456
25
+ # my_config.some_namespace.another_secret
26
+ # # => 456
27
+ # my_config.fetch(:foo)
28
+ # # => KeyError
29
+ # my_config.foo!
30
+ # # => KeyError
31
+ #
10
32
  class EncryptedConfiguration < EncryptedFile
11
33
  delegate :[], :fetch, to: :config
12
34
  delegate_missing_to :options
@@ -16,10 +38,11 @@ module ActiveSupport
16
38
  env_key: env_key, raise_if_missing_key: raise_if_missing_key
17
39
  end
18
40
 
19
- # Allow a config to be started without a file present
41
+ # Reads the file and returns the decrypted content. See EncryptedFile#read.
20
42
  def read
21
43
  super
22
44
  rescue ActiveSupport::EncryptedFile::MissingContentError
45
+ # Allow a config to be started without a file present
23
46
  ""
24
47
  end
25
48
 
@@ -29,6 +52,14 @@ module ActiveSupport
29
52
  super
30
53
  end
31
54
 
55
+ # Returns the decrypted content as a Hash with symbolized keys.
56
+ #
57
+ # my_config = ActiveSupport::EncryptedConfiguration.new(...)
58
+ # my_config.read # => "some_secret: 123\nsome_namespace:\n another_secret: 456"
59
+ #
60
+ # my_config.config
61
+ # # => { some_secret: 123, some_namespace: { another_secret: 789 } }
62
+ #
32
63
  def config
33
64
  @config ||= deserialize(read).deep_symbolize_keys
34
65
  end
@@ -45,7 +76,7 @@ module ActiveSupport
45
76
  end
46
77
 
47
78
  def options
48
- @options ||= ActiveSupport::InheritableOptions.new(deep_transform(config))
79
+ @options ||= deep_transform(config)
49
80
  end
50
81
 
51
82
  def deserialize(config)
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "pathname"
4
- require "tmpdir"
4
+ require "tempfile"
5
5
  require "active_support/message_encryptor"
6
6
 
7
7
  module ActiveSupport
@@ -81,17 +81,16 @@ module ActiveSupport
81
81
 
82
82
  private
83
83
  def writing(contents)
84
- tmp_file = "#{Process.pid}.#{content_path.basename.to_s.chomp('.enc')}"
85
- tmp_path = Pathname.new File.join(Dir.tmpdir, tmp_file)
86
- tmp_path.binwrite contents
84
+ Tempfile.create(["", "-" + content_path.basename.to_s.chomp(".enc")]) do |tmp_file|
85
+ tmp_path = Pathname.new(tmp_file)
86
+ tmp_path.binwrite contents
87
87
 
88
- yield tmp_path
88
+ yield tmp_path
89
89
 
90
- updated_contents = tmp_path.binread
90
+ updated_contents = tmp_path.binread
91
91
 
92
- write(updated_contents) if updated_contents != contents
93
- ensure
94
- FileUtils.rm(tmp_path) if tmp_path&.exist?
92
+ write(updated_contents) if updated_contents != contents
93
+ end
95
94
  end
96
95
 
97
96
 
@@ -1,9 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ gem "listen", "~> 3.5"
4
+ require "listen"
5
+
3
6
  require "set"
4
7
  require "pathname"
5
8
  require "concurrent/atomic/atomic_boolean"
6
- require "listen"
7
9
  require "active_support/fork_tracker"
8
10
 
9
11
  module ActiveSupport
@@ -43,6 +45,10 @@ module ActiveSupport
43
45
  ObjectSpace.define_finalizer(self, @core.finalizer)
44
46
  end
45
47
 
48
+ def inspect
49
+ "#<ActiveSupport::EventedFileUpdateChecker:#{object_id} @files=#{@core.files.to_a.inspect}"
50
+ end
51
+
46
52
  def updated?
47
53
  if @core.restart?
48
54
  @core.thread_safely(&:restart)
@@ -66,7 +72,7 @@ module ActiveSupport
66
72
  end
67
73
 
68
74
  class Core
69
- attr_reader :updated
75
+ attr_reader :updated, :files
70
76
 
71
77
  def initialize(files, dirs)
72
78
  @files = files.map { |file| Pathname(file).expand_path }.to_set
@@ -84,6 +90,10 @@ module ActiveSupport
84
90
  @mutex = Mutex.new
85
91
 
86
92
  start
93
+ # inotify / FSEvents file descriptors are inherited on fork, so
94
+ # we need to reopen them otherwise only the parent or the child
95
+ # will be notified.
96
+ # FIXME: this callback is keeping a reference on the instance
87
97
  @after_fork = ActiveSupport::ForkTracker.after_fork { start }
88
98
  end
89
99
 
@@ -105,6 +115,11 @@ module ActiveSupport
105
115
  @dtw, @missing = [*@dtw, *@missing].partition(&:exist?)
106
116
  @listener = @dtw.any? ? Listen.to(*@dtw, &method(:changed)) : nil
107
117
  @listener&.start
118
+
119
+ # Wait for the listener to be ready to avoid race conditions
120
+ # Unfortunately this isn't quite enough on macOS because the Darwin backend
121
+ # has an extra private thread we can't wait on.
122
+ @listener&.wait_for_state(:processing_events)
108
123
  end
109
124
 
110
125
  def stop
@@ -9,8 +9,8 @@ module ActiveSupport
9
9
  module VERSION
10
10
  MAJOR = 7
11
11
  MINOR = 0
12
- TINY = 4
13
- PRE = "3"
12
+ TINY = 7
13
+ PRE = "2"
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -136,7 +136,7 @@ module ActiveSupport
136
136
 
137
137
  result.tr!("_", " ")
138
138
  result.lstrip!
139
- unless keep_id_suffix
139
+ if !keep_id_suffix && lower_case_and_underscored_word&.end_with?("_id")
140
140
  result.delete_suffix!(" id")
141
141
  end
142
142
 
@@ -172,8 +172,6 @@ module ActiveSupport
172
172
  # optional parameter +keep_id_suffix+ to true.
173
173
  # By default, this parameter is false.
174
174
  #
175
- # +titleize+ is also aliased as +titlecase+.
176
- #
177
175
  # titleize('man from the boondocks') # => "Man From The Boondocks"
178
176
  # titleize('x-men: the last stand') # => "X Men: The Last Stand"
179
177
  # titleize('TheManWithoutAPast') # => "The Man Without A Past"
@@ -196,8 +194,8 @@ module ActiveSupport
196
194
  end
197
195
 
198
196
  # Creates a class name from a plural table name like Rails does for table
199
- # names to models. Note that this returns a string and not a Class (To
200
- # convert to an actual class follow +classify+ with #constantize).
197
+ # names to models. Note that this returns a string and not a Class. (To
198
+ # convert to an actual class follow +classify+ with #constantize.)
201
199
  #
202
200
  # classify('ham_and_eggs') # => "HamAndEgg"
203
201
  # classify('posts') # => "Post"
@@ -361,8 +359,8 @@ module ActiveSupport
361
359
  # If passed an optional +locale+ parameter, the uncountables will be
362
360
  # found for that locale.
363
361
  #
364
- # apply_inflections('post', inflections.plurals, :en) # => "posts"
365
- # apply_inflections('posts', inflections.singulars, :en) # => "post"
362
+ # apply_inflections('post', inflections.plurals, :en) # => "posts"
363
+ # apply_inflections('posts', inflections.singulars, :en) # => "post"
366
364
  def apply_inflections(word, rules, locale = :en)
367
365
  result = word.to_s.dup
368
366
 
@@ -66,7 +66,7 @@ module ActiveSupport
66
66
  # Executes all blocks registered to +name+ via on_load, using +base+ as the
67
67
  # evaluation context.
68
68
  #
69
- # ActiveSupport.run_load_hooks(:active_record, ActiveRecord::Base)
69
+ # ActiveSupport.run_load_hooks(:active_record, ActiveRecord::Base)
70
70
  #
71
71
  # In the case of the above example, it will execute all hooks registered
72
72
  # for +:active_record+ within the class +ActiveRecord::Base+.
@@ -237,8 +237,8 @@ module ActiveSupport
237
237
  #
238
238
  # Raises an error if invalid event name type is passed:
239
239
  #
240
- # ActiveSupport::Notifications.subscribe(:render) {|*args| ...}
241
- # #=> ArgumentError (pattern must be specified as a String, Regexp or empty)
240
+ # ActiveSupport::Notifications.subscribe(:render) {|*args| ...}
241
+ # #=> ArgumentError (pattern must be specified as a String, Regexp or empty)
242
242
  #
243
243
  def subscribe(pattern = nil, callback = nil, &block)
244
244
  notifier.subscribe(pattern, callback, monotonic: false, &block)
@@ -358,13 +358,14 @@ module ActiveSupport
358
358
  # out by default (set <tt>:strip_insignificant_zeros</tt> to
359
359
  # +false+ to change that):
360
360
  #
361
- # number_to_human(12.00001) # => "12"
362
- # number_to_human(12.00001, strip_insignificant_zeros: false) # => "12.0"
361
+ # number_to_human(12.00001) # => "12"
362
+ # number_to_human(12.00001, strip_insignificant_zeros: false) # => "12.0"
363
363
  #
364
364
  # ==== Custom Unit Quantifiers
365
365
  #
366
366
  # You can also use your own custom unit quantifiers:
367
- # number_to_human(500000, units: { unit: 'ml', thousand: 'lt' }) # => "500 lt"
367
+ #
368
+ # number_to_human(500000, units: { unit: 'ml', thousand: 'lt' }) # => "500 lt"
368
369
  #
369
370
  # If in your I18n locale you have:
370
371
  #
@@ -3,32 +3,36 @@
3
3
  require "active_support/core_ext/object/duplicable"
4
4
 
5
5
  module ActiveSupport
6
- # +ParameterFilter+ allows you to specify keys for sensitive data from
7
- # hash-like object and replace corresponding value. Filtering only certain
8
- # sub-keys from a hash is possible by using the dot notation:
9
- # 'credit_card.number'. If a proc is given, each key and value of a hash and
10
- # all sub-hashes are passed to it, where the value or the key can be replaced
11
- # using String#replace or similar methods.
6
+ # +ParameterFilter+ replaces values in a <tt>Hash</tt>-like object if their
7
+ # keys match one of the specified filters.
12
8
  #
9
+ # Matching based on nested keys is possible by using dot notation, e.g.
10
+ # <tt>"credit_card.number"</tt>.
11
+ #
12
+ # If a proc is given as a filter, each key and value of the <tt>Hash</tt>-like
13
+ # and of any nested <tt>Hash</tt>es will be passed to it. The value or key can
14
+ # then be mutated as desired using methods such as <tt>String#replace</tt>.
15
+ #
16
+ # # Replaces values with "[FILTERED]" for keys that match /password/i.
13
17
  # ActiveSupport::ParameterFilter.new([:password])
14
- # => replaces the value to all keys matching /password/i with "[FILTERED]"
15
18
  #
19
+ # # Replaces values with "[FILTERED]" for keys that match /foo|bar/i.
16
20
  # ActiveSupport::ParameterFilter.new([:foo, "bar"])
17
- # => replaces the value to all keys matching /foo|bar/i with "[FILTERED]"
18
21
  #
19
- # ActiveSupport::ParameterFilter.new([/\Apin\z/i, /\Apin_/i])
20
- # => replaces the value for the exact (case-insensitive) key 'pin' and all
21
- # (case-insensitive) keys beginning with 'pin_', with "[FILTERED]".
22
- # Does not match keys with 'pin' as a substring, such as 'shipping_id'.
22
+ # # Replaces values for the exact key "pin" and for keys that begin with
23
+ # # "pin_". Does not match keys that otherwise include "pin" as a
24
+ # # substring, such as "shipping_id".
25
+ # ActiveSupport::ParameterFilter.new([/\Apin\z/, /\Apin_/])
23
26
  #
27
+ # # Replaces the value for :code in `{ credit_card: { code: "xxxx" } }`.
28
+ # # Does not change `{ file: { code: "xxxx" } }`.
24
29
  # ActiveSupport::ParameterFilter.new(["credit_card.code"])
25
- # => replaces { credit_card: {code: "xxxx"} } with "[FILTERED]", does not
26
- # change { file: { code: "xxxx"} }
27
30
  #
31
+ # # Reverses values for keys that match /secret/i.
28
32
  # ActiveSupport::ParameterFilter.new([-> (k, v) do
29
33
  # v.reverse! if /secret/i.match?(k)
30
34
  # end])
31
- # => reverses the value to all keys matching /secret/i
35
+ #
32
36
  class ParameterFilter
33
37
  FILTERED = "[FILTERED]" # :nodoc:
34
38
 
@@ -25,38 +25,39 @@ module ActiveSupport
25
25
 
26
26
  module Forking
27
27
  def run_in_isolation(&blk)
28
- read, write = IO.pipe
29
- read.binmode
30
- write.binmode
28
+ IO.pipe do |read, write|
29
+ read.binmode
30
+ write.binmode
31
31
 
32
- pid = fork do
33
- read.close
34
- yield
35
- begin
36
- if error?
37
- failures.map! { |e|
38
- begin
39
- Marshal.dump e
40
- e
41
- rescue TypeError
42
- ex = Exception.new e.message
43
- ex.set_backtrace e.backtrace
44
- Minitest::UnexpectedError.new ex
45
- end
46
- }
32
+ pid = fork do
33
+ read.close
34
+ yield
35
+ begin
36
+ if error?
37
+ failures.map! { |e|
38
+ begin
39
+ Marshal.dump e
40
+ e
41
+ rescue TypeError
42
+ ex = Exception.new e.message
43
+ ex.set_backtrace e.backtrace
44
+ Minitest::UnexpectedError.new ex
45
+ end
46
+ }
47
+ end
48
+ test_result = defined?(Minitest::Result) ? Minitest::Result.from(self) : dup
49
+ result = Marshal.dump(test_result)
47
50
  end
48
- test_result = defined?(Minitest::Result) ? Minitest::Result.from(self) : dup
49
- result = Marshal.dump(test_result)
51
+
52
+ write.puts [result].pack("m")
53
+ exit!
50
54
  end
51
55
 
52
- write.puts [result].pack("m")
53
- exit!
56
+ write.close
57
+ result = read.read
58
+ Process.wait2(pid)
59
+ result.unpack1("m")
54
60
  end
55
-
56
- write.close
57
- result = read.read
58
- Process.wait2(pid)
59
- result.unpack1("m")
60
61
  end
61
62
  end
62
63
 
@@ -221,7 +221,14 @@ module ActiveSupport
221
221
  )
222
222
  formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
223
223
  elsif format == NOT_SET
224
- "#{time.strftime("%Y-%m-%d %H:%M:%S")} #{formatted_offset(false, 'UTC')}" # mimicking Ruby Time#to_s format
224
+ if formatter = ::Time::DATE_FORMATS[:default]
225
+ ActiveSupport::Deprecation.warn(
226
+ "Using a :default format for TimeWithZone#to_s is deprecated. Please use TimeWithZone#to_fs instead."
227
+ )
228
+ formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
229
+ else
230
+ "#{time.strftime("%Y-%m-%d %H:%M:%S")} #{formatted_offset(false, 'UTC')}" # mimicking Ruby Time#to_s format
231
+ end
225
232
  else
226
233
  ActiveSupport::Deprecation.warn(
227
234
  "TimeWithZone#to_s(#{format.inspect}) is deprecated. Please use TimeWithZone#to_fs(#{format.inspect}) instead."
@@ -566,8 +573,8 @@ module ActiveSupport
566
573
 
567
574
  # Send the missing method to +time+ instance, and wrap result in a new
568
575
  # TimeWithZone with the existing +time_zone+.
569
- def method_missing(sym, *args, &block)
570
- wrap_with_time_zone time.__send__(sym, *args, &block)
576
+ def method_missing(...)
577
+ wrap_with_time_zone time.__send__(...)
571
578
  rescue NoMethodError => e
572
579
  raise e, e.message.sub(time.inspect, inspect).sub("Time", "ActiveSupport::TimeWithZone"), e.backtrace
573
580
  end
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.4.3
4
+ version: 7.0.7.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-03-13 00:00:00.000000000 Z
11
+ date: 2023-08-22 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.4.3/activesupport/CHANGELOG.md
363
- documentation_uri: https://api.rubyonrails.org/v7.0.4.3/
362
+ changelog_uri: https://github.com/rails/rails/blob/v7.0.7.2/activesupport/CHANGELOG.md
363
+ documentation_uri: https://api.rubyonrails.org/v7.0.7.2/
364
364
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
365
- source_code_uri: https://github.com/rails/rails/tree/v7.0.4.3/activesupport
365
+ source_code_uri: https://github.com/rails/rails/tree/v7.0.7.2/activesupport
366
366
  rubygems_mfa_required: 'true'
367
367
  post_install_message:
368
368
  rdoc_options:
@@ -381,7 +381,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
381
381
  - !ruby/object:Gem::Version
382
382
  version: '0'
383
383
  requirements: []
384
- rubygems_version: 3.4.3
384
+ rubygems_version: 3.3.3
385
385
  signing_key:
386
386
  specification_version: 4
387
387
  summary: A toolkit of support libraries and Ruby core extensions extracted from the