activesupport 7.0.4 → 7.1.5.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 (189) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1076 -230
  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 +2 -0
  7. data/lib/active_support/backtrace_cleaner.rb +30 -5
  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 +37 -10
  14. data/lib/active_support/cache/mem_cache_store.rb +100 -76
  15. data/lib/active_support/cache/memory_store.rb +78 -24
  16. data/lib/active_support/cache/null_store.rb +6 -0
  17. data/lib/active_support/cache/redis_cache_store.rb +153 -141
  18. data/lib/active_support/cache/serializer_with_fallback.rb +175 -0
  19. data/lib/active_support/cache/strategy/local_cache.rb +29 -14
  20. data/lib/active_support/cache.rb +333 -253
  21. data/lib/active_support/callbacks.rb +44 -21
  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 +10 -0
  27. data/lib/active_support/core_ext/array/conversions.rb +2 -1
  28. data/lib/active_support/core_ext/array.rb +0 -1
  29. data/lib/active_support/core_ext/class/subclasses.rb +13 -10
  30. data/lib/active_support/core_ext/date/calculations.rb +15 -0
  31. data/lib/active_support/core_ext/date/conversions.rb +2 -1
  32. data/lib/active_support/core_ext/date.rb +0 -1
  33. data/lib/active_support/core_ext/date_and_time/calculations.rb +10 -0
  34. data/lib/active_support/core_ext/date_time/calculations.rb +4 -0
  35. data/lib/active_support/core_ext/date_time/conversions.rb +6 -2
  36. data/lib/active_support/core_ext/date_time.rb +0 -1
  37. data/lib/active_support/core_ext/digest/uuid.rb +1 -10
  38. data/lib/active_support/core_ext/enumerable.rb +8 -75
  39. data/lib/active_support/core_ext/erb/util.rb +196 -0
  40. data/lib/active_support/core_ext/hash/conversions.rb +1 -1
  41. data/lib/active_support/core_ext/hash/deep_merge.rb +22 -14
  42. data/lib/active_support/core_ext/hash/deep_transform_values.rb +3 -3
  43. data/lib/active_support/core_ext/hash/keys.rb +3 -3
  44. data/lib/active_support/core_ext/integer/inflections.rb +12 -12
  45. data/lib/active_support/core_ext/module/attribute_accessors.rb +6 -0
  46. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +34 -16
  47. data/lib/active_support/core_ext/module/concerning.rb +6 -6
  48. data/lib/active_support/core_ext/module/delegation.rb +81 -37
  49. data/lib/active_support/core_ext/module/deprecation.rb +15 -12
  50. data/lib/active_support/core_ext/module/introspection.rb +0 -1
  51. data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
  52. data/lib/active_support/core_ext/numeric/conversions.rb +2 -0
  53. data/lib/active_support/core_ext/numeric.rb +0 -1
  54. data/lib/active_support/core_ext/object/deep_dup.rb +16 -0
  55. data/lib/active_support/core_ext/object/duplicable.rb +25 -16
  56. data/lib/active_support/core_ext/object/inclusion.rb +13 -5
  57. data/lib/active_support/core_ext/object/instance_variables.rb +22 -12
  58. data/lib/active_support/core_ext/object/json.rb +16 -6
  59. data/lib/active_support/core_ext/object/to_query.rb +0 -2
  60. data/lib/active_support/core_ext/object/with.rb +44 -0
  61. data/lib/active_support/core_ext/object/with_options.rb +9 -9
  62. data/lib/active_support/core_ext/object.rb +1 -0
  63. data/lib/active_support/core_ext/pathname/blank.rb +16 -0
  64. data/lib/active_support/core_ext/pathname/existence.rb +2 -0
  65. data/lib/active_support/core_ext/pathname.rb +1 -0
  66. data/lib/active_support/core_ext/range/conversions.rb +28 -7
  67. data/lib/active_support/core_ext/range/overlap.rb +40 -0
  68. data/lib/active_support/core_ext/range.rb +1 -2
  69. data/lib/active_support/core_ext/securerandom.rb +24 -12
  70. data/lib/active_support/core_ext/string/filters.rb +20 -14
  71. data/lib/active_support/core_ext/string/indent.rb +1 -1
  72. data/lib/active_support/core_ext/string/inflections.rb +16 -9
  73. data/lib/active_support/core_ext/string/output_safety.rb +42 -174
  74. data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
  75. data/lib/active_support/core_ext/time/calculations.rb +22 -2
  76. data/lib/active_support/core_ext/time/conversions.rb +2 -2
  77. data/lib/active_support/core_ext/time/zones.rb +7 -8
  78. data/lib/active_support/core_ext/time.rb +0 -1
  79. data/lib/active_support/current_attributes.rb +15 -6
  80. data/lib/active_support/deep_mergeable.rb +53 -0
  81. data/lib/active_support/dependencies/autoload.rb +17 -12
  82. data/lib/active_support/deprecation/behaviors.rb +65 -42
  83. data/lib/active_support/deprecation/constant_accessor.rb +5 -4
  84. data/lib/active_support/deprecation/deprecators.rb +104 -0
  85. data/lib/active_support/deprecation/disallowed.rb +6 -8
  86. data/lib/active_support/deprecation/instance_delegator.rb +31 -4
  87. data/lib/active_support/deprecation/method_wrappers.rb +6 -23
  88. data/lib/active_support/deprecation/proxy_wrappers.rb +37 -22
  89. data/lib/active_support/deprecation/reporting.rb +43 -26
  90. data/lib/active_support/deprecation.rb +32 -5
  91. data/lib/active_support/deprecator.rb +7 -0
  92. data/lib/active_support/descendants_tracker.rb +104 -132
  93. data/lib/active_support/duration/iso8601_serializer.rb +0 -2
  94. data/lib/active_support/duration.rb +2 -1
  95. data/lib/active_support/encrypted_configuration.rb +63 -11
  96. data/lib/active_support/encrypted_file.rb +16 -12
  97. data/lib/active_support/environment_inquirer.rb +22 -2
  98. data/lib/active_support/error_reporter/test_helper.rb +15 -0
  99. data/lib/active_support/error_reporter.rb +121 -35
  100. data/lib/active_support/evented_file_update_checker.rb +17 -2
  101. data/lib/active_support/execution_wrapper.rb +4 -4
  102. data/lib/active_support/file_update_checker.rb +4 -2
  103. data/lib/active_support/fork_tracker.rb +10 -2
  104. data/lib/active_support/gem_version.rb +4 -4
  105. data/lib/active_support/gzip.rb +2 -0
  106. data/lib/active_support/hash_with_indifferent_access.rb +35 -17
  107. data/lib/active_support/html_safe_translation.rb +16 -6
  108. data/lib/active_support/i18n.rb +1 -1
  109. data/lib/active_support/i18n_railtie.rb +20 -13
  110. data/lib/active_support/inflector/inflections.rb +2 -0
  111. data/lib/active_support/inflector/methods.rb +28 -18
  112. data/lib/active_support/inflector/transliterate.rb +3 -1
  113. data/lib/active_support/isolated_execution_state.rb +26 -22
  114. data/lib/active_support/json/decoding.rb +2 -1
  115. data/lib/active_support/json/encoding.rb +25 -43
  116. data/lib/active_support/key_generator.rb +9 -1
  117. data/lib/active_support/lazy_load_hooks.rb +7 -5
  118. data/lib/active_support/locale/en.yml +2 -0
  119. data/lib/active_support/log_subscriber.rb +85 -33
  120. data/lib/active_support/logger.rb +9 -60
  121. data/lib/active_support/logger_thread_safe_level.rb +10 -24
  122. data/lib/active_support/message_encryptor.rb +197 -53
  123. data/lib/active_support/message_encryptors.rb +141 -0
  124. data/lib/active_support/message_pack/cache_serializer.rb +23 -0
  125. data/lib/active_support/message_pack/extensions.rb +292 -0
  126. data/lib/active_support/message_pack/serializer.rb +63 -0
  127. data/lib/active_support/message_pack.rb +50 -0
  128. data/lib/active_support/message_verifier.rb +212 -93
  129. data/lib/active_support/message_verifiers.rb +135 -0
  130. data/lib/active_support/messages/codec.rb +65 -0
  131. data/lib/active_support/messages/metadata.rb +111 -45
  132. data/lib/active_support/messages/rotation_coordinator.rb +93 -0
  133. data/lib/active_support/messages/rotator.rb +34 -32
  134. data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
  135. data/lib/active_support/multibyte/chars.rb +2 -0
  136. data/lib/active_support/multibyte/unicode.rb +9 -37
  137. data/lib/active_support/notifications/fanout.rb +245 -81
  138. data/lib/active_support/notifications/instrumenter.rb +87 -22
  139. data/lib/active_support/notifications.rb +3 -3
  140. data/lib/active_support/number_helper/number_converter.rb +14 -5
  141. data/lib/active_support/number_helper/number_to_currency_converter.rb +6 -6
  142. data/lib/active_support/number_helper/number_to_human_size_converter.rb +3 -3
  143. data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -0
  144. data/lib/active_support/number_helper.rb +379 -317
  145. data/lib/active_support/ordered_hash.rb +3 -3
  146. data/lib/active_support/ordered_options.rb +14 -0
  147. data/lib/active_support/parameter_filter.rb +103 -84
  148. data/lib/active_support/proxy_object.rb +2 -0
  149. data/lib/active_support/railtie.rb +33 -21
  150. data/lib/active_support/reloader.rb +12 -4
  151. data/lib/active_support/rescuable.rb +2 -0
  152. data/lib/active_support/secure_compare_rotator.rb +16 -9
  153. data/lib/active_support/string_inquirer.rb +3 -1
  154. data/lib/active_support/subscriber.rb +9 -27
  155. data/lib/active_support/syntax_error_proxy.rb +60 -0
  156. data/lib/active_support/tagged_logging.rb +64 -24
  157. data/lib/active_support/test_case.rb +153 -6
  158. data/lib/active_support/testing/assertions.rb +26 -10
  159. data/lib/active_support/testing/autorun.rb +0 -2
  160. data/lib/active_support/testing/constant_stubbing.rb +32 -0
  161. data/lib/active_support/testing/deprecation.rb +25 -25
  162. data/lib/active_support/testing/error_reporter_assertions.rb +107 -0
  163. data/lib/active_support/testing/isolation.rb +29 -28
  164. data/lib/active_support/testing/method_call_assertions.rb +21 -8
  165. data/lib/active_support/testing/parallelize_executor.rb +8 -3
  166. data/lib/active_support/testing/setup_and_teardown.rb +2 -0
  167. data/lib/active_support/testing/stream.rb +1 -1
  168. data/lib/active_support/testing/strict_warnings.rb +39 -0
  169. data/lib/active_support/testing/time_helpers.rb +37 -15
  170. data/lib/active_support/time_with_zone.rb +8 -37
  171. data/lib/active_support/values/time_zone.rb +18 -7
  172. data/lib/active_support/version.rb +1 -1
  173. data/lib/active_support/xml_mini/jdom.rb +3 -10
  174. data/lib/active_support/xml_mini/nokogiri.rb +1 -1
  175. data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
  176. data/lib/active_support/xml_mini/rexml.rb +1 -1
  177. data/lib/active_support/xml_mini.rb +2 -2
  178. data/lib/active_support.rb +14 -3
  179. metadata +148 -19
  180. data/lib/active_support/core_ext/array/deprecated_conversions.rb +0 -25
  181. data/lib/active_support/core_ext/date/deprecated_conversions.rb +0 -26
  182. data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +0 -22
  183. data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +0 -60
  184. data/lib/active_support/core_ext/range/deprecated_conversions.rb +0 -26
  185. data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -7
  186. data/lib/active_support/core_ext/range/overlaps.rb +0 -10
  187. data/lib/active_support/core_ext/time/deprecated_conversions.rb +0 -22
  188. data/lib/active_support/core_ext/uri.rb +0 -5
  189. data/lib/active_support/per_thread_registry.rb +0 -65
