activesupport 5.2.8.1 → 6.1.6.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.

Files changed (188) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +426 -424
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -3
  5. data/lib/active_support/actionable_error.rb +48 -0
  6. data/lib/active_support/array_inquirer.rb +4 -2
  7. data/lib/active_support/backtrace_cleaner.rb +29 -3
  8. data/lib/active_support/benchmarkable.rb +1 -1
  9. data/lib/active_support/cache/file_store.rb +34 -34
  10. data/lib/active_support/cache/mem_cache_store.rb +39 -24
  11. data/lib/active_support/cache/memory_store.rb +59 -33
  12. data/lib/active_support/cache/null_store.rb +8 -3
  13. data/lib/active_support/cache/redis_cache_store.rb +72 -45
  14. data/lib/active_support/cache/strategy/local_cache.rb +41 -26
  15. data/lib/active_support/cache.rb +148 -78
  16. data/lib/active_support/callbacks.rb +81 -64
  17. data/lib/active_support/concern.rb +70 -3
  18. data/lib/active_support/concurrency/share_lock.rb +0 -1
  19. data/lib/active_support/configurable.rb +10 -14
  20. data/lib/active_support/configuration_file.rb +51 -0
  21. data/lib/active_support/core_ext/array/access.rb +18 -6
  22. data/lib/active_support/core_ext/array/conversions.rb +5 -5
  23. data/lib/active_support/core_ext/array/extract.rb +21 -0
  24. data/lib/active_support/core_ext/array.rb +1 -1
  25. data/lib/active_support/core_ext/benchmark.rb +2 -2
  26. data/lib/active_support/core_ext/class/attribute.rb +32 -47
  27. data/lib/active_support/core_ext/class/subclasses.rb +17 -38
  28. data/lib/active_support/core_ext/date/calculations.rb +6 -5
  29. data/lib/active_support/core_ext/date/conversions.rb +2 -1
  30. data/lib/active_support/core_ext/date_and_time/calculations.rb +37 -47
  31. data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
  32. data/lib/active_support/core_ext/date_and_time/zones.rb +0 -1
  33. data/lib/active_support/core_ext/date_time/calculations.rb +1 -1
  34. data/lib/active_support/core_ext/date_time/conversions.rb +0 -1
  35. data/lib/active_support/core_ext/digest/uuid.rb +1 -0
  36. data/lib/active_support/core_ext/enumerable.rb +171 -75
  37. data/lib/active_support/core_ext/hash/conversions.rb +3 -3
  38. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  39. data/lib/active_support/core_ext/hash/except.rb +2 -2
  40. data/lib/active_support/core_ext/hash/keys.rb +1 -30
  41. data/lib/active_support/core_ext/hash/slice.rb +6 -27
  42. data/lib/active_support/core_ext/hash.rb +1 -2
  43. data/lib/active_support/core_ext/integer/multiple.rb +1 -1
  44. data/lib/active_support/core_ext/kernel.rb +0 -1
  45. data/lib/active_support/core_ext/load_error.rb +1 -1
  46. data/lib/active_support/core_ext/marshal.rb +2 -0
  47. data/lib/active_support/core_ext/module/attr_internal.rb +2 -2
  48. data/lib/active_support/core_ext/module/attribute_accessors.rb +30 -39
  49. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +17 -19
  50. data/lib/active_support/core_ext/module/concerning.rb +8 -2
  51. data/lib/active_support/core_ext/module/delegation.rb +76 -33
  52. data/lib/active_support/core_ext/module/introspection.rb +16 -15
  53. data/lib/active_support/core_ext/module/redefine_method.rb +8 -17
  54. data/lib/active_support/core_ext/module.rb +0 -1
  55. data/lib/active_support/core_ext/name_error.rb +29 -2
  56. data/lib/active_support/core_ext/numeric/conversions.rb +129 -129
  57. data/lib/active_support/core_ext/numeric.rb +0 -1
  58. data/lib/active_support/core_ext/object/blank.rb +1 -2
  59. data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
  60. data/lib/active_support/core_ext/object/duplicable.rb +7 -114
  61. data/lib/active_support/core_ext/object/json.rb +14 -2
  62. data/lib/active_support/core_ext/object/try.rb +17 -7
  63. data/lib/active_support/core_ext/object/with_options.rb +1 -1
  64. data/lib/active_support/core_ext/range/compare_range.rb +34 -13
  65. data/lib/active_support/core_ext/range/conversions.rb +31 -29
  66. data/lib/active_support/core_ext/range/each.rb +0 -1
  67. data/lib/active_support/core_ext/range/include_time_with_zone.rb +8 -3
  68. data/lib/active_support/core_ext/regexp.rb +8 -5
  69. data/lib/active_support/core_ext/securerandom.rb +23 -3
  70. data/lib/active_support/core_ext/string/access.rb +5 -16
  71. data/lib/active_support/core_ext/string/conversions.rb +1 -0
  72. data/lib/active_support/core_ext/string/filters.rb +42 -1
  73. data/lib/active_support/core_ext/string/inflections.rb +45 -6
  74. data/lib/active_support/core_ext/string/inquiry.rb +1 -0
  75. data/lib/active_support/core_ext/string/multibyte.rb +6 -5
  76. data/lib/active_support/core_ext/string/output_safety.rb +70 -13
  77. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -2
  78. data/lib/active_support/core_ext/string/strip.rb +3 -1
  79. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
  80. data/lib/active_support/core_ext/symbol.rb +3 -0
  81. data/lib/active_support/core_ext/time/calculations.rb +53 -3
  82. data/lib/active_support/core_ext/time/conversions.rb +2 -0
  83. data/lib/active_support/core_ext/uri.rb +6 -1
  84. data/lib/active_support/core_ext.rb +1 -1
  85. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  86. data/lib/active_support/current_attributes.rb +16 -2
  87. data/lib/active_support/dependencies/zeitwerk_integration.rb +120 -0
  88. data/lib/active_support/dependencies.rb +109 -34
  89. data/lib/active_support/deprecation/behaviors.rb +16 -3
  90. data/lib/active_support/deprecation/disallowed.rb +56 -0
  91. data/lib/active_support/deprecation/instance_delegator.rb +0 -1
  92. data/lib/active_support/deprecation/method_wrappers.rb +18 -23
  93. data/lib/active_support/deprecation/proxy_wrappers.rb +29 -6
  94. data/lib/active_support/deprecation/reporting.rb +50 -7
  95. data/lib/active_support/deprecation.rb +6 -1
  96. data/lib/active_support/descendants_tracker.rb +59 -9
  97. data/lib/active_support/digest.rb +2 -0
  98. data/lib/active_support/duration/iso8601_parser.rb +2 -4
  99. data/lib/active_support/duration/iso8601_serializer.rb +18 -14
  100. data/lib/active_support/duration.rb +82 -33
  101. data/lib/active_support/encrypted_configuration.rb +0 -4
  102. data/lib/active_support/encrypted_file.rb +22 -4
  103. data/lib/active_support/environment_inquirer.rb +20 -0
  104. data/lib/active_support/evented_file_update_checker.rb +82 -117
  105. data/lib/active_support/execution_wrapper.rb +2 -1
  106. data/lib/active_support/file_update_checker.rb +0 -1
  107. data/lib/active_support/fork_tracker.rb +64 -0
  108. data/lib/active_support/gem_version.rb +3 -3
  109. data/lib/active_support/hash_with_indifferent_access.rb +70 -42
  110. data/lib/active_support/i18n.rb +1 -0
  111. data/lib/active_support/i18n_railtie.rb +15 -8
  112. data/lib/active_support/inflector/inflections.rb +2 -7
  113. data/lib/active_support/inflector/methods.rb +49 -58
  114. data/lib/active_support/inflector/transliterate.rb +47 -18
  115. data/lib/active_support/json/decoding.rb +25 -26
  116. data/lib/active_support/json/encoding.rb +11 -3
  117. data/lib/active_support/key_generator.rb +1 -33
  118. data/lib/active_support/lazy_load_hooks.rb +5 -2
  119. data/lib/active_support/locale/en.rb +33 -0
  120. data/lib/active_support/locale/en.yml +7 -3
  121. data/lib/active_support/log_subscriber.rb +39 -9
  122. data/lib/active_support/logger.rb +2 -17
  123. data/lib/active_support/logger_silence.rb +11 -19
  124. data/lib/active_support/logger_thread_safe_level.rb +50 -6
  125. data/lib/active_support/message_encryptor.rb +8 -13
  126. data/lib/active_support/message_verifier.rb +10 -10
  127. data/lib/active_support/messages/metadata.rb +11 -2
  128. data/lib/active_support/messages/rotation_configuration.rb +2 -1
  129. data/lib/active_support/messages/rotator.rb +10 -9
  130. data/lib/active_support/multibyte/chars.rb +10 -68
  131. data/lib/active_support/multibyte/unicode.rb +15 -327
  132. data/lib/active_support/notifications/fanout.rb +116 -16
  133. data/lib/active_support/notifications/instrumenter.rb +71 -9
  134. data/lib/active_support/notifications.rb +72 -8
  135. data/lib/active_support/number_helper/number_converter.rb +5 -6
  136. data/lib/active_support/number_helper/number_to_currency_converter.rb +4 -9
  137. data/lib/active_support/number_helper/number_to_delimited_converter.rb +3 -2
  138. data/lib/active_support/number_helper/number_to_human_converter.rb +4 -3
  139. data/lib/active_support/number_helper/number_to_human_size_converter.rb +4 -3
  140. data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
  141. data/lib/active_support/number_helper/number_to_phone_converter.rb +2 -1
  142. data/lib/active_support/number_helper/number_to_rounded_converter.rb +12 -7
  143. data/lib/active_support/number_helper/rounding_helper.rb +12 -28
  144. data/lib/active_support/number_helper.rb +38 -12
  145. data/lib/active_support/option_merger.rb +22 -3
  146. data/lib/active_support/ordered_hash.rb +1 -1
  147. data/lib/active_support/ordered_options.rb +13 -3
  148. data/lib/active_support/parameter_filter.rb +133 -0
  149. data/lib/active_support/per_thread_registry.rb +2 -1
  150. data/lib/active_support/rails.rb +1 -10
  151. data/lib/active_support/railtie.rb +23 -1
  152. data/lib/active_support/reloader.rb +4 -5
  153. data/lib/active_support/rescuable.rb +4 -4
  154. data/lib/active_support/secure_compare_rotator.rb +51 -0
  155. data/lib/active_support/security_utils.rb +19 -12
  156. data/lib/active_support/string_inquirer.rb +4 -3
  157. data/lib/active_support/subscriber.rb +72 -28
  158. data/lib/active_support/tagged_logging.rb +42 -8
  159. data/lib/active_support/test_case.rb +91 -0
  160. data/lib/active_support/testing/assertions.rb +30 -9
  161. data/lib/active_support/testing/deprecation.rb +0 -1
  162. data/lib/active_support/testing/file_fixtures.rb +2 -0
  163. data/lib/active_support/testing/isolation.rb +2 -2
  164. data/lib/active_support/testing/method_call_assertions.rb +28 -1
  165. data/lib/active_support/testing/parallelization/server.rb +78 -0
  166. data/lib/active_support/testing/parallelization/worker.rb +100 -0
  167. data/lib/active_support/testing/parallelization.rb +51 -0
  168. data/lib/active_support/testing/stream.rb +1 -2
  169. data/lib/active_support/testing/time_helpers.rb +47 -12
  170. data/lib/active_support/time_with_zone.rb +81 -47
  171. data/lib/active_support/values/time_zone.rb +34 -17
  172. data/lib/active_support/xml_mini/jdom.rb +2 -3
  173. data/lib/active_support/xml_mini/libxml.rb +2 -2
  174. data/lib/active_support/xml_mini/libxmlsax.rb +4 -4
  175. data/lib/active_support/xml_mini/nokogiri.rb +2 -2
  176. data/lib/active_support/xml_mini/nokogirisax.rb +3 -3
  177. data/lib/active_support/xml_mini/rexml.rb +10 -3
  178. data/lib/active_support/xml_mini.rb +2 -10
  179. data/lib/active_support.rb +14 -1
  180. metadata +54 -27
  181. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -9
  182. data/lib/active_support/core_ext/hash/compact.rb +0 -29
  183. data/lib/active_support/core_ext/hash/transform_values.rb +0 -32
  184. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -13
  185. data/lib/active_support/core_ext/module/reachable.rb +0 -11
  186. data/lib/active_support/core_ext/numeric/inquiry.rb +0 -28
  187. data/lib/active_support/core_ext/range/include_range.rb +0 -3
  188. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -43,7 +43,7 @@ module ActiveSupport
