activesupport 5.0.0 → 6.1.0

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 (268) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +343 -590
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +5 -4
  5. data/lib/active_support/actionable_error.rb +48 -0
  6. data/lib/active_support/all.rb +5 -3
  7. data/lib/active_support/array_inquirer.rb +11 -5
  8. data/lib/active_support/backtrace_cleaner.rb +33 -5
  9. data/lib/active_support/benchmarkable.rb +5 -3
  10. data/lib/active_support/builder.rb +3 -1
  11. data/lib/active_support/cache/file_store.rb +45 -53
  12. data/lib/active_support/cache/mem_cache_store.rb +81 -79
  13. data/lib/active_support/cache/memory_store.rb +69 -41
  14. data/lib/active_support/cache/null_store.rb +11 -4
  15. data/lib/active_support/cache/redis_cache_store.rb +493 -0
  16. data/lib/active_support/cache/strategy/local_cache.rb +74 -37
  17. data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
  18. data/lib/active_support/cache.rb +332 -161
  19. data/lib/active_support/callbacks.rb +657 -586
  20. data/lib/active_support/concern.rb +79 -6
  21. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +35 -0
  22. data/lib/active_support/concurrency/share_lock.rb +59 -19
  23. data/lib/active_support/configurable.rb +15 -17
  24. data/lib/active_support/configuration_file.rb +46 -0
  25. data/lib/active_support/core_ext/array/access.rb +21 -7
  26. data/lib/active_support/core_ext/array/conversions.rb +20 -18
  27. data/lib/active_support/core_ext/array/extract.rb +21 -0
  28. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  29. data/lib/active_support/core_ext/array/grouping.rb +3 -1
  30. data/lib/active_support/core_ext/array/inquiry.rb +3 -1
  31. data/lib/active_support/core_ext/array/wrap.rb +2 -0
  32. data/lib/active_support/core_ext/array.rb +9 -7
  33. data/lib/active_support/core_ext/benchmark.rb +5 -3
  34. data/lib/active_support/core_ext/big_decimal/conversions.rb +6 -6
  35. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  36. data/lib/active_support/core_ext/class/attribute.rb +52 -49
  37. data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
  38. data/lib/active_support/core_ext/class/subclasses.rb +18 -26
  39. data/lib/active_support/core_ext/class.rb +4 -2
  40. data/lib/active_support/core_ext/date/acts_like.rb +3 -1
  41. data/lib/active_support/core_ext/date/blank.rb +3 -1
  42. data/lib/active_support/core_ext/date/calculations.rb +16 -13
  43. data/lib/active_support/core_ext/date/conversions.rb +23 -21
  44. data/lib/active_support/core_ext/date/zones.rb +4 -2
  45. data/lib/active_support/core_ext/date.rb +7 -5
  46. data/lib/active_support/core_ext/date_and_time/calculations.rb +82 -53
  47. data/lib/active_support/core_ext/date_and_time/compatibility.rb +18 -5
  48. data/lib/active_support/core_ext/date_and_time/zones.rb +9 -9
  49. data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
  50. data/lib/active_support/core_ext/date_time/blank.rb +3 -1
  51. data/lib/active_support/core_ext/date_time/calculations.rb +23 -11
  52. data/lib/active_support/core_ext/date_time/compatibility.rb +15 -2
  53. data/lib/active_support/core_ext/date_time/conversions.rb +14 -13
  54. data/lib/active_support/core_ext/date_time.rb +7 -5
  55. data/lib/active_support/core_ext/digest/uuid.rb +7 -5
  56. data/lib/active_support/core_ext/digest.rb +3 -0
  57. data/lib/active_support/core_ext/enumerable.rb +165 -29
  58. data/lib/active_support/core_ext/file/atomic.rb +7 -5
  59. data/lib/active_support/core_ext/file.rb +3 -1
  60. data/lib/active_support/core_ext/hash/conversions.rb +40 -39
  61. data/lib/active_support/core_ext/hash/deep_merge.rb +8 -12
  62. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  63. data/lib/active_support/core_ext/hash/except.rb +4 -2
  64. data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -2
  65. data/lib/active_support/core_ext/hash/keys.rb +9 -36
  66. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  67. data/lib/active_support/core_ext/hash/slice.rb +8 -29
  68. data/lib/active_support/core_ext/hash.rb +10 -9
  69. data/lib/active_support/core_ext/integer/inflections.rb +3 -1
  70. data/lib/active_support/core_ext/integer/multiple.rb +3 -1
  71. data/lib/active_support/core_ext/integer/time.rb +11 -18
  72. data/lib/active_support/core_ext/integer.rb +5 -3
  73. data/lib/active_support/core_ext/kernel/concern.rb +3 -1
  74. data/lib/active_support/core_ext/kernel/reporting.rb +3 -1
  75. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  76. data/lib/active_support/core_ext/kernel.rb +5 -4
  77. data/lib/active_support/core_ext/load_error.rb +2 -23
  78. data/lib/active_support/core_ext/marshal.rb +6 -2
  79. data/lib/active_support/core_ext/module/aliasing.rb +5 -48
  80. data/lib/active_support/core_ext/module/anonymous.rb +2 -0
  81. data/lib/active_support/core_ext/module/attr_internal.rb +7 -5
  82. data/lib/active_support/core_ext/module/attribute_accessors.rb +53 -59
  83. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +31 -24
  84. data/lib/active_support/core_ext/module/concerning.rb +16 -11
  85. data/lib/active_support/core_ext/module/delegation.rb +159 -44
  86. data/lib/active_support/core_ext/module/deprecation.rb +2 -0
  87. data/lib/active_support/core_ext/module/introspection.rb +23 -26
  88. data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
  89. data/lib/active_support/core_ext/module/remove_method.rb +5 -23
  90. data/lib/active_support/core_ext/module.rb +13 -12
  91. data/lib/active_support/core_ext/name_error.rb +36 -2
  92. data/lib/active_support/core_ext/numeric/bytes.rb +2 -0
  93. data/lib/active_support/core_ext/numeric/conversions.rb +129 -134
  94. data/lib/active_support/core_ext/numeric/time.rb +18 -26
  95. data/lib/active_support/core_ext/numeric.rb +5 -4
  96. data/lib/active_support/core_ext/object/acts_like.rb +12 -1
  97. data/lib/active_support/core_ext/object/blank.rb +14 -2
  98. data/lib/active_support/core_ext/object/conversions.rb +6 -4
  99. data/lib/active_support/core_ext/object/deep_dup.rb +4 -2
  100. data/lib/active_support/core_ext/object/duplicable.rb +13 -62
  101. data/lib/active_support/core_ext/object/inclusion.rb +3 -1
  102. data/lib/active_support/core_ext/object/instance_variables.rb +2 -0
  103. data/lib/active_support/core_ext/object/json.rb +42 -15
  104. data/lib/active_support/core_ext/object/to_param.rb +3 -1
  105. data/lib/active_support/core_ext/object/to_query.rb +10 -5
  106. data/lib/active_support/core_ext/object/try.rb +20 -8
  107. data/lib/active_support/core_ext/object/with_options.rb +15 -2
  108. data/lib/active_support/core_ext/object.rb +14 -12
  109. data/lib/active_support/core_ext/range/compare_range.rb +82 -0
  110. data/lib/active_support/core_ext/range/conversions.rb +35 -25
  111. data/lib/active_support/core_ext/range/each.rb +5 -2
  112. data/lib/active_support/core_ext/range/include_time_with_zone.rb +28 -0
  113. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  114. data/lib/active_support/core_ext/range.rb +7 -4
  115. data/lib/active_support/core_ext/regexp.rb +10 -1
  116. data/lib/active_support/core_ext/securerandom.rb +28 -6
  117. data/lib/active_support/core_ext/string/access.rb +9 -18
  118. data/lib/active_support/core_ext/string/behavior.rb +2 -0
  119. data/lib/active_support/core_ext/string/conversions.rb +5 -2
  120. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  121. data/lib/active_support/core_ext/string/filters.rb +47 -4
  122. data/lib/active_support/core_ext/string/indent.rb +6 -4
  123. data/lib/active_support/core_ext/string/inflections.rb +78 -29
  124. data/lib/active_support/core_ext/string/inquiry.rb +4 -1
  125. data/lib/active_support/core_ext/string/multibyte.rb +10 -5
  126. data/lib/active_support/core_ext/string/output_safety.rb +86 -31
  127. data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
  128. data/lib/active_support/core_ext/string/strip.rb +5 -1
  129. data/lib/active_support/core_ext/string/zones.rb +4 -2
  130. data/lib/active_support/core_ext/string.rb +15 -13
  131. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
  132. data/lib/active_support/core_ext/symbol.rb +3 -0
  133. data/lib/active_support/core_ext/time/acts_like.rb +3 -1
  134. data/lib/active_support/core_ext/time/calculations.rb +117 -45
  135. data/lib/active_support/core_ext/time/compatibility.rb +13 -2
  136. data/lib/active_support/core_ext/time/conversions.rb +18 -12
  137. data/lib/active_support/core_ext/time/zones.rb +9 -7
  138. data/lib/active_support/core_ext/time.rb +7 -5
  139. data/lib/active_support/core_ext/uri.rb +12 -7
  140. data/lib/active_support/core_ext.rb +3 -2
  141. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  142. data/lib/active_support/current_attributes.rb +208 -0
  143. data/lib/active_support/dependencies/autoload.rb +2 -0
  144. data/lib/active_support/dependencies/interlock.rb +7 -1
  145. data/lib/active_support/dependencies/zeitwerk_integration.rb +117 -0
  146. data/lib/active_support/dependencies.rb +172 -98
  147. data/lib/active_support/deprecation/behaviors.rb +45 -13
  148. data/lib/active_support/deprecation/constant_accessor.rb +52 -0
  149. data/lib/active_support/deprecation/disallowed.rb +56 -0
  150. data/lib/active_support/deprecation/instance_delegator.rb +16 -2
  151. data/lib/active_support/deprecation/method_wrappers.rb +32 -17
  152. data/lib/active_support/deprecation/proxy_wrappers.rb +35 -7
  153. data/lib/active_support/deprecation/reporting.rb +61 -16
  154. data/lib/active_support/deprecation.rb +17 -9
  155. data/lib/active_support/descendants_tracker.rb +61 -9
  156. data/lib/active_support/digest.rb +20 -0
  157. data/lib/active_support/duration/iso8601_parser.rb +67 -66
  158. data/lib/active_support/duration/iso8601_serializer.rb +25 -17
  159. data/lib/active_support/duration.rb +349 -46
  160. data/lib/active_support/encrypted_configuration.rb +45 -0
  161. data/lib/active_support/encrypted_file.rb +117 -0
  162. data/lib/active_support/environment_inquirer.rb +20 -0
  163. data/lib/active_support/evented_file_update_checker.rb +88 -112
  164. data/lib/active_support/execution_wrapper.rb +25 -13
  165. data/lib/active_support/executor.rb +3 -1
  166. data/lib/active_support/file_update_checker.rb +56 -51
  167. data/lib/active_support/fork_tracker.rb +62 -0
  168. data/lib/active_support/gem_version.rb +4 -2
  169. data/lib/active_support/gzip.rb +7 -5
  170. data/lib/active_support/hash_with_indifferent_access.rb +153 -49
  171. data/lib/active_support/i18n.rb +9 -6
  172. data/lib/active_support/i18n_railtie.rb +30 -20
  173. data/lib/active_support/inflections.rb +13 -11
  174. data/lib/active_support/inflector/inflections.rb +28 -15
  175. data/lib/active_support/inflector/methods.rb +120 -109
  176. data/lib/active_support/inflector/transliterate.rb +60 -25
  177. data/lib/active_support/inflector.rb +7 -5
  178. data/lib/active_support/json/decoding.rb +30 -29
  179. data/lib/active_support/json/encoding.rb +22 -11
  180. data/lib/active_support/json.rb +4 -2
  181. data/lib/active_support/key_generator.rb +6 -36
  182. data/lib/active_support/lazy_load_hooks.rb +53 -20
  183. data/lib/active_support/locale/en.rb +33 -0
  184. data/lib/active_support/locale/en.yml +7 -3
  185. data/lib/active_support/log_subscriber/test_helper.rb +11 -9
  186. data/lib/active_support/log_subscriber.rb +51 -18
  187. data/lib/active_support/logger.rb +9 -22
  188. data/lib/active_support/logger_silence.rb +14 -21
  189. data/lib/active_support/logger_thread_safe_level.rb +55 -8
  190. data/lib/active_support/message_encryptor.rb +170 -53
  191. data/lib/active_support/message_verifier.rb +91 -20
  192. data/lib/active_support/messages/metadata.rb +80 -0
  193. data/lib/active_support/messages/rotation_configuration.rb +23 -0
  194. data/lib/active_support/messages/rotator.rb +57 -0
  195. data/lib/active_support/multibyte/chars.rb +24 -78
  196. data/lib/active_support/multibyte/unicode.rb +21 -352
  197. data/lib/active_support/multibyte.rb +4 -2
  198. data/lib/active_support/notifications/fanout.rb +121 -19
  199. data/lib/active_support/notifications/instrumenter.rb +78 -14
  200. data/lib/active_support/notifications.rb +80 -12
  201. data/lib/active_support/number_helper/number_converter.rb +17 -16
  202. data/lib/active_support/number_helper/number_to_currency_converter.rb +6 -9
  203. data/lib/active_support/number_helper/number_to_delimited_converter.rb +5 -3
  204. data/lib/active_support/number_helper/number_to_human_converter.rb +13 -12
  205. data/lib/active_support/number_helper/number_to_human_size_converter.rb +11 -13
  206. data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
  207. data/lib/active_support/number_helper/number_to_phone_converter.rb +5 -4
  208. data/lib/active_support/number_helper/number_to_rounded_converter.rb +18 -55
  209. data/lib/active_support/number_helper/rounding_helper.rb +50 -0
  210. data/lib/active_support/number_helper.rb +45 -16
  211. data/lib/active_support/option_merger.rb +25 -4
  212. data/lib/active_support/ordered_hash.rb +6 -4
  213. data/lib/active_support/ordered_options.rb +23 -9
  214. data/lib/active_support/parameter_filter.rb +133 -0
  215. data/lib/active_support/per_thread_registry.rb +7 -5
  216. data/lib/active_support/proxy_object.rb +2 -0
  217. data/lib/active_support/rails.rb +8 -9
  218. data/lib/active_support/railtie.rb +62 -11
  219. data/lib/active_support/reloader.rb +12 -11
  220. data/lib/active_support/rescuable.rb +20 -11
  221. data/lib/active_support/secure_compare_rotator.rb +51 -0
  222. data/lib/active_support/security_utils.rb +26 -15
  223. data/lib/active_support/string_inquirer.rb +12 -3
  224. data/lib/active_support/subscriber.rb +77 -23
  225. data/lib/active_support/tagged_logging.rb +52 -17
  226. data/lib/active_support/test_case.rb +106 -29
  227. data/lib/active_support/testing/assertions.rb +144 -8
  228. data/lib/active_support/testing/autorun.rb +5 -10
  229. data/lib/active_support/testing/constant_lookup.rb +2 -1
  230. data/lib/active_support/testing/declarative.rb +3 -1
  231. data/lib/active_support/testing/deprecation.rb +4 -2
  232. data/lib/active_support/testing/file_fixtures.rb +4 -0
  233. data/lib/active_support/testing/isolation.rb +19 -24
  234. data/lib/active_support/testing/method_call_assertions.rb +31 -2
  235. data/lib/active_support/testing/parallelization/server.rb +78 -0
  236. data/lib/active_support/testing/parallelization/worker.rb +100 -0
  237. data/lib/active_support/testing/parallelization.rb +51 -0
  238. data/lib/active_support/testing/setup_and_teardown.rb +13 -8
  239. data/lib/active_support/testing/stream.rb +30 -29
  240. data/lib/active_support/testing/tagged_logging.rb +3 -1
  241. data/lib/active_support/testing/time_helpers.rb +125 -24
  242. data/lib/active_support/time.rb +14 -12
  243. data/lib/active_support/time_with_zone.rb +142 -55
  244. data/lib/active_support/values/time_zone.rb +160 -53
  245. data/lib/active_support/version.rb +3 -1
  246. data/lib/active_support/xml_mini/jdom.rb +115 -114
  247. data/lib/active_support/xml_mini/libxml.rb +15 -14
  248. data/lib/active_support/xml_mini/libxmlsax.rb +16 -18
  249. data/lib/active_support/xml_mini/nokogiri.rb +13 -13
  250. data/lib/active_support/xml_mini/nokogirisax.rb +15 -16
  251. data/lib/active_support/xml_mini/rexml.rb +18 -9
  252. data/lib/active_support/xml_mini.rb +44 -42
  253. data/lib/active_support.rb +19 -10
  254. metadata +79 -37
  255. data/lib/active_support/concurrency/latch.rb +0 -19
  256. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
  257. data/lib/active_support/core_ext/hash/compact.rb +0 -20
  258. data/lib/active_support/core_ext/hash/transform_values.rb +0 -29
  259. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
  260. data/lib/active_support/core_ext/kernel/debugger.rb +0 -3
  261. data/lib/active_support/core_ext/module/method_transplanting.rb +0 -3
  262. data/lib/active_support/core_ext/module/qualified_const.rb +0 -70
  263. data/lib/active_support/core_ext/module/reachable.rb +0 -8
  264. data/lib/active_support/core_ext/numeric/inquiry.rb +0 -26
  265. data/lib/active_support/core_ext/range/include_range.rb +0 -23
  266. data/lib/active_support/core_ext/struct.rb +0 -3
  267. data/lib/active_support/core_ext/time/marshal.rb +0 -3
  268. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,26 +1,28 @@
