activesupport 7.0.0 → 7.2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +156 -255
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +6 -6
  5. data/lib/active_support/actionable_error.rb +3 -1
  6. data/lib/active_support/array_inquirer.rb +3 -1
  7. data/lib/active_support/backtrace_cleaner.rb +41 -9
  8. data/lib/active_support/benchmarkable.rb +1 -0
  9. data/lib/active_support/broadcast_logger.rb +251 -0
  10. data/lib/active_support/builder.rb +1 -1
  11. data/lib/active_support/cache/coder.rb +153 -0
  12. data/lib/active_support/cache/entry.rb +134 -0
  13. data/lib/active_support/cache/file_store.rb +49 -17
  14. data/lib/active_support/cache/mem_cache_store.rb +111 -129
  15. data/lib/active_support/cache/memory_store.rb +81 -26
  16. data/lib/active_support/cache/null_store.rb +6 -0
  17. data/lib/active_support/cache/redis_cache_store.rb +175 -154
  18. data/lib/active_support/cache/serializer_with_fallback.rb +152 -0
  19. data/lib/active_support/cache/strategy/local_cache.rb +31 -13
  20. data/lib/active_support/cache.rb +457 -377
  21. data/lib/active_support/callbacks.rb +123 -139
  22. data/lib/active_support/code_generator.rb +15 -10
  23. data/lib/active_support/concern.rb +4 -2
  24. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +42 -3
  25. data/lib/active_support/concurrency/null_lock.rb +13 -0
  26. data/lib/active_support/configurable.rb +12 -2
  27. data/lib/active_support/core_ext/array/conversions.rb +7 -9
  28. data/lib/active_support/core_ext/array/inquiry.rb +2 -2
  29. data/lib/active_support/core_ext/array.rb +0 -1
  30. data/lib/active_support/core_ext/class/subclasses.rb +4 -15
  31. data/lib/active_support/core_ext/date/blank.rb +4 -0
  32. data/lib/active_support/core_ext/date/calculations.rb +20 -5
  33. data/lib/active_support/core_ext/date/conversions.rb +15 -16
  34. data/lib/active_support/core_ext/date.rb +0 -1
  35. data/lib/active_support/core_ext/date_and_time/calculations.rb +14 -4
  36. data/lib/active_support/core_ext/date_and_time/compatibility.rb +29 -2
  37. data/lib/active_support/core_ext/date_time/blank.rb +4 -0
  38. data/lib/active_support/core_ext/date_time/calculations.rb +4 -0
  39. data/lib/active_support/core_ext/date_time/conversions.rb +15 -15
  40. data/lib/active_support/core_ext/date_time.rb +0 -1
  41. data/lib/active_support/core_ext/digest/uuid.rb +7 -10
  42. data/lib/active_support/core_ext/enumerable.rb +51 -101
  43. data/lib/active_support/core_ext/erb/util.rb +201 -0
  44. data/lib/active_support/core_ext/file/atomic.rb +2 -0
  45. data/lib/active_support/core_ext/hash/conversions.rb +1 -2
  46. data/lib/active_support/core_ext/hash/deep_merge.rb +22 -14
  47. data/lib/active_support/core_ext/hash/deep_transform_values.rb +3 -3
  48. data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -3
  49. data/lib/active_support/core_ext/hash/keys.rb +7 -7
  50. data/lib/active_support/core_ext/integer/inflections.rb +12 -12
  51. data/lib/active_support/core_ext/kernel/singleton_class.rb +1 -1
  52. data/lib/active_support/core_ext/module/attr_internal.rb +17 -6
  53. data/lib/active_support/core_ext/module/attribute_accessors.rb +6 -0
  54. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +38 -20
  55. data/lib/active_support/core_ext/module/concerning.rb +6 -6
  56. data/lib/active_support/core_ext/module/delegation.rb +20 -119
  57. data/lib/active_support/core_ext/module/deprecation.rb +12 -12
  58. data/lib/active_support/core_ext/module/introspection.rb +0 -1
  59. data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
  60. data/lib/active_support/core_ext/numeric/conversions.rb +77 -75
  61. data/lib/active_support/core_ext/numeric.rb +0 -1
  62. data/lib/active_support/core_ext/object/acts_like.rb +29 -5
  63. data/lib/active_support/core_ext/object/blank.rb +45 -1
  64. data/lib/active_support/core_ext/object/deep_dup.rb +16 -0
  65. data/lib/active_support/core_ext/object/duplicable.rb +25 -16
  66. data/lib/active_support/core_ext/object/inclusion.rb +13 -5
  67. data/lib/active_support/core_ext/object/instance_variables.rb +4 -2
  68. data/lib/active_support/core_ext/object/json.rb +17 -7
  69. data/lib/active_support/core_ext/object/to_query.rb +0 -2
  70. data/lib/active_support/core_ext/object/with.rb +46 -0
  71. data/lib/active_support/core_ext/object/with_options.rb +9 -9
  72. data/lib/active_support/core_ext/object.rb +1 -0
  73. data/lib/active_support/core_ext/pathname/blank.rb +20 -0
  74. data/lib/active_support/core_ext/pathname/existence.rb +2 -0
  75. data/lib/active_support/core_ext/pathname.rb +1 -0
  76. data/lib/active_support/core_ext/range/conversions.rb +32 -11
  77. data/lib/active_support/core_ext/range/overlap.rb +40 -0
  78. data/lib/active_support/core_ext/range.rb +1 -2
  79. data/lib/active_support/core_ext/securerandom.rb +2 -6
  80. data/lib/active_support/core_ext/string/conversions.rb +3 -3
  81. data/lib/active_support/core_ext/string/filters.rb +21 -15
  82. data/lib/active_support/core_ext/string/indent.rb +1 -1
  83. data/lib/active_support/core_ext/string/inflections.rb +16 -9
  84. data/lib/active_support/core_ext/string/inquiry.rb +1 -1
  85. data/lib/active_support/core_ext/string/multibyte.rb +1 -1
  86. data/lib/active_support/core_ext/string/output_safety.rb +39 -150
  87. data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
  88. data/lib/active_support/core_ext/time/calculations.rb +42 -32
  89. data/lib/active_support/core_ext/time/compatibility.rb +16 -0
  90. data/lib/active_support/core_ext/time/conversions.rb +13 -15
  91. data/lib/active_support/core_ext/time/zones.rb +8 -9
  92. data/lib/active_support/core_ext/time.rb +0 -1
  93. data/lib/active_support/core_ext.rb +0 -1
  94. data/lib/active_support/current_attributes.rb +53 -46
  95. data/lib/active_support/deep_mergeable.rb +53 -0
  96. data/lib/active_support/delegation.rb +202 -0
  97. data/lib/active_support/dependencies/autoload.rb +9 -16
  98. data/lib/active_support/deprecation/behaviors.rb +65 -42
  99. data/lib/active_support/deprecation/constant_accessor.rb +47 -25
  100. data/lib/active_support/deprecation/deprecators.rb +104 -0
  101. data/lib/active_support/deprecation/disallowed.rb +6 -8
  102. data/lib/active_support/deprecation/method_wrappers.rb +6 -23
  103. data/lib/active_support/deprecation/proxy_wrappers.rb +34 -22
  104. data/lib/active_support/deprecation/reporting.rb +49 -27
  105. data/lib/active_support/deprecation.rb +39 -9
  106. data/lib/active_support/deprecator.rb +7 -0
  107. data/lib/active_support/descendants_tracker.rb +66 -175
  108. data/lib/active_support/duration/iso8601_parser.rb +2 -2
  109. data/lib/active_support/duration/iso8601_serializer.rb +1 -4
  110. data/lib/active_support/duration.rb +13 -7
  111. data/lib/active_support/encrypted_configuration.rb +63 -10
  112. data/lib/active_support/encrypted_file.rb +29 -13
  113. data/lib/active_support/environment_inquirer.rb +22 -2
  114. data/lib/active_support/error_reporter/test_helper.rb +15 -0
  115. data/lib/active_support/error_reporter.rb +160 -36
  116. data/lib/active_support/evented_file_update_checker.rb +19 -7
  117. data/lib/active_support/execution_wrapper.rb +23 -28
  118. data/lib/active_support/file_update_checker.rb +5 -3
  119. data/lib/active_support/fork_tracker.rb +4 -32
  120. data/lib/active_support/gem_version.rb +4 -4
  121. data/lib/active_support/gzip.rb +2 -0
  122. data/lib/active_support/hash_with_indifferent_access.rb +41 -25
  123. data/lib/active_support/html_safe_translation.rb +19 -6
  124. data/lib/active_support/i18n.rb +1 -1
  125. data/lib/active_support/i18n_railtie.rb +20 -13
  126. data/lib/active_support/inflector/inflections.rb +2 -0
  127. data/lib/active_support/inflector/methods.rb +28 -18
  128. data/lib/active_support/inflector/transliterate.rb +4 -2
  129. data/lib/active_support/isolated_execution_state.rb +39 -19
  130. data/lib/active_support/json/decoding.rb +2 -1
  131. data/lib/active_support/json/encoding.rb +25 -43
  132. data/lib/active_support/key_generator.rb +13 -5
  133. data/lib/active_support/lazy_load_hooks.rb +33 -7
  134. data/lib/active_support/locale/en.yml +2 -0
  135. data/lib/active_support/log_subscriber/test_helper.rb +2 -2
  136. data/lib/active_support/log_subscriber.rb +76 -36
  137. data/lib/active_support/logger.rb +22 -60
  138. data/lib/active_support/logger_thread_safe_level.rb +10 -32
  139. data/lib/active_support/message_encryptor.rb +200 -55
  140. data/lib/active_support/message_encryptors.rb +141 -0
  141. data/lib/active_support/message_pack/cache_serializer.rb +23 -0
  142. data/lib/active_support/message_pack/extensions.rb +305 -0
  143. data/lib/active_support/message_pack/serializer.rb +63 -0
  144. data/lib/active_support/message_pack.rb +50 -0
  145. data/lib/active_support/message_verifier.rb +220 -89
  146. data/lib/active_support/message_verifiers.rb +135 -0
  147. data/lib/active_support/messages/codec.rb +65 -0
  148. data/lib/active_support/messages/metadata.rb +111 -45
  149. data/lib/active_support/messages/rotation_coordinator.rb +93 -0
  150. data/lib/active_support/messages/rotator.rb +34 -32
  151. data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
  152. data/lib/active_support/multibyte/chars.rb +4 -2
  153. data/lib/active_support/multibyte/unicode.rb +9 -37
  154. data/lib/active_support/notifications/fanout.rb +248 -87
  155. data/lib/active_support/notifications/instrumenter.rb +93 -25
  156. data/lib/active_support/notifications.rb +38 -31
  157. data/lib/active_support/number_helper/number_converter.rb +16 -7
  158. data/lib/active_support/number_helper/number_to_currency_converter.rb +6 -6
  159. data/lib/active_support/number_helper/number_to_human_size_converter.rb +3 -3
  160. data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -0
  161. data/lib/active_support/number_helper.rb +379 -317
  162. data/lib/active_support/option_merger.rb +4 -4
  163. data/lib/active_support/ordered_hash.rb +3 -3
  164. data/lib/active_support/ordered_options.rb +68 -16
  165. data/lib/active_support/parameter_filter.rb +103 -84
  166. data/lib/active_support/proxy_object.rb +8 -3
  167. data/lib/active_support/railtie.rb +30 -25
  168. data/lib/active_support/reloader.rb +13 -5
  169. data/lib/active_support/rescuable.rb +12 -10
  170. data/lib/active_support/secure_compare_rotator.rb +17 -10
  171. data/lib/active_support/string_inquirer.rb +4 -2
  172. data/lib/active_support/subscriber.rb +10 -27
  173. data/lib/active_support/syntax_error_proxy.rb +60 -0
  174. data/lib/active_support/tagged_logging.rb +64 -25
  175. data/lib/active_support/test_case.rb +160 -7
  176. data/lib/active_support/testing/assertions.rb +29 -13
  177. data/lib/active_support/testing/autorun.rb +0 -2
  178. data/lib/active_support/testing/constant_stubbing.rb +54 -0
  179. data/lib/active_support/testing/deprecation.rb +20 -27
  180. data/lib/active_support/testing/error_reporter_assertions.rb +107 -0
  181. data/lib/active_support/testing/isolation.rb +46 -33
  182. data/lib/active_support/testing/method_call_assertions.rb +7 -8
  183. data/lib/active_support/testing/parallelization/server.rb +3 -0
  184. data/lib/active_support/testing/parallelize_executor.rb +8 -3
  185. data/lib/active_support/testing/setup_and_teardown.rb +2 -0
  186. data/lib/active_support/testing/stream.rb +1 -1
  187. data/lib/active_support/testing/strict_warnings.rb +43 -0
  188. data/lib/active_support/testing/tests_without_assertions.rb +19 -0
  189. data/lib/active_support/testing/time_helpers.rb +38 -16
  190. data/lib/active_support/time_with_zone.rb +28 -54
  191. data/lib/active_support/values/time_zone.rb +26 -15
  192. data/lib/active_support/version.rb +1 -1
  193. data/lib/active_support/xml_mini/jdom.rb +3 -10
  194. data/lib/active_support/xml_mini/nokogiri.rb +1 -1
  195. data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
  196. data/lib/active_support/xml_mini/rexml.rb +1 -1
  197. data/lib/active_support/xml_mini.rb +13 -4
  198. data/lib/active_support.rb +15 -3
  199. metadata +142 -21
  200. data/lib/active_support/core_ext/array/deprecated_conversions.rb +0 -25
  201. data/lib/active_support/core_ext/date/deprecated_conversions.rb +0 -26
  202. data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +0 -22
  203. data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +0 -60
  204. data/lib/active_support/core_ext/range/deprecated_conversions.rb +0 -26
  205. data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -7
  206. data/lib/active_support/core_ext/range/overlaps.rb +0 -10
  207. data/lib/active_support/core_ext/time/deprecated_conversions.rb +0 -22
  208. data/lib/active_support/core_ext/uri.rb +0 -5
  209. data/lib/active_support/deprecation/instance_delegator.rb +0 -38
  210. data/lib/active_support/per_thread_registry.rb +0 -65
  211. data/lib/active_support/ruby_features.rb +0 -7