43
43
  deprecation_horizon: deprecation_horizon)
44
44
  },
45
45
 
46
- silence: ->(message, callstack, deprecation_horizon, gem_name) {},
46
+ silence: ->(message, callstack, deprecation_horizon, gem_name) { },
47
47
  }
48
48
 
49
49
  # Behavior module allows to determine how to display deprecation messages.
@@ -51,7 +51,7 @@ module ActiveSupport
51
51
  # constant. Available behaviors are:
52
52
  #
53
53
  # [+raise+] Raise <tt>ActiveSupport::DeprecationException</tt>.
54
- # [+stderr+] Log all deprecation warnings to +$stderr+.
54
+ # [+stderr+] Log all deprecation warnings to <tt>$stderr</tt>.
55
55
  # [+log+] Log all deprecation warnings to +Rails.logger+.
56
56
  # [+notify+] Use +ActiveSupport::Notifications+ to notify +deprecation.rails+.
57
57
  # [+silence+] Do nothing.
@@ -67,13 +67,18 @@ module ActiveSupport
67
67
  @behavior ||= [DEFAULT_BEHAVIORS[:stderr]]
68
68
  end
69
69
 
70
+ # Returns the current behavior for disallowed deprecations or if one isn't set, defaults to +:raise+.
71
+ def disallowed_behavior
72
+ @disallowed_behavior ||= [DEFAULT_BEHAVIORS[:raise]]
73
+ end
74
+
70
75
  # Sets the behavior to the specified value. Can be a single value, array,