1
- require 'set'
2
- require 'thread'
3
- require 'concurrent/map'
4
- require 'pathname'
5
- require 'active_support/core_ext/module/aliasing'
6
- require 'active_support/core_ext/module/attribute_accessors'
7
- require 'active_support/core_ext/module/introspection'
8
- require 'active_support/core_ext/module/anonymous'
9
- require 'active_support/core_ext/module/qualified_const'
10
- require 'active_support/core_ext/object/blank'
11
- require 'active_support/core_ext/kernel/reporting'
12
- require 'active_support/core_ext/load_error'
13
- require 'active_support/core_ext/name_error'
14
- require 'active_support/core_ext/string/starts_ends_with'
1
+ # frozen_string_literal: true
2
+
3
+ require "set"
4
+ require "thread"
5
+ require "concurrent/map"
6
+ require "pathname"
7
+ require "active_support/core_ext/module/aliasing"
8
+ require "active_support/core_ext/module/attribute_accessors"
9
+ require "active_support/core_ext/module/introspection"
10
+ require "active_support/core_ext/module/anonymous"
11
+ require "active_support/core_ext/object/blank"
12
+ require "active_support/core_ext/kernel/reporting"
13
+ require "active_support/core_ext/load_error"
14
+ require "active_support/core_ext/name_error"
15
15
  require "active_support/dependencies/interlock"
