activesupport 6.0.0.rc1 → 6.0.3.rc1

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 (80) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +165 -2
  3. data/README.rdoc +1 -1
  4. data/lib/active_support/backtrace_cleaner.rb +0 -1
  5. data/lib/active_support/cache.rb +29 -28
  6. data/lib/active_support/cache/file_store.rb +7 -8
  7. data/lib/active_support/cache/mem_cache_store.rb +8 -8
  8. data/lib/active_support/cache/memory_store.rb +8 -7
  9. data/lib/active_support/cache/null_store.rb +3 -3
  10. data/lib/active_support/cache/redis_cache_store.rb +8 -8
  11. data/lib/active_support/cache/strategy/local_cache.rb +23 -23
  12. data/lib/active_support/callbacks.rb +0 -3
  13. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +18 -0
  14. data/lib/active_support/concurrency/share_lock.rb +0 -1
  15. data/lib/active_support/core_ext/array/conversions.rb +5 -5
  16. data/lib/active_support/core_ext/date_and_time/calculations.rb +0 -30
  17. data/lib/active_support/core_ext/date_and_time/zones.rb +0 -1
  18. data/lib/active_support/core_ext/date_time/conversions.rb +0 -1
  19. data/lib/active_support/core_ext/digest.rb +3 -0
  20. data/lib/active_support/core_ext/hash/conversions.rb +1 -1
  21. data/lib/active_support/core_ext/hash/deep_transform_values.rb +2 -2
  22. data/lib/active_support/core_ext/module/delegation.rb +14 -1
  23. data/lib/active_support/core_ext/module/introspection.rb +1 -0
  24. data/lib/active_support/core_ext/object/duplicable.rb +7 -117
  25. data/lib/active_support/core_ext/object/try.rb +2 -0
  26. data/lib/active_support/core_ext/range/compare_range.rb +9 -3
  27. data/lib/active_support/core_ext/range/each.rb +0 -1
  28. data/lib/active_support/core_ext/range/include_time_with_zone.rb +2 -2
  29. data/lib/active_support/core_ext/string/filters.rb +1 -1
  30. data/lib/active_support/core_ext/string/output_safety.rb +2 -1
  31. data/lib/active_support/core_ext/time/calculations.rb +30 -0
  32. data/lib/active_support/dependencies.rb +35 -6
  33. data/lib/active_support/dependencies/zeitwerk_integration.rb +22 -4
  34. data/lib/active_support/deprecation/method_wrappers.rb +12 -6
  35. data/lib/active_support/deprecation/proxy_wrappers.rb +28 -3
  36. data/lib/active_support/descendants_tracker.rb +0 -1
  37. data/lib/active_support/duration.rb +15 -13
  38. data/lib/active_support/duration/iso8601_parser.rb +0 -1
  39. data/lib/active_support/duration/iso8601_serializer.rb +0 -1
  40. data/lib/active_support/encrypted_file.rb +1 -1
  41. data/lib/active_support/evented_file_update_checker.rb +11 -2
  42. data/lib/active_support/file_update_checker.rb +0 -1
  43. data/lib/active_support/gem_version.rb +1 -1
  44. data/lib/active_support/i18n_railtie.rb +4 -0
  45. data/lib/active_support/inflector/inflections.rb +0 -1
  46. data/lib/active_support/inflector/methods.rb +1 -2
  47. data/lib/active_support/inflector/transliterate.rb +27 -1
  48. data/lib/active_support/json/decoding.rb +0 -1
  49. data/lib/active_support/lazy_load_hooks.rb +0 -1
  50. data/lib/active_support/locale/en.rb +4 -2
  51. data/lib/active_support/log_subscriber.rb +0 -1
  52. data/lib/active_support/logger.rb +1 -1
  53. data/lib/active_support/logger_thread_safe_level.rb +2 -1
  54. data/lib/active_support/message_encryptor.rb +1 -1
  55. data/lib/active_support/message_verifier.rb +2 -2
  56. data/lib/active_support/messages/metadata.rb +3 -2
  57. data/lib/active_support/messages/rotator.rb +4 -4
  58. data/lib/active_support/multibyte/chars.rb +1 -2
  59. data/lib/active_support/multibyte/unicode.rb +0 -1
  60. data/lib/active_support/notifications/fanout.rb +2 -2
  61. data/lib/active_support/notifications/instrumenter.rb +4 -4
  62. data/lib/active_support/number_helper.rb +4 -0
  63. data/lib/active_support/number_helper/number_converter.rb +4 -5
  64. data/lib/active_support/number_helper/number_to_currency_converter.rb +7 -8
  65. data/lib/active_support/number_helper/number_to_delimited_converter.rb +0 -1
  66. data/lib/active_support/number_helper/number_to_human_converter.rb +0 -1
  67. data/lib/active_support/number_helper/number_to_human_size_converter.rb +0 -1
  68. data/lib/active_support/number_helper/number_to_phone_converter.rb +0 -1
  69. data/lib/active_support/number_helper/number_to_rounded_converter.rb +0 -1
  70. data/lib/active_support/option_merger.rb +21 -3
  71. data/lib/active_support/ordered_hash.rb +1 -1
  72. data/lib/active_support/ordered_options.rb +5 -1
  73. data/lib/active_support/parameter_filter.rb +7 -3
  74. data/lib/active_support/string_inquirer.rb +0 -1
  75. data/lib/active_support/testing/parallelization.rb +16 -2
  76. data/lib/active_support/testing/stream.rb +0 -1
  77. data/lib/active_support/testing/time_helpers.rb +0 -2
  78. data/lib/active_support/xml_mini.rb +0 -1
  79. data/lib/active_support/xml_mini/jdom.rb +0 -1
  80. metadata +13 -9