71
76
  # or an object that responds to +call+.
72
77
  #
73
78
  # Available behaviors:
74
79
  #
75
80
  # [+raise+] Raise <tt>ActiveSupport::DeprecationException</tt>.
76
- # [+stderr+] Log all deprecation warnings to +$stderr+.
81
+ # [+stderr+] Log all deprecation warnings to <tt>$stderr</tt>.
77
82
  # [+log+] Log all deprecation warnings to +Rails.logger+.
78
83
  # [+notify+] Use +ActiveSupport::Notifications+ to notify +deprecation.rails+.
79
84
  # [+silence+] Do nothing.
@@ -92,6 +97,14 @@ module ActiveSupport
92
97
  @behavior = Array(behavior).map { |b| DEFAULT_BEHAVIORS[b] || arity_coerce(b) }
93
98
  end
94
99
 
100
+ # Sets the behavior for disallowed deprecations (those configured by
101
+ # ActiveSupport::Deprecation.disallowed_warnings=) to the specified
102
+ # value. As with +behavior=+, this can be a single value, array, or an
103
+ # object that responds to +call+.
104
+ def disallowed_behavior=(behavior)
105
+ @disallowed_behavior = Array(behavior).map { |b| DEFAULT_BEHAVIORS[b] || arity_coerce(b) }
106
+ end
107
+
95
108
  private