16
- require 'active_support/inflector'
16
+ require "active_support/inflector"
17
17
 
18
18
  module ActiveSupport #:nodoc:
19
19
  module Dependencies #:nodoc:
20
20
  extend self
21
21
 
22
- mattr_accessor :interlock
23
- self.interlock = Interlock.new
22
+ UNBOUND_METHOD_MODULE_NAME = Module.instance_method(:name)
23
+ private_constant :UNBOUND_METHOD_MODULE_NAME
24
+
25
+ mattr_accessor :interlock, default: Interlock.new
24
26
 
25
27
  # :doc:
26
28
 
@@ -47,46 +49,48 @@ module ActiveSupport #:nodoc:
47
49
  # :nodoc:
48
50
 
49
51
  # Should we turn on Ruby warnings on the first load of dependent files?
50
- mattr_accessor :warnings_on_first_load
51
- self.warnings_on_first_load = false
52
+ mattr_accessor :warnings_on_first_load, default: false
52
53
 
53
54
  # All files ever loaded.
54
- mattr_accessor :history
55
- self.history = Set.new
55
+ mattr_accessor :history, default: Set.new
56
56
 
57
57
  # All files currently loaded.
58
- mattr_accessor :loaded
59
- self.loaded = Set.new
58
+ mattr_accessor :loaded, default: Set.new
60
59
 