@@ -5,6 +5,8 @@ require "active_support/core_ext/enumerable"
5
5
  require "active_support/core_ext/module/delegation"
6
6
 
7
7
  module ActiveSupport
8
+ # = Current Attributes
9
+ #
8
10
  # Abstract super class that provides a thread-isolated attributes singleton, which resets automatically
9
11
  # before and after each request. This allows you to keep all the per-request attributes easily
10
12
  # available to the whole system.
@@ -90,6 +92,8 @@ module ActiveSupport
90
92
  include ActiveSupport::Callbacks
91
93
  define_callbacks :reset
92
94
 
95
+ INVALID_ATTRIBUTE_NAMES = [:set, :reset, :resets, :instance, :before_reset, :after_reset, :reset_all, :clear_all] # :nodoc:
96
+
93
97
  class << self
94
98
  # Returns singleton instance for this class in this thread. If none exists, one is created.
95
99
  def instance
@@ -98,6 +102,11 @@ module ActiveSupport
98
102
 
99
103
  # Declares one or more attributes that will be given both class and instance accessor methods.
100
104
  def attribute(*names)
105
+ invalid_attribute_names = names.map(&:to_sym) & INVALID_ATTRIBUTE_NAMES
106
+ if invalid_attribute_names.any?
107
+ raise ArgumentError, "Restricted attribute names: #{invalid_attribute_names.join(", ")}"
108
+ end
109
+
101
110
  ActiveSupport::CodeGenerator.batch(generated_attribute_methods, __FILE__, __LINE__) do |owner|