@@ -29,7 +29,6 @@ module DateAndTime
29
29
  end
30
30
 
31
31
  private
32
-
33
32
  def time_with_zone(time, zone)
34
33
  if time
35
34
  ActiveSupport::TimeWithZone.new(time.utc? ? time : time.getutc, zone)
@@ -96,7 +96,6 @@ class DateTime
96
96
  end
97
97
 
98
98
  private
99
-
100
99
  def offset_in_seconds
101
100
  (offset * 86400).to_i
102
101
  end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/digest/uuid"
@@ -73,7 +73,7 @@ class Hash
73
73
  # configure your own builder with the <tt>:builder</tt> option. The method also accepts
74
74
  # options like <tt>:dasherize</tt> and friends, they are forwarded to the builder.
75
75
  def to_xml(options = {})
76
- require "active_support/builder" unless defined?(Builder)
76
+ require "active_support/builder" unless defined?(Builder::XmlMarkup)
77
77
 
78
78
  options = options.dup
79
79
  options[:indent] ||= 2
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Hash
4
- # Returns a new hash with all keys converted by the block operation.
5
- # This includes the keys from the root hash and from all
4
+ # Returns a new hash with all values converted by the block operation.
5
+ # This includes the values from the root hash and from all
6
6
  # nested hashes and arrays.
7
7
  #
8
8
  # hash = { person: { name: 'Rob', age: '28' } }
@@ -193,7 +193,13 @@ class Module
193
193
  method_names = methods.map do |method|
194
194
  # Attribute writer methods only accept one argument. Makes sure []=
195
195
  # methods still accept two arguments.
196
- definition = /[^\]]=$/.match?(method) ? "arg" : "*args, &block"
196
+ definition = if /[^\]]=$/.match?(method)
197
+ "arg"
198
+ elsif RUBY_VERSION >= "2.7"
199
+ "..."
200
+ else
201
+ "*args, &block"
202
+ end
197
203
 
198
204
  # The following generated method calls the target exactly once, storing
199
205
  # the returned value in a dummy variable.
@@ -275,6 +281,11 @@ class Module
275
281
  #
276
282
  # The delegated method must be public on the target, otherwise it will
277
283
  # raise +NoMethodError+.
284
+ #
285
+ # The <tt>marshal_dump</tt> and <tt>_dump</tt> methods are exempt from
286
+ # delegation due to possible interference when calling
287
+ # <tt>Marshal.dump(object)</tt>, should the delegation target method
288
+ # of <tt>object</tt> add or remove instance variables.
278
289
  def delegate_missing_to(target)
279
290
  target = target.to_s
280
291
  target = "self.#{target}" if DELEGATION_RESERVED_METHOD_NAMES.include?(target)
@@ -284,6 +295,7 @@ class Module
284
295
  # It may look like an oversight, but we deliberately do not pass
285
296
  # +include_private+, because they do not get delegated.
286
297
 
298
+ return false if name == :marshal_dump || name == :_dump
287
299
  #{target}.respond_to?(name) || super
288
300
  end
289
301
 
@@ -302,6 +314,7 @@ class Module
302
314
  end
303
315
  end
304
316
  end
317
+ ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
305
318
  RUBY
306
319
  end
307
320
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/core_ext/string/filters"
3
4
  require "active_support/inflector"