61
60
  # Stack of files being loaded.
62
- mattr_accessor :loading
63
- self.loading = []
61
+ mattr_accessor :loading, default: []
64
62
 
65
63
  # Should we load files or require them?
66
- mattr_accessor :mechanism
67
- self.mechanism = ENV['NO_RELOAD'] ? :require : :load
64
+ mattr_accessor :mechanism, default: ENV["NO_RELOAD"] ? :require : :load
68
65
 
69
66
  # The set of directories from which we may automatically load files. Files
70
67
  # under these directories will be reloaded on each request in development mode,
71
68
  # unless the directory also appears in autoload_once_paths.
72
- mattr_accessor :autoload_paths
73
- self.autoload_paths = []
69
+ mattr_accessor :autoload_paths, default: []
74
70
 
75
71
  # The set of directories from which automatically loaded constants are loaded
76
72
  # only once. All directories in this set must also be present in +autoload_paths+.
77
- mattr_accessor :autoload_once_paths
78
- self.autoload_once_paths = []
73
+ mattr_accessor :autoload_once_paths, default: []
74
+
75
+ # This is a private set that collects all eager load paths during bootstrap.
76
+ # Useful for Zeitwerk integration. Its public interface is the config.* path
77
+ # accessors of each engine.
78
+ mattr_accessor :_eager_load_paths, default: Set.new
79
79
 
80
80
  # An array of qualified constant names that have been loaded. Adding a name
81
81
  # to this array will cause it to be unloaded the next time Dependencies are
82
82
  # cleared.
83
- mattr_accessor :autoloaded_constants
84
- self.autoloaded_constants = []
83
+ mattr_accessor :autoloaded_constants, default: []
85
84
 
86
85
  # An array of constant names that need to be unloaded on every request. Used
87
86
  # to allow arbitrary constants to be marked for unloading.
88
- mattr_accessor :explicitly_unloadable_constants
89
- self.explicitly_unloadable_constants = []
87
+ mattr_accessor :explicitly_unloadable_constants, default: []
88
+
89
+ # The logger used when tracing autoloads.
90
+ mattr_accessor :logger
91
+
92
+ # If true, trace autoloads with +logger.debug+.
93
+ mattr_accessor :verbose, default: false
90
94
 
91
95
  # The WatchStack keeps a stack of the modules being watched as files are
92
96
  # loaded. If a file in the process of being loaded (parent.rb) triggers the
@@ -94,7 +98,7 @@ module ActiveSupport #:nodoc:
94
98
  # handles the new constants.
95
99
  #
96
100
  # If child.rb is being autoloaded, its constants will be added to
97
- # autoloaded_constants. If it was being `require`d, they will be discarded.
101
+ # autoloaded_constants. If it was being required, they will be discarded.
98
102
  #
99
103
  # This is handled by walking back up the watch stack and adding the constants
100
104
  # found by child.rb to the list of original constants in parent.rb.