102
111
  names.each do |name|
103
112
  owner.define_cached_method(name, namespace: :current_attributes) do |batch|
@@ -133,14 +142,14 @@ module ActiveSupport
133
142
  end
134
143
  end
135
144
 
136
- # Calls this block before #reset is called on the instance. Used for resetting external collaborators that depend on current values.
137
- def before_reset(&block)
138
- set_callback :reset, :before, &block
145
+ # Calls this callback before #reset is called on the instance. Used for resetting external collaborators that depend on current values.
146
+ def before_reset(*methods, &block)
147
+ set_callback :reset, :before, *methods, &block
139
148
  end
140
149
 
141
- # Calls this block after #reset is called on the instance. Used for resetting external collaborators, like Time.zone.
142
- def resets(&block)
143
- set_callback :reset, :after, &block
150
+ # Calls this callback after #reset is called on the instance. Used for resetting external collaborators, like Time.zone.
151
+ def resets(*methods, &block)
152
+ set_callback :reset, :after, *methods, &block
144
153
  end
145
154
  alias_method :after_reset, :resets
146
155
 
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ # Provides +deep_merge+ and +deep_merge!+ methods. Expects the including class
5
+ # to provide a <tt>merge!(other, &block)</tt> method.
6
+ module DeepMergeable # :nodoc:
7
+ # Returns a new instance with the values from +other+ merged recursively.
8
+ #
9
+ # class Hash
10
+ # include ActiveSupport::DeepMergeable
11
+ # end
12
+ #
13
+ # hash_1 = { a: true, b: { c: [1, 2, 3] } }
14
+ # hash_2 = { a: false, b: { x: [3, 4, 5] } }
15
+ #
16
+ # hash_1.deep_merge(hash_2)
17
+ # # => { a: false, b: { c: [1, 2, 3], x: [3, 4, 5] } }
18
+ #
19
+ # A block can be provided to merge non-<tt>DeepMergeable</tt> values:
20
+ #
21
+ # hash_1 = { a: 100, b: 200, c: { c1: 100 } }
22
+ # hash_2 = { b: 250, c: { c1: 200 } }
23
+ #
24
+ # hash_1.deep_merge(hash_2) do |key, this_val, other_val|
25
+ # this_val + other_val
26
+ # end
27
+ # # => { a: 100, b: 450, c: { c1: 300 } }
28
+ #
29
+ def deep_merge(other, &block)
30
+ dup.deep_merge!(other, &block)
31
+ end
32
+
33
+ # Same as #deep_merge, but modifies +self+.
34
+ def deep_merge!(other, &block)
35
+ merge!(other) do |key, this_val, other_val|
36
+ if this_val.is_a?(DeepMergeable) && this_val.deep_merge?(other_val)
37
+ this_val.deep_merge(other_val, &block)
38
+ elsif block_given?
39
+ block.call(key, this_val, other_val)
40
+ else
41
+ other_val
42
+ end
43
+ end
44
+ end
45
+
46
+ # Returns true if +other+ can be deep merged into +self+. Classes may
47
+ # override this method to restrict or expand the domain of deep mergeable
48
+ # values. Defaults to checking that +other+ is of type +self.class+.
49
+ def deep_merge?(other)
50
+ other.is_a?(self.class)
51
+ end
52
+ end
53
+ end
@@ -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:
@@ -26,11 +28,14 @@ module ActiveSupport
26
28
  # MyLib.eager_load!