4
5
 
5
6
  class Module
@@ -28,96 +28,6 @@ class Object
28
28
  end
29
29
  end
30
30
 
31
- class NilClass
32
- begin
33
- nil.dup
34
- rescue TypeError
35
-
36
- # +nil+ is not duplicable:
37
- #
38
- # nil.duplicable? # => false
39
- # nil.dup # => TypeError: can't dup NilClass
40
- def duplicable?
41
- false
42
- end
43
- end
44
- end
45
-
46
- class FalseClass
47
- begin
48
- false.dup
49
- rescue TypeError
50
-
51
- # +false+ is not duplicable:
52
- #
53
- # false.duplicable? # => false
54
- # false.dup # => TypeError: can't dup FalseClass
55
- def duplicable?
56
- false
57
- end
58
- end
59
- end
60
-
61
- class TrueClass
62
- begin
63
- true.dup
64
- rescue TypeError
65
-
66
- # +true+ is not duplicable:
67
- #
68
- # true.duplicable? # => false
69
- # true.dup # => TypeError: can't dup TrueClass
70
- def duplicable?
71
- false
72
- end
73
- end
74
- end
75
-
76
- class Symbol
77
- begin
78
- :symbol.dup
79
-
80
- # Some symbols couldn't be duped in Ruby 2.4.0 only, due to a bug.
81
- # This feature check catches any regression.
82
- "symbol_from_string".to_sym.dup
83
- rescue TypeError
84
-
85
- # Symbols are not duplicable:
86
- #
87
- # :my_symbol.duplicable? # => false
88
- # :my_symbol.dup # => TypeError: can't dup Symbol
89
- def duplicable?
90
- false
91
- end
92
- end
93
- end
94
-
95
- class Numeric
96
- begin
97
- 1.dup
98
- rescue TypeError
99
-
100
- # Numbers are not duplicable:
101
- #
102
- # 3.duplicable? # => false
103
- # 3.dup # => TypeError: can't dup Integer
104
- def duplicable?
105
- false
106
- end
107
- end
108
- end
109
-
110
- require "bigdecimal"
111
- class BigDecimal
112
- # BigDecimals are duplicable:
113
- #
114
- # BigDecimal("1.2").duplicable? # => true
115
- # BigDecimal("1.2").dup # => #<BigDecimal:...,'0.12E1',18(18)>
116
- def duplicable?
117
- true
118
- end
119
- end
120
-
121
31
  class Method
122
32
  # Methods are not duplicable:
123
33
  #
@@ -128,32 +38,12 @@ class Method
128
38
  end
129
39
  end
130
40
 
131
- class Complex
132
- begin
133
- Complex(1).dup
134
- rescue TypeError
135
-
136
- # Complexes are not duplicable:
137
- #
138
- # Complex(1).duplicable? # => false
139
- # Complex(1).dup # => TypeError: can't copy Complex
140
- def duplicable?
141
- false
142
- end
143
- end
144
- end
145
-
146
- class Rational
147
- begin
148
- Rational(1).dup
149
- rescue TypeError
150
-
151
- # Rationals are not duplicable:
152
- #
153
- # Rational(1).duplicable? # => false
154
- # Rational(1).dup # => TypeError: can't copy Rational
155
- def duplicable?
156
- false
157
- end
41
+ class UnboundMethod
42
+ # Unbound methods are not duplicable:
43
+ #
44
+ # method(:puts).unbind.duplicable? # => false
45
+ # method(:puts).unbind.dup # => TypeError: allocator undefined for UnboundMethod
46
+ def duplicable?
47
+ false
158
48
  end
159
49
  end
@@ -15,6 +15,7 @@ module ActiveSupport
15
15
  public_send(method_name, *args, &b)
16
16
  end
17
17
  end
18
+ ruby2_keywords(:try) if respond_to?(:ruby2_keywords, true)
18
19
 
19
20
  def try!(method_name = nil, *args, &b)
20
21
  if method_name.nil? && block_given?
@@ -27,6 +28,7 @@ module ActiveSupport
27
28
  public_send(method_name, *args, &b)
28
29
  end
29
30
  end
31
+ ruby2_keywords(:try!) if respond_to?(:ruby2_keywords, true)
30
32
  end
31
33
  end
32
34
 
@@ -11,13 +11,15 @@ module ActiveSupport
11
11
  # The native Range#=== behavior is untouched.
12
12
  # ('a'..'f') === ('c') # => true
13
13
  # (5..9) === (11) # => false