96
109
  def arity_coerce(behavior)
97
110
  unless behavior.respond_to?(:call)
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ class Deprecation
5
+ module Disallowed
6
+ # Sets the criteria used to identify deprecation messages which should be
7
+ # disallowed. Can be an array containing strings, symbols, or regular
8
+ # expressions. (Symbols are treated as strings). These are compared against
9
+ # the text of the generated deprecation warning.
10
+ #
11
+ # Additionally the scalar symbol +:all+ may be used to treat all
12
+ # deprecations as disallowed.
13
+ #
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+
17
+ attr_writer :disallowed_warnings
18
+
19
+ # Returns the configured criteria used to identify deprecation messages
20
+ # which should be treated as disallowed.
21
+ def disallowed_warnings
22
+ @disallowed_warnings ||= []
23
+ end
24
+
25
+ private
26
+ def deprecation_disallowed?(message)
27
+ disallowed = ActiveSupport::Deprecation.disallowed_warnings
28
+ return false if explicitly_allowed?(message)
29
+ return true if disallowed == :all
30
+ disallowed.any? do |rule|
31
+ case rule
32
+ when String, Symbol
33
+ message.include?(rule.to_s)
34
+ when Regexp
35
+ rule.match?(message)
36
+ end
37
+ end
38
+ end
39
+
40
+ def explicitly_allowed?(message)
41
+ allowances = @explicitly_allowed_warnings.value
42
+ return false unless allowances
43
+ return true if allowances == :all
44
+ allowances = [allowances] unless allowances.kind_of?(Array)
45
+ allowances.any? do |rule|
46
+ case rule
47
+ when String, Symbol
48
+ message.include?(rule.to_s)
49
+ when Regexp
50
+ rule.match?(message)
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/kernel/singleton_class"
4
3
  require "active_support/core_ext/module/delegation"
5
4
 
6
5
  module ActiveSupport
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/module/aliasing"
4
3
  require "active_support/core_ext/array/extract_options"
4
+ require "active_support/core_ext/module/redefine_method"
5
5
 