@@ -106,9 +110,11 @@ module ActiveSupport #:nodoc:
106
110
  # parent.rb then requires namespace/child.rb, the stack will look like
107
111
  # [[Object], [Namespace]].
108
112
 
113
+ attr_reader :watching
114
+
109
115
  def initialize
110
116
  @watching = []
111
- @stack = Hash.new { |h,k| h[k] = [] }
117
+ @stack = Hash.new { |h, k| h[k] = [] }
112
118
  end
113
119
 
114
120
  def each(&block)
@@ -147,7 +153,7 @@ module ActiveSupport #:nodoc:
147
153
 
148
154
  # Normalize the list of new constants, and add them to the list we will return
149
155
  new_constants.each do |suffix|
150
- constants << ([namespace, suffix] - ["Object"]).join("::".freeze)
156
+ constants << ([namespace, suffix] - ["Object"]).join("::")
151
157
  end
152
158
  end
153
159
  constants
@@ -170,14 +176,13 @@ module ActiveSupport #:nodoc:
170
176
  end
171
177
 
172
178
  private
173
- def pop_modules(modules)
174
- modules.each { |mod| @stack[mod].pop }
175
- end
179
+ def pop_modules(modules)
180
+ modules.each { |mod| @stack[mod].pop }
181
+ end
176
182
  end
177
183
 
178
184
  # An internal stack used to record which constants are loaded by any block.
179
- mattr_accessor :constant_watch_stack
180
- self.constant_watch_stack = WatchStack.new
185
+ mattr_accessor :constant_watch_stack, default: WatchStack.new
181
186
 
182
187
  # Module includes this module.
183
188
  module ModuleConstMissing #:nodoc:
@@ -198,6 +203,11 @@ module ActiveSupport #:nodoc:
198
203
  end
199
204
  end
200
205
 
206
+ def self.include_into(base)
207
+ base.include(self)
208
+ append_features(base)
209
+ end
210
+
201
211
  def const_missing(const_name)
202
212
  from_mod = anonymous? ? guess_for_anonymous(const_name) : self
203
213
  Dependencies.load_missing_constant(from_mod, const_name)
@@ -227,6 +237,21 @@ module ActiveSupport #:nodoc:
227
237
  base.class_eval do
228
238
  define_method(:load, Kernel.instance_method(:load))
229
239
  private :load
240
+
241
+ define_method(:require, Kernel.instance_method(:require))
242
+ private :require
243
+ end
244
+ end
245
+
246
+ def self.include_into(base)
247
+ base.include(self)
248
+
249
+ if base.instance_method(:load).owner == base
250
+ base.remove_method(:load)
251
+ end
252
+
253
+ if base.instance_method(:require).owner == base
254
+ base.remove_method(:require)
230
255
  end
231
256
  end
232
257
 
@@ -234,16 +259,27 @@ module ActiveSupport #:nodoc:
234
259
  Dependencies.require_or_load(file_name)
235
260
  end
236
261
 
237
- # Interprets a file using <tt>mechanism</tt> and marks its defined
238
- # constants as autoloaded. <tt>file_name</tt> can be either a string or
262
+ # :doc:
263
+
264
+ # <b>Warning:</b> This method is obsolete in +:zeitwerk+ mode. In
265
+ # +:zeitwerk+ mode semantics match Ruby's and you do not need to be
266
+ # defensive with load order. Just refer to classes and modules normally.
267
+ # If the constant name is dynamic, camelize if needed, and constantize.
268
+ #
269
+ # In +:classic+ mode, interprets a file using +mechanism+ and marks its
270
+ # defined constants as autoloaded. +file_name+ can be either a string or
239
271
  # respond to <tt>to_path</tt>.
240
272
  #
241
- # Use this method in code that absolutely needs a certain constant to be
242
- # defined at that point. A typical use case is to make constant name
243
- # resolution deterministic for constants with the same relative name in
244
- # different namespaces whose evaluation would depend on load order
245
- # otherwise.
246
- def require_dependency(file_name, message = "No such file to load -- %s")
273
+ # In +:classic+ mode, use this method in code that absolutely needs a
274
+ # certain constant to be defined at that point. A typical use case is to
275
+ # make constant name resolution deterministic for constants with the same
276
+ # relative name in different namespaces whose evaluation would depend on
277
+ # load order otherwise.
278
+ #
279
+ # Engines that do not control the mode in which their parent application
280
+ # runs should call +require_dependency+ where needed in case the runtime
281
+ # mode is +:classic+.
282
+ def require_dependency(file_name, message = "No such file to load -- %s.rb")
247
283
  file_name = file_name.to_path if file_name.respond_to?(:to_path)
248
284
  unless file_name.is_a?(String)
249
285
  raise ArgumentError, "the file name must either be a String or implement #to_path -- you passed #{file_name.inspect}"
@@ -252,9 +288,13 @@ module ActiveSupport #:nodoc:
252
288
  Dependencies.depend_on(file_name, message)
253
289
  end
254
290
 
291
+ # :nodoc:
292
+
255
293
  def load_dependency(file)
256
294
  if Dependencies.load? && Dependencies.constant_watch_stack.watching?
257
- Dependencies.new_constants_in(Object) { yield }
295
+ descs = Dependencies.constant_watch_stack.watching.flatten.uniq
296
+
297
+ Dependencies.new_constants_in(*descs) { yield }
258
298
  else
259
299
  yield
260
300
  end
@@ -281,18 +321,17 @@ module ActiveSupport #:nodoc:
281
321
  end
282
322
 
283
323
  private
324
+ def load(file, wrap = false)
325
+ result = false
326
+ load_dependency(file) { result = super }
327
+ result
328
+ end
284
329
 
285
- def load(file, wrap = false)
286
- result = false
287
- load_dependency(file) { result = super }
288
- result
289
- end
290
-
291
- def require(file)
292
- result = false
293
- load_dependency(file) { result = super }
294
- result
295
- end
330
+ def require(file)
331
+ result = false
332
+ load_dependency(file) { result = super }
333
+ result
334
+ end
296
335
  end