@@ -3,10 +3,12 @@
3
3
  require "active_support/inflector/methods"
4
4
 
5
5
  module ActiveSupport
6
+ # = Active Support \Autoload
7
+ #
6
8
  # Autoload and eager load conveniences for your library.
7
9
  #
8
10
  # This module allows you to define autoloads based on
9
- # Rails conventions (i.e. no need to define the path
11
+ # \Rails conventions (i.e. no need to define the path
10
12
  # it is automatically guessed based on the filename)
11
13
  # and also define a set of constants that needs to be
12
14
  # eager loaded:
@@ -25,15 +27,6 @@ module ActiveSupport
25
27
  #
26
28
  # MyLib.eager_load!
27
29
  module Autoload
28
- def self.extended(base) # :nodoc:
29
- base.class_eval do
30
- @_autoloads = {}
31
- @_under_path = nil
32
- @_at_path = nil
33
- @_eager_autoload = false
34
- end
35
- end
36
-
37
30
  def autoload(const_name, path = @_at_path)
38
31
  unless path
39
32
  full = [name, @_under_path, const_name.to_s].compact.join("::")
@@ -41,7 +34,8 @@ module ActiveSupport
41
34
  end
42
35
 
43
36
  if @_eager_autoload
44
- @_autoloads[const_name] = path
37
+ @_eagerloaded_constants ||= []
38
+ @_eagerloaded_constants << const_name
45
39
  end
