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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +165 -2
- data/README.rdoc +1 -1
- data/lib/active_support/backtrace_cleaner.rb +0 -1
- data/lib/active_support/cache.rb +29 -28
- data/lib/active_support/cache/file_store.rb +7 -8
- data/lib/active_support/cache/mem_cache_store.rb +8 -8
- data/lib/active_support/cache/memory_store.rb +8 -7
- data/lib/active_support/cache/null_store.rb +3 -3
- data/lib/active_support/cache/redis_cache_store.rb +8 -8
- data/lib/active_support/cache/strategy/local_cache.rb +23 -23
- data/lib/active_support/callbacks.rb +0 -3
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +18 -0
- data/lib/active_support/concurrency/share_lock.rb +0 -1
- data/lib/active_support/core_ext/array/conversions.rb +5 -5
- data/lib/active_support/core_ext/date_and_time/calculations.rb +0 -30
- data/lib/active_support/core_ext/date_and_time/zones.rb +0 -1
- data/lib/active_support/core_ext/date_time/conversions.rb +0 -1
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/hash/conversions.rb +1 -1
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +2 -2
- data/lib/active_support/core_ext/module/delegation.rb +14 -1
- data/lib/active_support/core_ext/module/introspection.rb +1 -0
- data/lib/active_support/core_ext/object/duplicable.rb +7 -117
- data/lib/active_support/core_ext/object/try.rb +2 -0
- data/lib/active_support/core_ext/range/compare_range.rb +9 -3
- data/lib/active_support/core_ext/range/each.rb +0 -1
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +2 -2
- data/lib/active_support/core_ext/string/filters.rb +1 -1
- data/lib/active_support/core_ext/string/output_safety.rb +2 -1
- data/lib/active_support/core_ext/time/calculations.rb +30 -0
- data/lib/active_support/dependencies.rb +35 -6
- data/lib/active_support/dependencies/zeitwerk_integration.rb +22 -4
- data/lib/active_support/deprecation/method_wrappers.rb +12 -6
- data/lib/active_support/deprecation/proxy_wrappers.rb +28 -3
- data/lib/active_support/descendants_tracker.rb +0 -1
- data/lib/active_support/duration.rb +15 -13
- data/lib/active_support/duration/iso8601_parser.rb +0 -1
- data/lib/active_support/duration/iso8601_serializer.rb +0 -1
- data/lib/active_support/encrypted_file.rb +1 -1
- data/lib/active_support/evented_file_update_checker.rb +11 -2
- data/lib/active_support/file_update_checker.rb +0 -1
- data/lib/active_support/gem_version.rb +1 -1
- data/lib/active_support/i18n_railtie.rb +4 -0
- data/lib/active_support/inflector/inflections.rb +0 -1
- data/lib/active_support/inflector/methods.rb +1 -2
- data/lib/active_support/inflector/transliterate.rb +27 -1
- data/lib/active_support/json/decoding.rb +0 -1
- data/lib/active_support/lazy_load_hooks.rb +0 -1
- data/lib/active_support/locale/en.rb +4 -2
- data/lib/active_support/log_subscriber.rb +0 -1
- data/lib/active_support/logger.rb +1 -1
- data/lib/active_support/logger_thread_safe_level.rb +2 -1
- data/lib/active_support/message_encryptor.rb +1 -1
- data/lib/active_support/message_verifier.rb +2 -2
- data/lib/active_support/messages/metadata.rb +3 -2
- data/lib/active_support/messages/rotator.rb +4 -4
- data/lib/active_support/multibyte/chars.rb +1 -2
- data/lib/active_support/multibyte/unicode.rb +0 -1
- data/lib/active_support/notifications/fanout.rb +2 -2
- data/lib/active_support/notifications/instrumenter.rb +4 -4
- data/lib/active_support/number_helper.rb +4 -0
- data/lib/active_support/number_helper/number_converter.rb +4 -5
- data/lib/active_support/number_helper/number_to_currency_converter.rb +7 -8
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +0 -1
- data/lib/active_support/number_helper/number_to_human_converter.rb +0 -1
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +0 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +0 -1
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +0 -1
- data/lib/active_support/option_merger.rb +21 -3
- data/lib/active_support/ordered_hash.rb +1 -1
- data/lib/active_support/ordered_options.rb +5 -1
- data/lib/active_support/parameter_filter.rb +7 -3
- data/lib/active_support/string_inquirer.rb +0 -1
- data/lib/active_support/testing/parallelization.rb +16 -2
- data/lib/active_support/testing/stream.rb +0 -1
- data/lib/active_support/testing/time_helpers.rb +0 -2
- data/lib/active_support/xml_mini.rb +0 -1
- data/lib/active_support/xml_mini/jdom.rb +0 -1
- metadata +13 -9
@@ -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
|
5
|
-
# This includes the
|
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)
|
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
|
@@ -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
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
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
|
@@ -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
|
12
|
+
if self.begin.is_a?(TimeWithZone)
|
13
13
|
cover?(value)
|
14
|
-
elsif
|
14
|
+
elsif self.end.is_a?(TimeWithZone)
|
15
15
|
cover?(value)
|
16
16
|
else
|
17
17
|
super
|
@@ -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
|
330
|
-
Module
|
331
|
-
Exception.
|
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.
|
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
|
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
|
|