297
336
 
298
337
  # Exception file-blaming.
@@ -317,9 +356,9 @@ module ActiveSupport #:nodoc:
317
356
  end
318
357
 
319
358
  def hook!
320
- Object.class_eval { include Loadable }
321
- Module.class_eval { include ModuleConstMissing }
322
- Exception.class_eval { include Blamable }
359
+ Loadable.include_into(Object)
360
+ ModuleConstMissing.include_into(Module)
361
+ Exception.include(Blamable)
323
362
  end
324
363
 
325
364
  def unhook!
@@ -336,7 +375,12 @@ module ActiveSupport #:nodoc:
336
375
  require_or_load(path || file_name)
337
376
  rescue LoadError => load_error
338
377
  if file_name = load_error.message[/ -- (.*?)(\.rb)?$/, 1]
339
- load_error.message.replace(message % file_name)
378
+ load_error_message = if load_error.respond_to?(:original_message)
379
+ load_error.original_message
380
+ else
381
+ load_error.message
382
+ end
383
+ load_error_message.replace(message % file_name)
340
384
  load_error.copy_blame!(load_error)
341
385
  end
342
386
  raise
@@ -351,7 +395,7 @@ module ActiveSupport #:nodoc:
351
395
  end
352
396
 
353
397
  def require_or_load(file_name, const_path = nil)
354
- file_name = $` if file_name =~ /\.rb\z/
398
+ file_name = file_name.chomp(".rb")
355
399
  expanded = File.expand_path(file_name)
356
400
  return if loaded.include?(expanded)
357
401
 
@@ -371,7 +415,7 @@ module ActiveSupport #:nodoc:
371
415
  load_args = ["#{file_name}.rb"]
372
416
  load_args << const_path unless const_path.nil?
373
417
 
374
- if !warnings_on_first_load or history.include?(expanded)
418
+ if !warnings_on_first_load || history.include?(expanded)
375
419
  result = load_file(*load_args)
376
420
  else
377
421
  enable_warnings { result = load_file(*load_args) }
@@ -401,7 +445,7 @@ module ActiveSupport #:nodoc:
401
445
  # constant paths which would cause Dependencies to attempt to load this
402
446
  # file.
403
447
  def loadable_constants_for_path(path, bases = autoload_paths)
404
- path = $` if path =~ /\.rb\z/
448
+ path = path.chomp(".rb")
405
449
  expanded_path = File.expand_path(path)
406
450
  paths = []
407
451
 
@@ -410,7 +454,7 @@ module ActiveSupport #:nodoc:
410
454
  next unless expanded_path.start_with?(expanded_root)
411
455
 
412
456
  root_size = expanded_root.size
413
- next if expanded_path[root_size] != ?/.freeze
457
+ next if expanded_path[root_size] != ?/
414
458
 
415
459
  nesting = expanded_path[(root_size + 1)..-1]
416
460
  paths << nesting.camelize unless nesting.blank?
@@ -422,7 +466,7 @@ module ActiveSupport #:nodoc:
422
466
 
423
467
  # Search for a file in autoload_paths matching the provided suffix.
424
468
  def search_for_file(path_suffix)
425
- path_suffix = path_suffix.sub(/(\.rb)?$/, ".rb".freeze)
469
+ path_suffix += ".rb" unless path_suffix.end_with?(".rb")
426
470
 
427
471
  autoload_paths.each do |root|
428
472
  path = File.join(root, path_suffix)
@@ -442,9 +486,9 @@ module ActiveSupport #:nodoc:
442
486
  end
443
487
 
444
488
  def load_once_path?(path)
445
- # to_s works around a ruby issue where String#starts_with?(Pathname)
489
+ # to_s works around a ruby issue where String#start_with?(Pathname)
446
490
  # will raise a TypeError: no implicit conversion of Pathname into String
447
- autoload_once_paths.any? { |base| path.starts_with? base.to_s }
491
+ autoload_once_paths.any? { |base| path.start_with?(base.to_s) }
448
492
  end
449
493
 
450
494
  # Attempt to autoload the provided module name by searching for a directory
@@ -456,7 +500,9 @@ module ActiveSupport #:nodoc:
456
500
  return nil unless base_path = autoloadable_module?(path_suffix)
457
501
  mod = Module.new
458
502
  into.const_set const_name, mod
503
+ log("constant #{qualified_name} autoloaded (module autovivified from #{File.join(base_path, path_suffix)})")
459
504
  autoloaded_constants << qualified_name unless autoload_once_paths.include?(base_path)
505
+ autoloaded_constants.uniq!
460
506
  mod
461
507
  end
462
508
 
@@ -492,30 +538,36 @@ module ActiveSupport #:nodoc:
492
538
  # it is not possible to load the constant into from_mod, try its parent
493
539
  # module using +const_missing+.
494
540
  def load_missing_constant(from_mod, const_name)
495
- unless qualified_const_defined?(from_mod.name) && Inflector.constantize(from_mod.name).equal?(from_mod)
541
+ from_mod_name = real_mod_name(from_mod)
542
+ unless qualified_const_defined?(from_mod_name) && Inflector.constantize(from_mod_name).equal?(from_mod)
496
543
  raise ArgumentError, "A copy of #{from_mod} has been removed from the module tree but is still active!"
497
544
  end
498
545
 
499
- qualified_name = qualified_name_for from_mod, const_name
546
+ qualified_name = qualified_name_for(from_mod, const_name)
500
547
  path_suffix = qualified_name.underscore
501
548
 
502
549
  file_path = search_for_file(path_suffix)
503
550
 
504
551
  if file_path
505
552
  expanded = File.expand_path(file_path)
506
- expanded.sub!(/\.rb\z/, ''.freeze)
553
+ expanded.delete_suffix!(".rb")
507
554
 
508
555
  if loading.include?(expanded)