46
40
 
47
41
  super const_name, path
@@ -69,11 +63,10 @@ module ActiveSupport
69
63
  end
70
64
 
71
65
  def eager_load!
72
- @_autoloads.each_value { |file| require file }
73
- end
74
-
75
- def autoloads
76
- @_autoloads
66
+ if @_eagerloaded_constants
67
+ @_eagerloaded_constants.each { |const_name| const_get(const_name) }
68
+ @_eagerloaded_constants = nil
69
+ end
77
70
  end
78
71
  end
79
72
  end
@@ -3,7 +3,7 @@
3
3
  require "active_support/notifications"
4
4
 
5
5
  module ActiveSupport
6
- # Raised when <tt>ActiveSupport::Deprecation::Behavior#behavior</tt> is set with <tt>:raise</tt>.
6
+ # Raised when ActiveSupport::Deprecation::Behavior#behavior is set with <tt>:raise</tt>.
7
7
  # You would set <tt>:raise</tt>, as a behavior to raise errors and proactively report exceptions from deprecations.
8
8
  class DeprecationException < StandardError
9
9
  end
@@ -11,18 +11,18 @@ module ActiveSupport
11
11
  class Deprecation
12
12
  # Default warning behaviors per Rails.env.
13
13
  DEFAULT_BEHAVIORS = {
14
- raise: ->(message, callstack, deprecation_horizon, gem_name) {
14
+ raise: ->(message, callstack, deprecator) do
15
15
  e = DeprecationException.new(message)
16
16
  e.set_backtrace(callstack.map(&:to_s))
17
17
  raise e
18
- },
18
+ end,
19
19
 
20
- stderr: ->(message, callstack, deprecation_horizon, gem_name) {
20
+ stderr: ->(message, callstack, deprecator) do
21
21
  $stderr.puts(message)
22
- $stderr.puts callstack.join("\n ") if debug
23
- },
22
+ $stderr.puts callstack.join("\n ") if deprecator.debug
23
+ end,
24
24
 
25
- log: ->(message, callstack, deprecation_horizon, gem_name) {
25
+ log: ->(message, callstack, deprecator) do
26
26
  logger =
27
27
  if defined?(Rails.logger) && Rails.logger
28
28
  Rails.logger
@@ -31,33 +31,41 @@ module ActiveSupport
31
31
  ActiveSupport::Logger.new($stderr)
32
32
  end
33
33
  logger.warn message
34
- logger.debug callstack.join("\n ") if debug
35
- },
36
-
37
- notify: ->(message, callstack, deprecation_horizon, gem_name) {
38
- notification_name = "deprecation.#{gem_name.underscore.tr('/', '_')}"
39
- ActiveSupport::Notifications.instrument(notification_name,
40
- message: message,
41
- callstack: callstack,
42
- gem_name: gem_name,
43
- deprecation_horizon: deprecation_horizon)
44
- },
45
-
46
- silence: ->(message, callstack, deprecation_horizon, gem_name) { },
34
+ logger.debug callstack.join("\n ") if deprecator.debug
35
+ end,
36
+
37
+ notify: ->(message, callstack, deprecator) do
38
+ ActiveSupport::Notifications.instrument(
39
+ "deprecation.#{deprecator.gem_name.underscore.tr("/", "_")}",
40
+ message: message,
41
+ callstack: callstack,
42
+ gem_name: deprecator.gem_name,
43
+ deprecation_horizon: deprecator.deprecation_horizon,
44
+ )
45
+ end,
46
+
47
+ silence: ->(message, callstack, deprecator) { },
48
+
49
+ report: ->(message, callstack, deprecator) do
50
+ error = DeprecationException.new(message)
51
+ error.set_backtrace(callstack.map(&:to_s))
52
+ ActiveSupport.error_reporter.report(error)
53
+ end
47
54
  }