14
+ #
15
+ # The given range must be fully bounded, with both start and end.
14
16
  def ===(value)
15
17
  if value.is_a?(::Range)
16
18
  # 1...10 includes 1..9 but it does not include 1..10.
17
19
  # 1..10 includes 1...11 but it does not include 1...12.
18
20
  operator = exclude_end? && !value.exclude_end? ? :< : :<=
19
21
  value_max = !exclude_end? && value.exclude_end? ? value.max : value.last
20
- super(value.first) && value_max.send(operator, last)
22
+ super(value.first) && (self.end.nil? || value_max.send(operator, last))
21
23
  else
22
24
  super
23
25
  end
@@ -32,13 +34,15 @@ module ActiveSupport
32
34
  # The native Range#include? behavior is untouched.
33
35
  # ('a'..'f').include?('c') # => true
34
36
  # (5..9).include?(11) # => false
37
+ #
38
+ # The given range must be fully bounded, with both start and end.
35
39
  def include?(value)
36
40
  if value.is_a?(::Range)
37
41
  # 1...10 includes 1..9 but it does not include 1..10.
38
42
  # 1..10 includes 1...11 but it does not include 1...12.
39
43
  operator = exclude_end? && !value.exclude_end? ? :< : :<=
40
44
  value_max = !exclude_end? && value.exclude_end? ? value.max : value.last
41
- super(value.first) && value_max.send(operator, last)
45
+ super(value.first) && (self.end.nil? || value_max.send(operator, last))
42
46
  else
43
47
  super
44
48
  end
@@ -53,13 +57,15 @@ module ActiveSupport
53
57
  # The native Range#cover? behavior is untouched.
54
58
  # ('a'..'f').cover?('c') # => true
55
59
  # (5..9).cover?(11) # => false
60
+ #
61
+ # The given range must be fully bounded, with both start and end.
56
62
  def cover?(value)
57
63
  if value.is_a?(::Range)
58
64
  # 1...10 covers 1..9 but it does not cover 1..10.
59
65
  # 1..10 covers 1...11 but it does not cover 1...12.
60
66
  operator = exclude_end? && !value.exclude_end? ? :< : :<=
61
67
  value_max = !exclude_end? && value.exclude_end? ? value.max : value.last
62
- super(value.first) && value_max.send(operator, last)
68
+ super(value.first) && (self.end.nil? || value_max.send(operator, last))
63
69
  else
64
70
  super
65
71
  end
@@ -15,7 +15,6 @@ module ActiveSupport
15
15
  end
16
16
 
17
17
  private
18
-
19
18
  def ensure_iteration_allowed
20
19
  raise TypeError, "can't iterate from #{first.class}" if first.is_a?(TimeWithZone)
21
20
  end
@@ -9,9 +9,9 @@ module ActiveSupport
9
9
  # (1.hour.ago..1.hour.from_now).include?(Time.current) # => true
10
10
  #
11
11
  def include?(value)
12
- if first.is_a?(TimeWithZone)
12
+ if self.begin.is_a?(TimeWithZone)
13
13
  cover?(value)
14
- elsif last.is_a?(TimeWithZone)
14
+ elsif self.end.is_a?(TimeWithZone)
15
15
  cover?(value)
16
16
  else
17
17
  super
@@ -75,7 +75,7 @@ class String
75
75
  length_with_room_for_omission
76
76
  end
77
77
 
78
- "#{self[0, stop]}#{omission}"
78
+ +"#{self[0, stop]}#{omission}"
79
79
  end
80
80
 
81
81
  # Truncates +text+ to at most <tt>bytesize</tt> bytes in length without
@@ -291,13 +291,14 @@ module ActiveSupport #:nodoc:
291
291
  end
292
292
 
293
293
  private
294
-
295
294
  def html_escape_interpolated_argument(arg)
296
295
  (!html_safe? || arg.html_safe?) ? arg : CGI.escapeHTML(arg.to_s)
297
296
  end
298
297
 
299
298
  def set_block_back_references(block, match_data)
300
299
  block.binding.eval("proc { |m| $~ = m }").call(match_data)
300
+ rescue ArgumentError
301
+ # Can't create binding from C level Proc
301
302
  end
302
303
  end
303
304
  end
@@ -311,4 +311,34 @@ class Time
311
311
  end
312
312
  alias_method :eql_without_coercion, :eql?
313
313
  alias_method :eql?, :eql_with_coercion