6
6
  module ActiveSupport
7
7
  class Deprecation
@@ -53,37 +53,32 @@ module ActiveSupport
53
53
  options = method_names.extract_options!
54
54
  deprecator = options.delete(:deprecator) || self
55
55
  method_names += options.keys
56
- mod = Module.new
56
+ mod = nil
57
57
 
58
58
  method_names.each do |method_name|
59
+ message = options[method_name]
59
60
  if target_module.method_defined?(method_name) || target_module.private_method_defined?(method_name)
60
- aliased_method, punctuation = method_name.to_s.sub(/([?!=])$/, ""), $1
61
- with_method = "#{aliased_method}_with_deprecation#{punctuation}"
62
- without_method = "#{aliased_method}_without_deprecation#{punctuation}"
63
-
64
- target_module.send(:define_method, with_method) do |*args, &block|
65
- deprecator.deprecation_warning(method_name, options[method_name])
66
- send(without_method, *args, &block)
67
- end
68
-
69
- target_module.send(:alias_method, without_method, method_name)
70
- target_module.send(:alias_method, method_name, with_method)
71
-
72
- case
73
- when target_module.protected_method_defined?(without_method)
74
- target_module.send(:protected, method_name)
75
- when target_module.private_method_defined?(without_method)
76
- target_module.send(:private, method_name)
61
+ method = target_module.instance_method(method_name)
62
+ target_module.module_eval do
63
+ redefine_method(method_name) do |*args, &block|
64
+ deprecator.deprecation_warning(method_name, message)
65
+ method.bind(self).call(*args, &block)
66
+ end
67
+ ruby2_keywords(method_name) if respond_to?(:ruby2_keywords, true)
77
68
  end
78
69
  else
79
- mod.send(:define_method, method_name) do |*args, &block|
80
- deprecator.deprecation_warning(method_name, options[method_name])
81
- super(*args, &block)
70
+ mod ||= Module.new
71
+ mod.module_eval do
72
+ define_method(method_name) do |*args, &block|
73
+ deprecator.deprecation_warning(method_name, message)
74
+ super(*args, &block)
75
+ end
76
+ ruby2_keywords(method_name) if respond_to?(:ruby2_keywords, true)
82
77
  end
83
78
  end
84
79
  end
85
80
 
86
- target_module.prepend(mod) unless mod.instance_methods(false).empty?
81
+ target_module.prepend(mod) if mod
87
82
  end
88
83
  end
89
84
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/regexp"
4
-
5
3
  module ActiveSupport
6
4
  class Deprecation
7
5
  class DeprecationProxy #:nodoc:
@@ -122,9 +120,16 @@ module ActiveSupport
122
120
  # # => DEPRECATION WARNING: PLANETS is deprecated! Use PLANETS_POST_2006 instead.
123
121
  # (Backtrace information…)
124
122
  # ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"]
125
- class DeprecatedConstantProxy < DeprecationProxy
123
+ class DeprecatedConstantProxy < Module
124
+ def self.new(*args, **options, &block)
125
+ object = args.first
126
+
127
+ return object unless object
128
+ super
129
+ end
130
+
126
131
  def initialize(old_const, new_const, deprecator = ActiveSupport::Deprecation.instance, message: "#{old_const} is deprecated! Use #{new_const} instead.")
127
- require "active_support/inflector/methods"
132
+ Kernel.require "active_support/inflector/methods"
128
133
 
129
134
  @old_const = old_const
130
135
  @new_const = new_const
@@ -132,6 +137,18 @@ module ActiveSupport
132
137
  @message = message
133
138
  end
134
139
 
140
+ instance_methods.each { |m| undef_method m unless /^__|^object_id$/.match?(m) }
141
+
142
+ # Don't give a deprecation warning on inspect since test/unit and error
143
+ # logs rely on it for diagnostics.
144
+ def inspect
145
+ target.inspect
146
+ end
147
+
148
+ # Don't give a deprecation warning on methods that IRB may invoke
149
+ # during tab-completion.
150
+ delegate :hash, :instance_methods, :name, :respond_to?, to: :target
151
+
135
152
  # Returns the class of the new constant.
136
153
  #
137
154
  # PLANETS_POST_2006 = %w(mercury venus earth mars jupiter saturn uranus neptune)
@@ -146,8 +163,14 @@ module ActiveSupport
146
163
  ActiveSupport::Inflector.constantize(@new_const.to_s)
147
164
  end
148
165
 