48
55
 
49
56
  # Behavior module allows to determine how to display deprecation messages.
50
57
  # You can create a custom behavior or set any from the +DEFAULT_BEHAVIORS+
51
58
  # constant. Available behaviors are:
52
59
  #
53
- # [+raise+] Raise <tt>ActiveSupport::DeprecationException</tt>.
54
- # [+stderr+] Log all deprecation warnings to <tt>$stderr</tt>.
55
- # [+log+] Log all deprecation warnings to +Rails.logger+.
56
- # [+notify+] Use +ActiveSupport::Notifications+ to notify +deprecation.rails+.
57
- # [+silence+] Do nothing. On Rails, set <tt>config.active_support.report_deprecations = false</tt> to disable all behaviors.
60
+ # [+:raise+] Raise ActiveSupport::DeprecationException.
61
+ # [+:stderr+] Log all deprecation warnings to <tt>$stderr</tt>.
62
+ # [+:log+] Log all deprecation warnings to +Rails.logger+.
63
+ # [+:notify+] Use ActiveSupport::Notifications to notify +deprecation.rails+.
64
+ # [+:report+] Use ActiveSupport::ErrorReporter to report deprecations.
65
+ # [+:silence+] Do nothing. On \Rails, set <tt>config.active_support.report_deprecations = false</tt> to disable all behaviors.
58
66
  #
59
67
  # Setting behaviors only affects deprecations that happen after boot time.
60
- # For more information you can read the documentation of the +behavior=+ method.
68
+ # For more information you can read the documentation of the #behavior= method.
61
69
  module Behavior
62
70
  # Whether to print a backtrace along with the warning.
63
71
  attr_accessor :debug
@@ -77,32 +85,36 @@ module ActiveSupport
77
85
  #
78
86
  # Available behaviors:
79
87
  #