314
+
315
+ # Returns a new time the specified number of days ago.
316
+ def prev_day(days = 1)
317
+ advance(days: -days)
318
+ end
319
+
320
+ # Returns a new time the specified number of days in the future.
321
+ def next_day(days = 1)
322
+ advance(days: days)
323
+ end
324
+
325
+ # Returns a new time the specified number of months ago.
326
+ def prev_month(months = 1)
327
+ advance(months: -months)
328
+ end
329
+
330
+ # Returns a new time the specified number of months in the future.
331
+ def next_month(months = 1)
332
+ advance(months: months)
333
+ end
334
+
335
+ # Returns a new time the specified number of years ago.
336
+ def prev_year(years = 1)
337
+ advance(years: -years)
338
+ end
339
+
340
+ # Returns a new time the specified number of years in the future.
341
+ def next_year(years = 1)
342
+ advance(years: years)
343
+ end
314
344
  end
@@ -20,6 +20,9 @@ module ActiveSupport #:nodoc:
20
20
  module Dependencies #:nodoc:
21
21
  extend self
22
22
 
23
+ UNBOUND_METHOD_MODULE_NAME = Module.instance_method(:name)
24
+ private_constant :UNBOUND_METHOD_MODULE_NAME
25
+
23
26
  mattr_accessor :interlock, default: Interlock.new
24
27
 
25
28
  # :doc:
@@ -201,6 +204,11 @@ module ActiveSupport #:nodoc:
201
204
  end
202
205
  end
203
206
 
207
+ def self.include_into(base)
208
+ base.include(self)
209
+ append_features(base)
210
+ end
211
+
204
212
  def const_missing(const_name)
205
213
  from_mod = anonymous? ? guess_for_anonymous(const_name) : self
206
214
  Dependencies.load_missing_constant(from_mod, const_name)
@@ -230,6 +238,21 @@ module ActiveSupport #:nodoc:
230
238
  base.class_eval do
231
239
  define_method(:load, Kernel.instance_method(:load))
232
240
  private :load
241
+
242
+ define_method(:require, Kernel.instance_method(:require))
243
+ private :require
244
+ end
245
+ end
246
+
247
+ def self.include_into(base)
248
+ base.include(self)
249
+
250
+ if base.instance_method(:load).owner == base
251
+ base.remove_method(:load)
252
+ end
253
+
254
+ if base.instance_method(:require).owner == base
255
+ base.remove_method(:require)
233
256
  end
234
257
  end
235
258
 
@@ -290,7 +313,6 @@ module ActiveSupport #:nodoc:
290
313
  end
291
314
 
292
315
  private
293
-
294
316
  def load(file, wrap = false)
295
317
  result = false
296
318
  load_dependency(file) { result = super }
@@ -326,9 +348,9 @@ module ActiveSupport #:nodoc:
326
348
  end
327
349
 
328
350
  def hook!
329
- Object.class_eval { include Loadable }
330
- Module.class_eval { include ModuleConstMissing }
331
- Exception.class_eval { include Blamable }
351
+ Loadable.include_into(Object)
352
+ ModuleConstMissing.include_into(Module)
353
+ Exception.include(Blamable)
332
354
  end
333
355
 
334
356
  def unhook!
@@ -639,7 +661,7 @@ module ActiveSupport #:nodoc:
639
661
 
640
662
  # Determine if the given constant has been automatically loaded.
641
663
  def autoloaded?(desc)
642
- return false if desc.is_a?(Module) && desc.anonymous?
664
+ return false if desc.is_a?(Module) && real_mod_name(desc).nil?
643
665
  name = to_constant_name desc
644
666
  return false unless qualified_const_defined?(name)
645
667
  autoloaded_constants.include?(name)
@@ -695,7 +717,7 @@ module ActiveSupport #:nodoc:
695
717
  when String then desc.sub(/^::/, "")
696
718
  when Symbol then desc.to_s
697
719
  when Module
698
- desc.name ||
720
+ real_mod_name(desc) ||
699
721
  raise(ArgumentError, "Anonymous modules have no name to be referenced by")
700
722
  else raise TypeError, "Not a valid constant descriptor: #{desc.inspect}"
701
723
  end
@@ -769,6 +791,13 @@ module ActiveSupport #:nodoc:
769
791
  def log(message)
770
792
  logger.debug("autoloading: #{message}") if logger && verbose
771
793
  end
794
+
795
+ private
796
+ # Returns the original name of a class or module even if `name` has been
797
+ # overridden.
798
+ def real_mod_name(mod)
799
+ UNBOUND_METHOD_MODULE_NAME.bind(mod).call
800
+ end
772
801
  end
773
802
  end
774
803