149
- def warn(callstack, called, args)
150
- @deprecator.warn(@message, callstack)
166
+ def const_missing(name)
167
+ @deprecator.warn(@message, caller_locations)
168
+ target.const_get(name)
169
+ end
170
+
171
+ def method_missing(called, *args, &block)
172
+ @deprecator.warn(@message, caller_locations)
173
+ target.__send__(called, *args, &block)
151
174
  end
152
175
  end
153
176
  end
@@ -6,7 +6,7 @@ module ActiveSupport
6
6
  class Deprecation
7
7
  module Reporting
8
8
  # Whether to print a message (silent mode)
9
- attr_accessor :silenced
9
+ attr_writer :silenced
10
10
  # Name of gem where method is deprecated
11
11
  attr_accessor :gem_name
12
12
 
@@ -20,7 +20,11 @@ module ActiveSupport
20
20
 
21
21
  callstack ||= caller_locations(2)
22
22
  deprecation_message(callstack, message).tap do |m|
23
- behavior.each { |b| b.call(m, callstack, deprecation_horizon, gem_name) }
23
+ if deprecation_disallowed?(message)
24
+ disallowed_behavior.each { |b| b.call(m, callstack, deprecation_horizon, gem_name) }
25
+ else
26
+ behavior.each { |b| b.call(m, callstack, deprecation_horizon, gem_name) }
27
+ end
24
28
  end
25
29
  end
26
30
 
@@ -33,11 +37,50 @@ module ActiveSupport
33
37
  # ActiveSupport::Deprecation.warn('something broke!')
34
38
  # end
35
39
  # # => nil
36
- def silence
37
- old_silenced, @silenced = @silenced, true
38
- yield
39
- ensure
40
- @silenced = old_silenced
40
+ def silence(&block)
41
+ @silenced_thread.bind(true, &block)
42
+ end
43
+
44
+ # Allow previously disallowed deprecation warnings within the block.
45
+ # <tt>allowed_warnings</tt> can be an array containing strings, symbols, or regular
46
+ # expressions. (Symbols are treated as strings). These are compared against
47
+ # the text of deprecation warning messages generated within the block.
48
+ # Matching warnings will be exempt from the rules set by
49
+ # +ActiveSupport::Deprecation.disallowed_warnings+
50
+ #
51
+ # The optional <tt>if:</tt> argument accepts a truthy/falsy value or an object that
52
+ # responds to <tt>.call</tt>. If truthy, then matching warnings will be allowed.
53
+ # If falsey then the method yields to the block without allowing the warning.
54
+ #
55
+ # ActiveSupport::Deprecation.disallowed_behavior = :raise
56
+ # ActiveSupport::Deprecation.disallowed_warnings = [
57
+ # "something broke"
58
+ # ]
59
+ #
60
+ # ActiveSupport::Deprecation.warn('something broke!')
61
+ # # => ActiveSupport::DeprecationException
62
+ #
63
+ # ActiveSupport::Deprecation.allow ['something broke'] do
64
+ # ActiveSupport::Deprecation.warn('something broke!')
65
+ # end
66
+ # # => nil
67
+ #
68
+ # ActiveSupport::Deprecation.allow ['something broke'], if: Rails.env.production? do
69
+ # ActiveSupport::Deprecation.warn('something broke!')
70
+ # end
71
+ # # => ActiveSupport::DeprecationException for dev/test, nil for production
72
+ def allow(allowed_warnings = :all, if: true, &block)
73
+ conditional = binding.local_variable_get(:if)
74
+ conditional = conditional.call if conditional.respond_to?(:call)
75
+ if conditional
76
+ @explicitly_allowed_warnings.bind(allowed_warnings, &block)
77
+ else
78
+ yield
79
+ end
80
+ end
81
+
82
+ def silenced
83
+ @silenced || @silenced_thread.value
41
84
  end
42
85
 
43
86
  def deprecation_warning(deprecated_method_name, message = nil, caller_backtrace = nil)
@@ -17,15 +17,18 @@ module ActiveSupport
17
17
  require "active_support/deprecation/instance_delegator"
18
18
  require "active_support/deprecation/behaviors"
19
19
  require "active_support/deprecation/reporting"
20
+ require "active_support/deprecation/disallowed"
20
21
  require "active_support/deprecation/constant_accessor"
21
22
  require "active_support/deprecation/method_wrappers"
22
23
  require "active_support/deprecation/proxy_wrappers"
23
24
  require "active_support/core_ext/module/deprecation"