27
29
  module Autoload
28
30
  def self.extended(base) # :nodoc:
29
- base.class_eval do
30
- @_autoloads = {}
31
- @_under_path = nil
32
- @_at_path = nil
33
- @_eager_autoload = false
31
+ if RUBY_VERSION < "3"
32
+ base.class_eval do
33
+ @_autoloads = nil
34
+ @_under_path = nil
35
+ @_at_path = nil
36
+ @_eager_autoload = false
37
+ @_eagerloaded_constants = nil
38
+ end
34
39
  end
35
40
  end
36
41
 
@@ -41,7 +46,8 @@ module ActiveSupport
41
46
  end
42
47
 
43
48
  if @_eager_autoload
44
- @_autoloads[const_name] = path
49
+ @_eagerloaded_constants ||= []
50
+ @_eagerloaded_constants << const_name
45
51
  end
46
52
 
47
53
  super const_name, path
@@ -69,11 +75,10 @@ module ActiveSupport
69
75
  end
70
76
 
71
77
  def eager_load!
72
- @_autoloads.each_value { |file| require file }
73
- end
74
-
75
- def autoloads
76
- @_autoloads
78
+ if @_eagerloaded_constants
79
+ @_eagerloaded_constants.each { |const_name| const_get(const_name) }
80
+ @_eagerloaded_constants = nil
81
+ end
77
82
  end