80
- # [+raise+] Raise <tt>ActiveSupport::DeprecationException</tt>.
81
- # [+stderr+] Log all deprecation warnings to <tt>$stderr</tt>.
82
- # [+log+] Log all deprecation warnings to +Rails.logger+.
83
- # [+notify+] Use +ActiveSupport::Notifications+ to notify +deprecation.rails+.
84
- # [+silence+] Do nothing.
88
+ # [+:raise+] Raise ActiveSupport::DeprecationException.
89
+ # [+:stderr+] Log all deprecation warnings to <tt>$stderr</tt>.
90
+ # [+:log+] Log all deprecation warnings to +Rails.logger+.
91
+ # [+:notify+] Use ActiveSupport::Notifications to notify +deprecation.rails+.
92
+ # [+:report+] Use ActiveSupport::ErrorReporter to report deprecations.
93
+ # [+:silence+] Do nothing.
85
94
  #
86
95
  # Setting behaviors only affects deprecations that happen after boot time.
87
96
  # Deprecation warnings raised by gems are not affected by this setting
88
- # because they happen before Rails boots up.
97
+ # because they happen before \Rails boots up.
89
98
  #
90
- # ActiveSupport::Deprecation.behavior = :stderr
91
- # ActiveSupport::Deprecation.behavior = [:stderr, :log]
92
- # ActiveSupport::Deprecation.behavior = MyCustomHandler
93
- # ActiveSupport::Deprecation.behavior = ->(message, callstack, deprecation_horizon, gem_name) {
99
+ # deprecator = ActiveSupport::Deprecation.new
100
+ # deprecator.behavior = :stderr
101
+ # deprecator.behavior = [:stderr, :log]
102
+ # deprecator.behavior = MyCustomHandler
103
+ # deprecator.behavior = ->(message, callstack, deprecation_horizon, gem_name) {
94
104
  # # custom stuff
95
105
  # }
96
106
  #
97
- # If you are using Rails, you can set <tt>config.active_support.report_deprecations = false</tt> to disable
98
- # all deprecation behaviors. This is similar to the +silence+ option but more performant.
107
+ # If you are using \Rails, you can set
108
+ # <tt>config.active_support.report_deprecations = false</tt> to disable
109
+ # all deprecation behaviors. This is similar to the +:silence+ option but
110
+ # more performant.
99
111
  def behavior=(behavior)
100
112
  @behavior = Array(behavior).map { |b| DEFAULT_BEHAVIORS[b] || arity_coerce(b) }
101
113
  end
102
114
 
103
115
  # Sets the behavior for disallowed deprecations (those configured by
104
- # ActiveSupport::Deprecation.disallowed_warnings=) to the specified
105
- # value. As with +behavior=+, this can be a single value, array, or an
116
+ # ActiveSupport::Deprecation#disallowed_warnings=) to the specified
117
+ # value. As with #behavior=, this can be a single value, array, or an
106
118
  # object that responds to +call+.
107
119
  def disallowed_behavior=(behavior)
108
120
  @disallowed_behavior = Array(behavior).map { |b| DEFAULT_BEHAVIORS[b] || arity_coerce(b) }
@@ -114,12 +126,23 @@ module ActiveSupport
114
126
  raise ArgumentError, "#{behavior.inspect} is not a valid deprecation behavior."
115
127
  end
116
128
 
117
- if behavior.arity == 4 || behavior.arity == -1
129
+ case arity_of_callable(behavior)
130
+ when 2
131
+ ->(message, callstack, deprecator) do
132
+ behavior.call(message, callstack)
133
+ end
134
+ when -2..3
118
135
  behavior
119
136
  else
120
- -> message, callstack, _, _ { behavior.call(message, callstack) }
137
+ ->(message, callstack, deprecator) do
138
+ behavior.call(message, callstack, deprecator.deprecation_horizon, deprecator.gem_name)
139
+ end
121
140
  end
122
141
  end
142
+
143
+ def arity_of_callable(callable)
144
+ callable.respond_to?(:arity) ? callable.arity : callable.method(:call).arity
145
+ end
123
146
  end
124
147
  end
125
148
  end
@@ -2,29 +2,6 @@
2
2
 
3
3
  module ActiveSupport
4
4
  class Deprecation
5
- # DeprecatedConstantAccessor transforms a constant into a deprecated one by
6
- # hooking +const_missing+.
7
- #
8
- # It takes the names of an old (deprecated) constant and of a new constant
9
- # (both in string form) and optionally a deprecator. The deprecator defaults
10
- # to +ActiveSupport::Deprecator+ if none is specified.
11
- #
12
- # The deprecated constant now returns the same object as the new one rather
13
- # than a proxy object, so it can be used transparently in +rescue+ blocks
14
- # etc.
15
- #
16
- # PLANETS = %w(mercury venus earth mars jupiter saturn uranus neptune pluto)
17
- #
18
- # # (In a later update, the original implementation of `PLANETS` has been removed.)
19
- #
20
- # PLANETS_POST_2006 = %w(mercury venus earth mars jupiter saturn uranus neptune)
21
- # include ActiveSupport::Deprecation::DeprecatedConstantAccessor
22
- # deprecate_constant 'PLANETS', 'PLANETS_POST_2006'
23
- #
24
- # PLANETS.map { |planet| planet.capitalize }
25
- # # => DEPRECATION WARNING: PLANETS is deprecated! Use PLANETS_POST_2006 instead.
26
- # (Backtrace information…)
27
- # ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"]
28
5
  module DeprecatedConstantAccessor
29
6
  def self.included(base)
30
7
  require "active_support/inflector/methods"
@@ -40,9 +17,54 @@ module ActiveSupport
40
17
  super
41
18
  end
42
19
 