25
+ require "concurrent/atomic/thread_local_var"
24
26
 
25
27
  include Singleton
26
28
  include InstanceDelegator
27
29
  include Behavior
28
30
  include Reporting
31
+ include Disallowed
29
32
  include MethodWrapper
30
33
 
31
34
  # The version number in which the deprecated behavior will be removed, by default.
@@ -35,12 +38,14 @@ module ActiveSupport
35
38
  # and the second is a library name.
36
39
  #
37
40
  # ActiveSupport::Deprecation.new('2.0', 'MyLibrary')
38
- def initialize(deprecation_horizon = "6.0", gem_name = "Rails")
41
+ def initialize(deprecation_horizon = "7.0", gem_name = "Rails")
39
42
  self.gem_name = gem_name
40
43
  self.deprecation_horizon = deprecation_horizon
41
44
  # By default, warnings are not silenced and debugging is off.
42
45
  self.silenced = false
43
46
  self.debug = false
47
+ @silenced_thread = Concurrent::ThreadLocalVar.new(false)
48
+ @explicitly_allowed_warnings = Concurrent::ThreadLocalVar.new(nil)
44
49
  end
45
50
  end
46
51
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "weakref"
4
+
3
5
  module ActiveSupport
4
6
  # This module provides an internal implementation to track descendants
5
7
  # which is faster than iterating through ObjectSpace.
@@ -8,8 +10,10 @@ module ActiveSupport
8
10
 
9
11
  class << self
10
12
  def direct_descendants(klass)
11
- @@direct_descendants[klass] || []
13
+ descendants = @@direct_descendants[klass]
14
+ descendants ? descendants.to_a : []
12
15
  end
16
+ alias_method :subclasses, :direct_descendants
13
17
 
14
18
  def descendants(klass)
15
19
  arr = []
@@ -20,10 +24,10 @@ module ActiveSupport
20
24
  def clear
21
25
  if defined? ActiveSupport::Dependencies
22
26
  @@direct_descendants.each do |klass, descendants|
23
- if ActiveSupport::Dependencies.autoloaded?(klass)
27
+ if Dependencies.autoloaded?(klass)
24
28
  @@direct_descendants.delete(klass)
25
29
  else
26
- descendants.reject! { |v| ActiveSupport::Dependencies.autoloaded?(v) }
30
+ descendants.reject! { |v| Dependencies.autoloaded?(v) }
27
31
  end
28
32
  end
29
33
  else
@@ -34,16 +38,18 @@ module ActiveSupport
34
38
  # This is the only method that is not thread safe, but is only ever called
35
39
  # during the eager loading phase.
36
40
  def store_inherited(klass, descendant)
37
- (@@direct_descendants[klass] ||= []) << descendant
41
+ (@@direct_descendants[klass] ||= DescendantsArray.new) << descendant
38
42
  end
39
43
 
40
44
  private
41
- def accumulate_descendants(klass, acc)
42
- if direct_descendants = @@direct_descendants[klass]
43
- acc.concat(direct_descendants)
44
- direct_descendants.each { |direct_descendant| accumulate_descendants(direct_descendant, acc) }
45
+ def accumulate_descendants(klass, acc)
46
+ if direct_descendants = @@direct_descendants[klass]
47
+ direct_descendants.each do |direct_descendant|
48
+ acc << direct_descendant
49
+ accumulate_descendants(direct_descendant, acc)
50
+ end
51
+ end
45
52
  end
46
- end
47
53
  end
48
54
 
49
55
  def inherited(base)
@@ -54,9 +60,53 @@ module ActiveSupport
54
60
  def direct_descendants
55
61
  DescendantsTracker.direct_descendants(self)
56
62
  end
63
+ alias_method :subclasses, :direct_descendants
57
64
 
58
65
  def descendants
59
66
  DescendantsTracker.descendants(self)
60
67
  end
68
+
69
+ # DescendantsArray is an array that contains weak references to classes.
70
+ class DescendantsArray # :nodoc:
71
+ include Enumerable
72
+
73
+ def initialize
74
+ @refs = []
75
+ end
76
+
77
+ def initialize_copy(orig)
78
+ @refs = @refs.dup
79
+ end
80
+
81
+ def <<(klass)
82
+ @refs << WeakRef.new(klass)
83
+ end
84
+
85
+ def each
86
+ @refs.reject! do |ref|
87
+ yield ref.__getobj__
88
+ false
89
+ rescue WeakRef::RefError
90
+ true
91
+ end
92
+ self
93
+ end
94
+
95
+ def refs_size
96
+ @refs.size
97
+ end
98
+
99
+ def cleanup!
100
+ @refs.delete_if { |ref| !ref.weakref_alive? }
101
+ end
102
+
103
+ def reject!
104
+ @refs.reject! do |ref|
105
+ yield ref.__getobj__
106
+ rescue WeakRef::RefError
107
+ true
108
+ end
109
+ end
110
+ end
61
111
  end