509
556
  raise "Circular dependency detected while autoloading constant #{qualified_name}"
510
557
  else
511
558
  require_or_load(expanded, qualified_name)
512
- raise LoadError, "Unable to autoload constant #{qualified_name}, expected #{file_path} to define it" unless from_mod.const_defined?(const_name, false)
513
- return from_mod.const_get(const_name)
559
+
560
+ if from_mod.const_defined?(const_name, false)
561
+ log("constant #{qualified_name} autoloaded from #{expanded}.rb")
562
+ return from_mod.const_get(const_name)
563
+ else
564
+ raise LoadError, "Unable to autoload constant #{qualified_name}, expected #{file_path} to define it"
565
+ end
514
566
  end
515
567
  elsif mod = autoload_module!(from_mod, const_name, qualified_name, path_suffix)
516
568
  return mod
517
- elsif (parent = from_mod.parent) && parent != from_mod &&
518
- ! from_mod.parents.any? { |p| p.const_defined?(const_name, false) }
569
+ elsif (parent = from_mod.module_parent) && parent != from_mod &&
570
+ ! from_mod.module_parents.any? { |p| p.const_defined?(const_name, false) }
519
571
  # If our parents do not have a constant named +const_name+ then we are free
520
572
  # to attempt to load upwards. If they do have such a constant, then this
521
573
  # const_missing must be due to from_mod::const_name, which should not
@@ -546,8 +598,8 @@ module ActiveSupport #:nodoc:
546
598
  end
547
599
  end
548
600
 
549
- name_error = NameError.new("uninitialized constant #{qualified_name}", const_name)
550
- name_error.set_backtrace(caller.reject {|l| l.starts_with? __FILE__ })
601
+ name_error = uninitialized_constant(qualified_name, const_name, receiver: from_mod)
602
+ name_error.set_backtrace(caller.reject { |l| l.start_with? __FILE__ })
551
603
  raise name_error
552
604
  end
553
605
 
@@ -559,6 +611,7 @@ module ActiveSupport #:nodoc:
559
611
  # as the environment will be in an inconsistent state, e.g. other constants
560
612
  # may have already been unloaded and not accessible.
561
613
  def remove_unloadable_constants!
614
+ log("removing unloadable constants")
562
615
  autoloaded_constants.each { |const| remove_constant const }
563
616
  autoloaded_constants.clear
564
617
  Reference.clear!
@@ -591,7 +644,7 @@ module ActiveSupport #:nodoc:
591
644
 
592
645
  def store(klass)
593
646
  return self unless klass.respond_to?(:name)
594
- raise(ArgumentError, 'anonymous classes cannot be cached') if klass.name.empty?
647
+ raise(ArgumentError, "anonymous classes cannot be cached") if klass.name.empty?
595
648
  @store[klass.name] = klass
596
649
  self
597
650
  end
@@ -622,10 +675,10 @@ module ActiveSupport #:nodoc:
622
675
 
623
676
  # Determine if the given constant has been automatically loaded.
624
677
  def autoloaded?(desc)
625
- return false if desc.is_a?(Module) && desc.anonymous?
678
+ return false if desc.is_a?(Module) && real_mod_name(desc).nil?
626
679
  name = to_constant_name desc
627
680
  return false unless qualified_const_defined?(name)
628
- return autoloaded_constants.include?(name)
681
+ autoloaded_constants.include?(name)
629
682
  end
630
683
 
631
684
  # Will the provided constant descriptor be unloaded?
@@ -675,29 +728,29 @@ module ActiveSupport #:nodoc:
675
728
  # A module, class, symbol, or string may be provided.
676
729
  def to_constant_name(desc) #:nodoc:
677
730
  case desc
678
- when String then desc.sub(/^::/, '')
679
- when Symbol then desc.to_s
680
- when Module
681
- desc.name ||
682
- raise(ArgumentError, "Anonymous modules have no name to be referenced by")
683
- else raise TypeError, "Not a valid constant descriptor: #{desc.inspect}"
731
+ when String then desc.delete_prefix("::")
732
+ when Symbol then desc.to_s
733
+ when Module
734
+ real_mod_name(desc) ||
735
+ raise(ArgumentError, "Anonymous modules have no name to be referenced by")
736
+ else raise TypeError, "Not a valid constant descriptor: #{desc.inspect}"
684
737
  end
685
738
  end
686
739
 
687
740
  def remove_constant(const) #:nodoc:
688
741
  # Normalize ::Foo, ::Object::Foo, Object::Foo, Object::Object::Foo, etc. as Foo.
689
- normalized = const.to_s.sub(/\A::/, '')
690
- normalized.sub!(/\A(Object::)+/, '')
742
+ normalized = const.to_s.delete_prefix("::")
743
+ normalized.sub!(/\A(Object::)+/, "")
691
744
 
692
- constants = normalized.split('::')
745
+ constants = normalized.split("::")
693
746
  to_remove = constants.pop
694
747
 
695
748
  # Remove the file path from the loaded list.
696
749
  file_path = search_for_file(const.underscore)
697
750
  if file_path
698
751
  expanded = File.expand_path(file_path)
699
- expanded.sub!(/\.rb\z/, '')
700
- self.loaded.delete(expanded)
752
+ expanded.delete_suffix!(".rb")
753
+ loaded.delete(expanded)
701
754
  end
702
755
 
703
756
  if constants.empty?
@@ -710,7 +763,7 @@ module ActiveSupport #:nodoc:
710
763
  # here than require the caller to be clever. We check the parent
711
764
  # rather than the very const argument because we do not want to
712
765
  # trigger Kernel#autoloads, see the comment below.
713
- parent_name = constants.join('::')
766
+ parent_name = constants.join("::")
714
767
  return unless qualified_const_defined?(parent_name)
715
768
  parent = constantize(parent_name)
716
769
  end
@@ -748,6 +801,27 @@ module ActiveSupport #:nodoc:
748
801
  # The constant is no longer reachable, just skip it.