78
83
  end
79
84
  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.respond_to?(:arity) && behavior.arity == 2
118
- -> message, callstack, _, _ { behavior.call(message, callstack) }
119
- else
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
120
135
  behavior
136
+ else
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
@@ -6,8 +6,7 @@ module ActiveSupport
6
6
  # hooking +const_missing+.
7
7
  #
8
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.
9
+ # (both in string form) and a deprecator.
11
10
  #
12
11
  # The deprecated constant now returns the same object as the new one rather
13
12
  # than a proxy object, so it can be used transparently in +rescue+ blocks
@@ -19,7 +18,7 @@ module ActiveSupport
19
18
  #
20
19
  # PLANETS_POST_2006 = %w(mercury venus earth mars jupiter saturn uranus neptune)
21
20
  # include ActiveSupport::Deprecation::DeprecatedConstantAccessor
22
- # deprecate_constant 'PLANETS', 'PLANETS_POST_2006'
21
+ # deprecate_constant 'PLANETS', 'PLANETS_POST_2006', deprecator: ActiveSupport::Deprecation.new
23
22
  #
24
23
  # PLANETS.map { |planet| planet.capitalize }
25
24
  # # => DEPRECATION WARNING: PLANETS is deprecated! Use PLANETS_POST_2006 instead.
@@ -40,7 +39,9 @@ module ActiveSupport
40
39
  super
41
40
  end
42
41
 
43
- def deprecate_constant(const_name, new_constant, message: nil, deprecator: ActiveSupport::Deprecation.instance)
42
+ def deprecate_constant(const_name, new_constant, message: nil, deprecator: nil)
43
+ ActiveSupport.deprecator.warn("DeprecatedConstantAccessor.deprecate_constant without a deprecator is deprecated") unless deprecator
44
+ deprecator ||= ActiveSupport::Deprecation._instance
44
45
  class_variable_set(:@@_deprecated_constants, {}) unless class_variable_defined?(:@@_deprecated_constants)
45
46
  class_variable_get(:@@_deprecated_constants)[const_name.to_s] = { new: new_constant, message: message, deprecator: deprecator }
46
47
  end
@@ -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)
@@ -1,24 +1,51 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/module/delegation"
4
-
5
3
  module ActiveSupport
6
4
  class Deprecation
7
5
  module InstanceDelegator # :nodoc:
8
6
  def self.included(base)
9
7
  base.extend(ClassMethods)
10
8
  base.singleton_class.prepend(OverrideDelegators)
11
- base.public_class_method :new
12
9
  end
13
10
 
14
11
  module ClassMethods # :nodoc:
12
+ MUTEX = Mutex.new
13
+ private_constant :MUTEX
14
+
15
15
  def include(included_module)
16
16
  included_module.instance_methods.each { |m| method_added(m) }
17
17
  super
18
18
  end
19
19
 
20
20
  def method_added(method_name)
21
- singleton_class.delegate(method_name, to: :instance)
21
+ use_instead =
22
+ case method_name
23
+ when :silence, :behavior=, :disallowed_behavior=, :disallowed_warnings=, :silenced=, :debug=
24
+ target = "(defined?(Rails.application.deprecators) ? Rails.application.deprecators : ActiveSupport::Deprecation._instance)"
25
+ "Rails.application.deprecators.#{method_name}"
26
+ when :warn, :deprecate_methods, :gem_name, :gem_name=, :deprecation_horizon, :deprecation_horizon=
27
+ "your own Deprecation object"
28
+ else
29
+ "Rails.application.deprecators[framework].#{method_name} where framework is for example :active_record"
30
+ end
31
+ args = /[^\]]=\z/.match?(method_name) ? "arg" : "..."
32
+ target ||= "ActiveSupport::Deprecation._instance"
33
+ singleton_class.module_eval <<~RUBY, __FILE__, __LINE__ + 1
34
+ def #{method_name}(#{args})
35
+ #{target}.#{method_name}(#{args})
36
+ ensure
37
+ ActiveSupport.deprecator.warn("Calling #{method_name} on ActiveSupport::Deprecation is deprecated and will be removed from Rails (use #{use_instead} instead)")
38
+ end
39
+ RUBY
40
+ end
41
+
42
+ def instance
43
+ ActiveSupport.deprecator.warn("ActiveSupport::Deprecation.instance is deprecated (use your own Deprecation object)")
44
+ _instance
45
+ end
46
+
47
+ def _instance
48
+ @_instance ||= MUTEX.synchronize { @_instance ||= new }
22
49
  end
23
50
  end
24
51
 
@@ -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!