62
112
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "digest"
4
+
3
5
  module ActiveSupport
4
6
  class Digest #:nodoc:
5
7
  class <<self
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "strscan"
4
- require "active_support/core_ext/regexp"
5
4
 
6
5
  module ActiveSupport
7
6
  class Duration
@@ -14,8 +13,8 @@ module ActiveSupport
14
13
  class ParsingError < ::ArgumentError; end
15
14
 
16
15
  PERIOD_OR_COMMA = /\.|,/
17
- PERIOD = ".".freeze
18
- COMMA = ",".freeze
16
+ PERIOD = "."
17
+ COMMA = ","
19
18
 
20
19
  SIGN_MARKER = /\A\-|\+|/
21
20
  DATE_MARKER = /P/
@@ -81,7 +80,6 @@ module ActiveSupport
81
80
  end
82
81
 
83
82
  private
84
-
85
83
  def finished?
86
84
  scanner.eos?
87
85
  end
@@ -1,12 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/core_ext/object/blank"
4
- require "active_support/core_ext/hash/transform_values"
5
4
 
6
5
  module ActiveSupport
7
6
  class Duration
8
7
  # Serializes duration to string according to ISO 8601 Duration format.
9
8
  class ISO8601Serializer # :nodoc:
9
+ DATE_COMPONENTS = %i(years months days)
10
+
10
11
  def initialize(duration, precision: nil)
11
12
  @duration = duration
12
13
  @precision = precision
@@ -14,26 +15,25 @@ module ActiveSupport
14
15
 
15
16
  # Builds and returns output string.
16
17
  def serialize
17
- parts, sign = normalize
18
- return "PT0S".freeze if parts.empty?
18
+ parts = normalize
19
+ return "PT0S" if parts.empty?
19
20
 
20
- output = "P".dup
21
+ output = +"P"
21
22
  output << "#{parts[:years]}Y" if parts.key?(:years)
22
23
  output << "#{parts[:months]}M" if parts.key?(:months)
23
- output << "#{parts[:weeks]}W" if parts.key?(:weeks)
24
24
  output << "#{parts[:days]}D" if parts.key?(:days)
25
- time = "".dup
25
+ output << "#{parts[:weeks]}W" if parts.key?(:weeks)
26
+ time = +""
26
27
  time << "#{parts[:hours]}H" if parts.key?(:hours)
27
28
  time << "#{parts[:minutes]}M" if parts.key?(:minutes)
28
29
  if parts.key?(:seconds)
29
30
  time << "#{sprintf(@precision ? "%0.0#{@precision}f" : '%g', parts[:seconds])}S"
30
31
  end
31
32
  output << "T#{time}" unless time.empty?
32
- "#{sign}#{output}"
33
+ output
33
34
  end
34
35
 
35
36
  private
36
-
37
37
  # Return pair of duration's parts and whole duration sign.
38
38
  # Parts are summarized (as they can become repetitive due to addition, etc).
39
39
  # Zero parts are removed as not significant.
@@ -42,13 +42,17 @@ module ActiveSupport
42
42
  parts = @duration.parts.each_with_object(Hash.new(0)) do |(k, v), p|
43
43
  p[k] += v unless v.zero?
44
44
  end
45
- # If all parts are negative - let's make a negative duration
46
- sign = ""
47
- if parts.values.all? { |v| v < 0 }
48
- sign = "-"
49
- parts.transform_values!(&:-@)
45
+
46
+ # Convert weeks to days and remove weeks if mixed with date parts
47
+ if week_mixed_with_date?(parts)
48
+ parts[:days] += parts.delete(:weeks) * SECONDS_PER_WEEK / SECONDS_PER_DAY
50
49
  end
51
- [parts, sign]
50
+
51
+ parts
52
+ end
53
+
54
+ def week_mixed_with_date?(parts)
55
+ parts.key?(:weeks) && (parts.keys & DATE_COMPONENTS).any?
52
56
  end
53
57
  end
54
58
  end