43
- def deprecate_constant(const_name, new_constant, message: nil, deprecator: ActiveSupport::Deprecation.instance)
20
+ # Provides a way to rename constants with a deprecation cycle in which
21
+ # both the old and new names work, but using the old one prints a
22
+ # deprecation message.
23
+ #
24
+ # In order to rename <tt>A::B</tt> to <tt>C::D</tt>, you need to delete the
25
+ # definition of <tt>A::B</tt> and declare the deprecation in +A+:
26
+ #
27
+ # require "active_support/deprecation"
28
+ #
29
+ # module A
30
+ # include ActiveSupport::Deprecation::DeprecatedConstantAccessor
31
+ #
32
+ # deprecate_constant "B", "C::D", deprecator: ActiveSupport::Deprecation.new
33
+ # end
34
+ #
35
+ # The first argument is a constant name (no colons). It is the name of
36
+ # the constant you want to deprecate in the enclosing class or module.
37
+ #
38
+ # The second argument is the constant path of the replacement. That
39
+ # has to be a full path even if the replacement is defined in the same
40
+ # namespace as the deprecated one was.
41
+ #
42
+ # In both cases, strings and symbols are supported.
43
+ #
44
+ # The +deprecator+ keyword argument is the object that will print the
45
+ # deprecation message, an instance of ActiveSupport::Deprecation.
46
+ #
47
+ # With that in place, references to <tt>A::B</tt> still work, they
48
+ # evaluate to <tt>C::D</tt> now, and trigger a deprecation warning:
49
+ #
50
+ # DEPRECATION WARNING: A::B is deprecated! Use C::D instead.
51
+ # (called from ...)
52
+ #
53
+ # The message can be customized with the optional +message+ keyword
54
+ # argument.
55
+ #
56
+ # For this to work, a +const_missing+ hook is installed. When client
57
+ # code references the deprecated constant, the callback prints the
58
+ # message and constantizes the replacement.
59
+ #
60
+ # Caveat: If the deprecated constant name is reachable in a different
61
+ # namespace and Ruby constant lookup finds it, the hook won't be
62
+ # called and the deprecation won't work as intended. This may happen,
63
+ # for example, if an ancestor of the enclosing namespace has a
64
+ # constant with the same name. This is an unsupported edge case.
65
+ def deprecate_constant(old_constant_name, new_constant_path, deprecator:, message: nil)
44
66
  class_variable_set(:@@_deprecated_constants, {}) unless class_variable_defined?(:@@_deprecated_constants)
45
- class_variable_get(:@@_deprecated_constants)[const_name.to_s] = { new: new_constant, message: message, deprecator: deprecator }
67
+ class_variable_get(:@@_deprecated_constants)[old_constant_name.to_s] = { new: new_constant_path, message: message, deprecator: deprecator }
46
68
  end
47
69
  end
48
70
  base.singleton_class.prepend extension
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ class Deprecation
5
+ # A managed collection of deprecators. Configuration methods, such as
6
+ # #behavior=, affect all deprecators in the collection. Additionally, the
7
+ # #silence method silences all deprecators in the collection for the
8
+ # duration of a given block.
9
+ class Deprecators
10
+ def initialize
11
+ @options = {}
12
+ @deprecators = {}
13
+ end
14
+
15
+ # Returns a deprecator added to this collection via #[]=.
16
+ def [](name)
17
+ @deprecators[name]
18
+ end
19
+
20
+ # Adds a given +deprecator+ to this collection. The deprecator will be
21
+ # immediately configured with any options previously set on this
22
+ # collection.
23
+ #
24
+ # deprecators = ActiveSupport::Deprecation::Deprecators.new
25
+ # deprecators.debug = true
26
+ #
27
+ # foo_deprecator = ActiveSupport::Deprecation.new("2.0", "Foo")
28
+ # foo_deprecator.debug # => false
29
+ #
30
+ # deprecators[:foo] = foo_deprecator
31
+ # deprecators[:foo].debug # => true
32
+ # foo_deprecator.debug # => true
33
+ #
34
+ def []=(name, deprecator)
35
+ apply_options(deprecator)
36
+ @deprecators[name] = deprecator
37
+ end
38
+
39
+ # Iterates over all deprecators in this collection. If no block is given,
40
+ # returns an +Enumerator+.
41
+ def each(&block)
42
+ return to_enum(__method__) unless block
43
+ @deprecators.each_value(&block)
44
+ end
45
+
46
+ # Sets the silenced flag for all deprecators in this collection.
47
+ def silenced=(silenced)
48
+ set_option(:silenced, silenced)
49
+ end
50
+
51
+ # Sets the debug flag for all deprecators in this collection.
52
+ def debug=(debug)
53
+ set_option(:debug, debug)
54
+ end
55
+
56
+ # Sets the deprecation warning behavior for all deprecators in this
57
+ # collection.
58
+ #
59
+ # See ActiveSupport::Deprecation#behavior=.
60
+ def behavior=(behavior)
61
+ set_option(:behavior, behavior)
62
+ end
63
+
64
+ # Sets the disallowed deprecation warning behavior for all deprecators in
65
+ # this collection.
66
+ #
67
+ # See ActiveSupport::Deprecation#disallowed_behavior=.
68
+ def disallowed_behavior=(disallowed_behavior)
69
+ set_option(:disallowed_behavior, disallowed_behavior)
70
+ end
71
+
72
+ # Sets the disallowed deprecation warnings for all deprecators in this
73
+ # collection.
74
+ #
75
+ # See ActiveSupport::Deprecation#disallowed_warnings=.
76
+ def disallowed_warnings=(disallowed_warnings)
77
+ set_option(:disallowed_warnings, disallowed_warnings)
78
+ end
79
+
80
+ # Silences all deprecators in this collection for the duration of the
81
+ # given block.
82
+ #
83
+ # See ActiveSupport::Deprecation#silence.
84
+ def silence(&block)
85
+ each { |deprecator| deprecator.begin_silence }
86
+ block.call
87
+ ensure
88
+ each { |deprecator| deprecator.end_silence }
89
+ end
90
+
91
+ private
92
+ def set_option(name, value)
93
+ @options[name] = value
94
+ each { |deprecator| deprecator.public_send("#{name}=", value) }
95
+ end
96
+
97
+ def apply_options(deprecator)
98
+ @options.each do |name, value|
99
+ deprecator.public_send("#{name}=", value)
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -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
@@ -24,10 +24,9 @@ module ActiveSupport
24
24
 