749
802
  end
750
803
  end
804
+
805
+ def log(message)
806
+ logger.debug("autoloading: #{message}") if logger && verbose
807
+ end
808
+
809
+ private
810
+ if RUBY_VERSION < "2.6"
811
+ def uninitialized_constant(qualified_name, const_name, receiver:)
812
+ NameError.new("uninitialized constant #{qualified_name}", const_name)
813
+ end
814
+ else
815
+ def uninitialized_constant(qualified_name, const_name, receiver:)
816
+ NameError.new("uninitialized constant #{qualified_name}", const_name, receiver: receiver)
817
+ end
818
+ end
819
+
820
+ # Returns the original name of a class or module even if `name` has been
821
+ # overridden.
822
+ def real_mod_name(mod)
823
+ UNBOUND_METHOD_MODULE_NAME.bind(mod).call
824
+ end
751
825
  end
752
826
  end
753
827
 
@@ -1,43 +1,49 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/notifications"
2
4
 
3
5
  module ActiveSupport
4
6
  # Raised when <tt>ActiveSupport::Deprecation::Behavior#behavior</tt> is set with <tt>:raise</tt>.
5
- # You would set <tt>:raise</tt>, as a behaviour to raise errors and proactively report exceptions from deprecations.
7
+ # You would set <tt>:raise</tt>, as a behavior to raise errors and proactively report exceptions from deprecations.
6
8
  class DeprecationException < StandardError
7
9
  end
8
10
 
9
11
  class Deprecation
10
12
  # Default warning behaviors per Rails.env.
11
13
  DEFAULT_BEHAVIORS = {
12
- raise: ->(message, callstack) {
14
+ raise: ->(message, callstack, deprecation_horizon, gem_name) {
13
15
  e = DeprecationException.new(message)
14
16
  e.set_backtrace(callstack.map(&:to_s))
15
17
  raise e
16
18
  },
17
19
 
18
- stderr: ->(message, callstack) {
20
+ stderr: ->(message, callstack, deprecation_horizon, gem_name) {
19
21
  $stderr.puts(message)
20
22
  $stderr.puts callstack.join("\n ") if debug
21
23
  },
22
24
 
23
- log: ->(message, callstack) {
25
+ log: ->(message, callstack, deprecation_horizon, gem_name) {
24
26
  logger =
25
27
  if defined?(Rails.logger) && Rails.logger
26
28
  Rails.logger
27
29
  else
28
- require 'active_support/logger'
30
+ require "active_support/logger"
29
31
  ActiveSupport::Logger.new($stderr)
30
32
  end
31
33
  logger.warn message
32
34
  logger.debug callstack.join("\n ") if debug
33
35
  },
34
36
 
35
- notify: ->(message, callstack) {
36
- ActiveSupport::Notifications.instrument("deprecation.rails",
37
- :message => message, :callstack => callstack)
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)
38
44
  },
39
45
 
40
- silence: ->(message, callstack) {},
46
+ silence: ->(message, callstack, deprecation_horizon, gem_name) { },
41
47
  }
42
48
 
43
49
  # Behavior module allows to determine how to display deprecation messages.
@@ -45,7 +51,7 @@ module ActiveSupport
45
51
  # constant. Available behaviors are:
46
52
  #
47
53
  # [+raise+] Raise <tt>ActiveSupport::DeprecationException</tt>.
48
- # [+stderr+] Log all deprecation warnings to +$stderr+.
54
+ # [+stderr+] Log all deprecation warnings to <tt>$stderr</tt>.
49
55
  # [+log+] Log all deprecation warnings to +Rails.logger+.
50
56
  # [+notify+] Use +ActiveSupport::Notifications+ to notify +deprecation.rails+.
51
57
  # [+silence+] Do nothing.
@@ -61,13 +67,18 @@ module ActiveSupport
61
67
  @behavior ||= [DEFAULT_BEHAVIORS[:stderr]]
62
68
  end
63
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
+
64
75
  # Sets the behavior to the specified value. Can be a single value, array,
65
76
  # or an object that responds to +call+.
66
77
  #
67
78
  # Available behaviors:
68
79
  #
69
80
  # [+raise+] Raise <tt>ActiveSupport::DeprecationException</tt>.
70
- # [+stderr+] Log all deprecation warnings to +$stderr+.
81
+ # [+stderr+] Log all deprecation warnings to <tt>$stderr</tt>.
71
82
  # [+log+] Log all deprecation warnings to +Rails.logger+.
72
83
  # [+notify+] Use +ActiveSupport::Notifications+ to notify +deprecation.rails+.
73
84
  # [+silence+] Do nothing.
@@ -79,12 +90,33 @@ module ActiveSupport
79
90
  # ActiveSupport::Deprecation.behavior = :stderr
80
91
  # ActiveSupport::Deprecation.behavior = [:stderr, :log]
81
92
  # ActiveSupport::Deprecation.behavior = MyCustomHandler
82
- # ActiveSupport::Deprecation.behavior = ->(message, callstack) {
93
+ # ActiveSupport::Deprecation.behavior = ->(message, callstack, deprecation_horizon, gem_name) {
83
94
  # # custom stuff
84
95
  # }
85
96
  def behavior=(behavior)
86
- @behavior = Array(behavior).map { |b| DEFAULT_BEHAVIORS[b] || b }
97
+ @behavior = Array(behavior).map { |b| DEFAULT_BEHAVIORS[b] || arity_coerce(b) }
87
98
  end
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
+
108
+ private
109
+ def arity_coerce(behavior)
110
+ unless behavior.respond_to?(:call)
111
+ raise ArgumentError, "#{behavior.inspect} is not a valid deprecation behavior."
112
+ end
113
+
114
+ if behavior.arity == 4 || behavior.arity == -1
115
+ behavior
116
+ else
117
+ -> message, callstack, _, _ { behavior.call(message, callstack) }
118
+ end
119
+ end
88
120
  end
89
121
  end
90
122
  end