25
25
  private
26
26
  def deprecation_disallowed?(message)
27
- disallowed = ActiveSupport::Deprecation.disallowed_warnings
28
27
  return false if explicitly_allowed?(message)
29
- return true if disallowed == :all
30
- disallowed.any? do |rule|
28
+ return true if disallowed_warnings == :all
29
+ message && disallowed_warnings.any? do |rule|
31
30
  case rule
32
31
  when String, Symbol
33
32
  message.include?(rule.to_s)
@@ -41,8 +40,7 @@ module ActiveSupport
41
40
  allowances = @explicitly_allowed_warnings.value
42
41
  return false unless allowances
43
42
  return true if allowances == :all
44
- allowances = [allowances] unless allowances.kind_of?(Array)
45
- allowances.any? do |rule|
43
+ message && Array(allowances).any? do |rule|
46
44
  case rule
47
45
  when String, Symbol
48
46
  message.include?(rule.to_s)
@@ -16,38 +16,21 @@ module ActiveSupport
16
16
  # def eee; end
17
17
  # end
18
18
  #
19
- # Using the default deprecator:
20
- # ActiveSupport::Deprecation.deprecate_methods(Fred, :aaa, bbb: :zzz, ccc: 'use Bar#ccc instead')
19
+ # deprecator = ActiveSupport::Deprecation.new('next-release', 'MyGem')
20
+ #
21
+ # deprecator.deprecate_methods(Fred, :aaa, bbb: :zzz, ccc: 'use Bar#ccc instead')
21
22
  # # => Fred
22
23
  #
23
24
  # Fred.new.aaa
24
- # # DEPRECATION WARNING: aaa is deprecated and will be removed from Rails 5.1. (called from irb_binding at (irb):10)
25
+ # # DEPRECATION WARNING: aaa is deprecated and will be removed from MyGem next-release. (called from irb_binding at (irb):10)
25
26
  # # => nil
26
27
  #
27
28
  # Fred.new.bbb
28
- # # DEPRECATION WARNING: bbb is deprecated and will be removed from Rails 5.1 (use zzz instead). (called from irb_binding at (irb):11)
29
+ # # DEPRECATION WARNING: bbb is deprecated and will be removed from MyGem next-release (use zzz instead). (called from irb_binding at (irb):11)
29
30
  # # => nil
30
31
  #
31
32
  # Fred.new.ccc
32
- # # DEPRECATION WARNING: ccc is deprecated and will be removed from Rails 5.1 (use Bar#ccc instead). (called from irb_binding at (irb):12)
33
- # # => nil
34
- #
35
- # Passing in a custom deprecator:
36
- # custom_deprecator = ActiveSupport::Deprecation.new('next-release', 'MyGem')
37
- # ActiveSupport::Deprecation.deprecate_methods(Fred, ddd: :zzz, deprecator: custom_deprecator)
38
- # # => [:ddd]
39
- #
40
- # Fred.new.ddd
41
- # DEPRECATION WARNING: ddd is deprecated and will be removed from MyGem next-release (use zzz instead). (called from irb_binding at (irb):15)
42
- # # => nil
43
- #
44
- # Using a custom deprecator directly:
45
- # custom_deprecator = ActiveSupport::Deprecation.new('next-release', 'MyGem')
46
- # custom_deprecator.deprecate_methods(Fred, eee: :zzz)
47
- # # => [:eee]
48
- #
49
- # Fred.new.eee
50
- # DEPRECATION WARNING: eee is deprecated and will be removed from MyGem next-release (use zzz instead). (called from irb_binding at (irb):18)
33
+ # # DEPRECATION WARNING: ccc is deprecated and will be removed from MyGem next-release (use Bar#ccc instead). (called from irb_binding at (irb):12)
51
34
  # # => nil
52
35
  def deprecate_methods(target_module, *method_names)
53
36
  options = method_names.extract_options!
@@ -3,7 +3,7 @@
3
3
  module ActiveSupport
4
4
  class Deprecation
5
5
  class DeprecationProxy # :nodoc:
6
- def self.new(*args, &block)
6
+ def self.new(*args, **kwargs, &block)
7
7
  object = args.first
8
8
 
9
9
  return object unless object
@@ -25,11 +25,10 @@ module ActiveSupport
25
25
  end
26
26
  end
27
27
 
28
- # DeprecatedObjectProxy transforms an object into a deprecated one. It
29
- # takes an object, a deprecation message and optionally a deprecator. The
30
- # deprecator defaults to +ActiveSupport::Deprecator+ if none is specified.
28
+ # DeprecatedObjectProxy transforms an object into a deprecated one. It takes an object, a deprecation message, and
29
+ # a deprecator.
31
30
  #
32
- # deprecated_object = ActiveSupport::Deprecation::DeprecatedObjectProxy.new(Object.new, "This object is now deprecated")
31
+ # deprecated_object = ActiveSupport::Deprecation::DeprecatedObjectProxy.new(Object.new, "This object is now deprecated", ActiveSupport::Deprecation.new)
33
32
  # # => #<Object:0x007fb9b34c34b0>
34
33
  #
35
34
  # deprecated_object.to_s
@@ -37,7 +36,7 @@ module ActiveSupport
37
36
  # (Backtrace)
38
37
  # # => "#<Object:0x007fb9b34c34b0>"
39
38
  class DeprecatedObjectProxy < DeprecationProxy
40
- def initialize(object, message, deprecator = ActiveSupport::Deprecation.instance)
39
+ def initialize(object, message, deprecator)
41
40
  @object = object
42
41
  @message = message
43
42
  @deprecator = deprecator
@@ -53,15 +52,15 @@ module ActiveSupport
53
52
  end
54
53
  end
55
54
 
56
- # DeprecatedInstanceVariableProxy transforms an instance variable into a
57
- # deprecated one. It takes an instance of a class, a method on that class
58
- # and an instance variable. It optionally takes a deprecator as the last
59
- # argument. The deprecator defaults to +ActiveSupport::Deprecator+ if none
60
- # is specified.
55
+ # DeprecatedInstanceVariableProxy transforms an instance variable into a deprecated one. It takes an instance of a
56
+ # class, a method on that class, an instance variable, and a deprecator as the last argument.
57
+ #
58
+ # Trying to use the deprecated instance variable will result in a deprecation warning, pointing to the method as a
59
+ # replacement.
61
60
  #
62
61
  # class Example
63
62
  # def initialize
64
- # @request = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(self, :request, :@request)
63
+ # @request = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(self, :request, :@request, ActiveSupport::Deprecation.new)
65
64
  # @_request = :special_request
66
65
  # end
67
66
  #
@@ -86,7 +85,7 @@ module ActiveSupport
86
85
  # example.request.to_s
87
86
  # # => "special_request"
88
87
  class DeprecatedInstanceVariableProxy < DeprecationProxy
89
- def initialize(instance, method, var = "@#{method}", deprecator = ActiveSupport::Deprecation.instance)
88
+ def initialize(instance, method, var = "@#{method}", deprecator:)
90
89
  @instance = instance
91
90
  @method = method
92
91
  @var = var
@@ -103,18 +102,16 @@ module ActiveSupport
103
102
  end
104
103
  end
105
104
 
106
- # DeprecatedConstantProxy transforms a constant into a deprecated one. It
107
- # takes the names of an old (deprecated) constant and of a new constant
108
- # (both in string form) and optionally a deprecator. The deprecator defaults
109
- # to +ActiveSupport::Deprecator+ if none is specified. The deprecated constant
110
- # now returns the value of the new one.
105
+ # DeprecatedConstantProxy transforms a constant into a deprecated one. It takes the full names of an old
106
+ # (deprecated) constant and of a new constant (both in string form) and a deprecator. The deprecated constant now
107
+ # returns the value of the new one.
111
108
  #
112
109
  # PLANETS = %w(mercury venus earth mars jupiter saturn uranus neptune pluto)
113
110
  #
114
111
  # # (In a later update, the original implementation of `PLANETS` has been removed.)
115
112
  #
116
113
  # PLANETS_POST_2006 = %w(mercury venus earth mars jupiter saturn uranus neptune)
117
- # PLANETS = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('PLANETS', 'PLANETS_POST_2006')
114
+ # PLANETS = ActiveSupport::Deprecation::DeprecatedConstantProxy.new("PLANETS", "PLANETS_POST_2006", ActiveSupport::Deprecation.new)
118
115
  #
119
116
  # PLANETS.map { |planet| planet.capitalize }
120
117
  # # => DEPRECATION WARNING: PLANETS is deprecated! Use PLANETS_POST_2006 instead.
@@ -128,7 +125,7 @@ module ActiveSupport
128
125
  super
129
126
  end
130
127
 
131
- def initialize(old_const, new_const, deprecator = ActiveSupport::Deprecation.instance, message: "#{old_const} is deprecated! Use #{new_const} instead.")
128
+ def initialize(old_const, new_const, deprecator, message: "#{old_const} is deprecated! Use #{new_const} instead.")
132
129
  Kernel.require "active_support/inflector/methods"
133
130
 
134
131
  @old_const = old_const
@@ -158,6 +155,21 @@ module ActiveSupport
158
155
  target.class
159
156
  end
160
157
 
158
+ def append_features(base)
159
+ @deprecator.warn(@message, caller_locations)
160
+ base.include(target)
161
+ end
162
+
163
+ def prepend_features(base)
164
+ @deprecator.warn(@message, caller_locations)
165
+ base.prepend(target)
166
+ end
167
+
168
+ def extended(base)
169
+ @deprecator.warn(@message, caller_locations)
170
+ base.extend(target)
171
+ end
172
+
161
173
  private
162
174
  def target
163
175
  ActiveSupport::Inflector.constantize(@new_const.to_s)
@@ -168,9 +180,9 @@ module ActiveSupport
168
180
  target.const_get(name)
169
181
  end
170
182
 
171
- def method_missing(called, *args, &block)
183
+ def method_missing(...)
172
184
  @deprecator.warn(@message, caller_locations)
173
- target.__send__(called, *args, &block)
185
+ target.__send__(...)
174
186
  end
175
187
  end
176
188
  end