activesupport 4.2.11.1 → 6.0.3.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activesupport might be problematic. Click here for more details.

Files changed (263) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +399 -411
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +7 -7
  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 +48 -0
  8. data/lib/active_support/backtrace_cleaner.rb +34 -6
  9. data/lib/active_support/benchmarkable.rb +6 -4
  10. data/lib/active_support/builder.rb +3 -1
  11. data/lib/active_support/cache/file_store.rb +58 -53
  12. data/lib/active_support/cache/mem_cache_store.rb +95 -91
  13. data/lib/active_support/cache/memory_store.rb +39 -36
  14. data/lib/active_support/cache/null_store.rb +11 -7
  15. data/lib/active_support/cache/redis_cache_store.rb +493 -0
  16. data/lib/active_support/cache/strategy/local_cache.rb +75 -42
  17. data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
  18. data/lib/active_support/cache.rb +331 -217
  19. data/lib/active_support/callbacks.rb +650 -592
  20. data/lib/active_support/concern.rb +35 -6
  21. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +35 -0
  22. data/lib/active_support/concurrency/share_lock.rb +226 -0
  23. data/lib/active_support/configurable.rb +13 -14
  24. data/lib/active_support/core_ext/array/access.rb +41 -1
  25. data/lib/active_support/core_ext/array/conversions.rb +24 -20
  26. data/lib/active_support/core_ext/array/extract.rb +21 -0
  27. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  28. data/lib/active_support/core_ext/array/grouping.rb +11 -18
  29. data/lib/active_support/core_ext/array/inquiry.rb +19 -0
  30. data/lib/active_support/core_ext/array/prepend_and_append.rb +4 -6
  31. data/lib/active_support/core_ext/array/wrap.rb +7 -4
  32. data/lib/active_support/core_ext/array.rb +9 -6
  33. data/lib/active_support/core_ext/benchmark.rb +3 -1
  34. data/lib/active_support/core_ext/big_decimal/conversions.rb +10 -12
  35. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  36. data/lib/active_support/core_ext/class/attribute.rb +45 -31
  37. data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
  38. data/lib/active_support/core_ext/class/subclasses.rb +20 -6
  39. data/lib/active_support/core_ext/class.rb +4 -3
  40. data/lib/active_support/core_ext/date/acts_like.rb +3 -1
  41. data/lib/active_support/core_ext/date/blank.rb +14 -0
  42. data/lib/active_support/core_ext/date/calculations.rb +17 -14
  43. data/lib/active_support/core_ext/date/conversions.rb +25 -23
  44. data/lib/active_support/core_ext/date/zones.rb +4 -2
  45. data/lib/active_support/core_ext/date.rb +6 -4
  46. data/lib/active_support/core_ext/date_and_time/calculations.rb +154 -65
  47. data/lib/active_support/core_ext/date_and_time/compatibility.rb +4 -3
  48. data/lib/active_support/core_ext/date_and_time/zones.rb +12 -13
  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 +14 -0
  51. data/lib/active_support/core_ext/date_time/calculations.rb +37 -19
  52. data/lib/active_support/core_ext/date_time/compatibility.rb +8 -6
  53. data/lib/active_support/core_ext/date_time/conversions.rb +16 -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 +114 -22
  58. data/lib/active_support/core_ext/file/atomic.rb +38 -31
  59. data/lib/active_support/core_ext/file.rb +3 -1
  60. data/lib/active_support/core_ext/hash/compact.rb +4 -23
  61. data/lib/active_support/core_ext/hash/conversions.rb +62 -41
  62. data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
  63. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  64. data/lib/active_support/core_ext/hash/except.rb +12 -9
  65. data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -3
  66. data/lib/active_support/core_ext/hash/keys.rb +19 -42
  67. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  68. data/lib/active_support/core_ext/hash/slice.rb +5 -27
  69. data/lib/active_support/core_ext/hash/transform_values.rb +4 -22
  70. data/lib/active_support/core_ext/hash.rb +10 -9
  71. data/lib/active_support/core_ext/integer/inflections.rb +3 -1
  72. data/lib/active_support/core_ext/integer/multiple.rb +3 -1
  73. data/lib/active_support/core_ext/integer/time.rb +11 -18
  74. data/lib/active_support/core_ext/integer.rb +5 -3
  75. data/lib/active_support/core_ext/kernel/concern.rb +5 -1
  76. data/lib/active_support/core_ext/kernel/reporting.rb +4 -84
  77. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  78. data/lib/active_support/core_ext/kernel.rb +5 -5
  79. data/lib/active_support/core_ext/load_error.rb +3 -22
  80. data/lib/active_support/core_ext/marshal.rb +8 -8
  81. data/lib/active_support/core_ext/module/aliasing.rb +6 -44
  82. data/lib/active_support/core_ext/module/anonymous.rb +12 -1
  83. data/lib/active_support/core_ext/module/attr_internal.rb +8 -9
  84. data/lib/active_support/core_ext/module/attribute_accessors.rb +46 -46
  85. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +144 -0
  86. data/lib/active_support/core_ext/module/concerning.rb +11 -12
  87. data/lib/active_support/core_ext/module/delegation.rb +133 -30
  88. data/lib/active_support/core_ext/module/deprecation.rb +4 -2
  89. data/lib/active_support/core_ext/module/introspection.rb +44 -19
  90. data/lib/active_support/core_ext/module/reachable.rb +5 -7
  91. data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
  92. data/lib/active_support/core_ext/module/remove_method.rb +8 -3
  93. data/lib/active_support/core_ext/module.rb +13 -11
  94. data/lib/active_support/core_ext/name_error.rb +22 -2
  95. data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
  96. data/lib/active_support/core_ext/numeric/conversions.rb +129 -136
  97. data/lib/active_support/core_ext/numeric/inquiry.rb +5 -0
  98. data/lib/active_support/core_ext/numeric/time.rb +35 -23
  99. data/lib/active_support/core_ext/numeric.rb +5 -3
  100. data/lib/active_support/core_ext/object/acts_like.rb +12 -1
  101. data/lib/active_support/core_ext/object/blank.rb +27 -3
  102. data/lib/active_support/core_ext/object/conversions.rb +6 -4
  103. data/lib/active_support/core_ext/object/deep_dup.rb +13 -4
  104. data/lib/active_support/core_ext/object/duplicable.rb +13 -93
  105. data/lib/active_support/core_ext/object/inclusion.rb +5 -3
  106. data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
  107. data/lib/active_support/core_ext/object/json.rb +51 -20
  108. data/lib/active_support/core_ext/object/to_param.rb +3 -1
  109. data/lib/active_support/core_ext/object/to_query.rb +10 -5
  110. data/lib/active_support/core_ext/object/try.rb +81 -23
  111. data/lib/active_support/core_ext/object/with_options.rb +16 -3
  112. data/lib/active_support/core_ext/object.rb +14 -13
  113. data/lib/active_support/core_ext/range/compare_range.rb +76 -0
  114. data/lib/active_support/core_ext/range/conversions.rb +37 -15
  115. data/lib/active_support/core_ext/range/each.rb +18 -17
  116. data/lib/active_support/core_ext/range/include_range.rb +7 -21
  117. data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -0
  118. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  119. data/lib/active_support/core_ext/range.rb +7 -4
  120. data/lib/active_support/core_ext/regexp.rb +2 -0
  121. data/lib/active_support/core_ext/securerandom.rb +45 -0
  122. data/lib/active_support/core_ext/string/access.rb +16 -6
  123. data/lib/active_support/core_ext/string/behavior.rb +3 -1
  124. data/lib/active_support/core_ext/string/conversions.rb +7 -4
  125. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  126. data/lib/active_support/core_ext/string/filters.rb +48 -6
  127. data/lib/active_support/core_ext/string/indent.rb +6 -4
  128. data/lib/active_support/core_ext/string/inflections.rb +66 -24
  129. data/lib/active_support/core_ext/string/inquiry.rb +3 -1
  130. data/lib/active_support/core_ext/string/multibyte.rb +16 -7
  131. data/lib/active_support/core_ext/string/output_safety.rb +93 -40
  132. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
  133. data/lib/active_support/core_ext/string/strip.rb +6 -5
  134. data/lib/active_support/core_ext/string/zones.rb +4 -2
  135. data/lib/active_support/core_ext/string.rb +15 -13
  136. data/lib/active_support/core_ext/time/acts_like.rb +3 -1
  137. data/lib/active_support/core_ext/time/calculations.rb +115 -52
  138. data/lib/active_support/core_ext/time/compatibility.rb +4 -2
  139. data/lib/active_support/core_ext/time/conversions.rb +20 -13
  140. data/lib/active_support/core_ext/time/zones.rb +41 -7
  141. data/lib/active_support/core_ext/time.rb +7 -6
  142. data/lib/active_support/core_ext/uri.rb +6 -7
  143. data/lib/active_support/core_ext.rb +3 -1
  144. data/lib/active_support/current_attributes.rb +203 -0
  145. data/lib/active_support/dependencies/autoload.rb +2 -0
  146. data/lib/active_support/dependencies/interlock.rb +57 -0
  147. data/lib/active_support/dependencies/zeitwerk_integration.rb +117 -0
  148. data/lib/active_support/dependencies.rb +208 -166
  149. data/lib/active_support/deprecation/behaviors.rb +44 -11
  150. data/lib/active_support/deprecation/constant_accessor.rb +52 -0
  151. data/lib/active_support/deprecation/instance_delegator.rb +17 -2
  152. data/lib/active_support/deprecation/method_wrappers.rb +61 -21
  153. data/lib/active_support/deprecation/proxy_wrappers.rb +81 -30
  154. data/lib/active_support/deprecation/reporting.rb +32 -12
  155. data/lib/active_support/deprecation.rb +12 -9
  156. data/lib/active_support/descendants_tracker.rb +57 -9
  157. data/lib/active_support/digest.rb +20 -0
  158. data/lib/active_support/duration/iso8601_parser.rb +123 -0
  159. data/lib/active_support/duration/iso8601_serializer.rb +53 -0
  160. data/lib/active_support/duration.rb +315 -40
  161. data/lib/active_support/encrypted_configuration.rb +45 -0
  162. data/lib/active_support/encrypted_file.rb +100 -0
  163. data/lib/active_support/evented_file_update_checker.rb +234 -0
  164. data/lib/active_support/execution_wrapper.rb +129 -0
  165. data/lib/active_support/executor.rb +8 -0
  166. data/lib/active_support/file_update_checker.rb +62 -37
  167. data/lib/active_support/gem_version.rb +6 -4
  168. data/lib/active_support/gzip.rb +7 -5
  169. data/lib/active_support/hash_with_indifferent_access.rb +129 -30
  170. data/lib/active_support/i18n.rb +9 -6
  171. data/lib/active_support/i18n_railtie.rb +50 -14
  172. data/lib/active_support/inflections.rb +13 -11
  173. data/lib/active_support/inflector/inflections.rb +58 -13
  174. data/lib/active_support/inflector/methods.rb +159 -145
  175. data/lib/active_support/inflector/transliterate.rb +84 -34
  176. data/lib/active_support/inflector.rb +7 -5
  177. data/lib/active_support/json/decoding.rb +32 -30
  178. data/lib/active_support/json/encoding.rb +17 -60
  179. data/lib/active_support/json.rb +4 -2
  180. data/lib/active_support/key_generator.rb +11 -43
  181. data/lib/active_support/lazy_load_hooks.rb +53 -20
  182. data/lib/active_support/locale/en.rb +33 -0
  183. data/lib/active_support/locale/en.yml +2 -0
  184. data/lib/active_support/log_subscriber/test_helper.rb +14 -12
  185. data/lib/active_support/log_subscriber.rb +44 -19
  186. data/lib/active_support/logger.rb +9 -23
  187. data/lib/active_support/logger_silence.rb +32 -14
  188. data/lib/active_support/logger_thread_safe_level.rb +32 -8
  189. data/lib/active_support/message_encryptor.rb +166 -53
  190. data/lib/active_support/message_verifier.rb +149 -16
  191. data/lib/active_support/messages/metadata.rb +72 -0
  192. data/lib/active_support/messages/rotation_configuration.rb +22 -0
  193. data/lib/active_support/messages/rotator.rb +56 -0
  194. data/lib/active_support/multibyte/chars.rb +56 -63
  195. data/lib/active_support/multibyte/unicode.rb +56 -290
  196. data/lib/active_support/multibyte.rb +4 -2
  197. data/lib/active_support/notifications/fanout.rb +109 -22
  198. data/lib/active_support/notifications/instrumenter.rb +107 -16
  199. data/lib/active_support/notifications.rb +51 -10
  200. data/lib/active_support/number_helper/number_converter.rb +16 -15
  201. data/lib/active_support/number_helper/number_to_currency_converter.rb +14 -15
  202. data/lib/active_support/number_helper/number_to_delimited_converter.rb +11 -4
  203. data/lib/active_support/number_helper/number_to_human_converter.rb +13 -10
  204. data/lib/active_support/number_helper/number_to_human_size_converter.rb +11 -9
  205. data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
  206. data/lib/active_support/number_helper/number_to_phone_converter.rb +15 -5
  207. data/lib/active_support/number_helper/number_to_rounded_converter.rb +25 -57
  208. data/lib/active_support/number_helper/rounding_helper.rb +66 -0
  209. data/lib/active_support/number_helper.rb +105 -68
  210. data/lib/active_support/option_merger.rb +24 -4
  211. data/lib/active_support/ordered_hash.rb +7 -5
  212. data/lib/active_support/ordered_options.rb +27 -5
  213. data/lib/active_support/parameter_filter.rb +128 -0
  214. data/lib/active_support/per_thread_registry.rb +9 -4
  215. data/lib/active_support/proxy_object.rb +2 -0
  216. data/lib/active_support/rails.rb +10 -8
  217. data/lib/active_support/railtie.rb +43 -9
  218. data/lib/active_support/reloader.rb +130 -0
  219. data/lib/active_support/rescuable.rb +108 -53
  220. data/lib/active_support/security_utils.rb +15 -11
  221. data/lib/active_support/string_inquirer.rb +11 -4
  222. data/lib/active_support/subscriber.rb +74 -30
  223. data/lib/active_support/tagged_logging.rb +25 -13
  224. data/lib/active_support/test_case.rb +107 -44
  225. data/lib/active_support/testing/assertions.rb +151 -20
  226. data/lib/active_support/testing/autorun.rb +4 -2
  227. data/lib/active_support/testing/constant_lookup.rb +2 -1
  228. data/lib/active_support/testing/declarative.rb +3 -1
  229. data/lib/active_support/testing/deprecation.rb +13 -10
  230. data/lib/active_support/testing/file_fixtures.rb +38 -0
  231. data/lib/active_support/testing/isolation.rb +35 -26
  232. data/lib/active_support/testing/method_call_assertions.rb +70 -0
  233. data/lib/active_support/testing/parallelization.rb +134 -0
  234. data/lib/active_support/testing/setup_and_teardown.rb +13 -8
  235. data/lib/active_support/testing/stream.rb +43 -0
  236. data/lib/active_support/testing/tagged_logging.rb +3 -1
  237. data/lib/active_support/testing/time_helpers.rb +84 -20
  238. data/lib/active_support/time.rb +14 -12
  239. data/lib/active_support/time_with_zone.rb +179 -39
  240. data/lib/active_support/values/time_zone.rb +203 -63
  241. data/lib/active_support/version.rb +3 -1
  242. data/lib/active_support/xml_mini/jdom.rb +116 -115
  243. data/lib/active_support/xml_mini/libxml.rb +16 -13
  244. data/lib/active_support/xml_mini/libxmlsax.rb +15 -14
  245. data/lib/active_support/xml_mini/nokogiri.rb +14 -12
  246. data/lib/active_support/xml_mini/nokogirisax.rb +14 -13
  247. data/lib/active_support/xml_mini/rexml.rb +11 -9
  248. data/lib/active_support/xml_mini.rb +38 -46
  249. data/lib/active_support.rb +13 -11
  250. metadata +84 -26
  251. data/lib/active_support/concurrency/latch.rb +0 -27
  252. data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -16
  253. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
  254. data/lib/active_support/core_ext/date_time/zones.rb +0 -6
  255. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
  256. data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
  257. data/lib/active_support/core_ext/module/method_transplanting.rb +0 -13
  258. data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
  259. data/lib/active_support/core_ext/object/itself.rb +0 -15
  260. data/lib/active_support/core_ext/struct.rb +0 -6
  261. data/lib/active_support/core_ext/thread.rb +0 -86
  262. data/lib/active_support/core_ext/time/marshal.rb +0 -30
  263. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,73 +1,97 @@
1
- require 'set'
2
- require 'thread'
3
- require 'thread_safe'
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'
15
- require 'active_support/inflector'
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
+ require "active_support/core_ext/string/starts_ends_with"
16
+ require "active_support/dependencies/interlock"
17
+ require "active_support/inflector"
16
18
 
17
19
  module ActiveSupport #:nodoc:
18
20
  module Dependencies #:nodoc:
19
21
  extend self
20
22
 
23
+ UNBOUND_METHOD_MODULE_NAME = Module.instance_method(:name)
24
+ private_constant :UNBOUND_METHOD_MODULE_NAME
25
+
26
+ mattr_accessor :interlock, default: Interlock.new
27
+
28
+ # :doc:
29
+
30
+ # Execute the supplied block without interference from any
31
+ # concurrent loads.
32
+ def self.run_interlock
33
+ Dependencies.interlock.running { yield }
34
+ end
35
+
36
+ # Execute the supplied block while holding an exclusive lock,
37
+ # preventing any other thread from being inside a #run_interlock
38
+ # block at the same time.
39
+ def self.load_interlock
40
+ Dependencies.interlock.loading { yield }
41
+ end
42
+
43
+ # Execute the supplied block while holding an exclusive lock,
44
+ # preventing any other thread from being inside a #run_interlock
45
+ # block at the same time.
46
+ def self.unload_interlock
47
+ Dependencies.interlock.unloading { yield }
48
+ end
49
+
50
+ # :nodoc:
51
+
21
52
  # Should we turn on Ruby warnings on the first load of dependent files?
22
- mattr_accessor :warnings_on_first_load
23
- self.warnings_on_first_load = false
53
+ mattr_accessor :warnings_on_first_load, default: false
24
54
 
25
55
  # All files ever loaded.
26
- mattr_accessor :history
27
- self.history = Set.new
56
+ mattr_accessor :history, default: Set.new
28
57
 
29
58
  # All files currently loaded.
30
- mattr_accessor :loaded
31
- self.loaded = Set.new
59
+ mattr_accessor :loaded, default: Set.new
32
60
 
33
61
  # Stack of files being loaded.
34
- mattr_accessor :loading
35
- self.loading = []
62
+ mattr_accessor :loading, default: []
36
63
 
37
64
  # Should we load files or require them?
38
- mattr_accessor :mechanism
39
- self.mechanism = ENV['NO_RELOAD'] ? :require : :load
65
+ mattr_accessor :mechanism, default: ENV["NO_RELOAD"] ? :require : :load
40
66
 
41
67
  # The set of directories from which we may automatically load files. Files
42
68
  # under these directories will be reloaded on each request in development mode,
43
69
  # unless the directory also appears in autoload_once_paths.
44
- mattr_accessor :autoload_paths
45
- self.autoload_paths = []
70
+ mattr_accessor :autoload_paths, default: []
46
71
 
47
72
  # The set of directories from which automatically loaded constants are loaded
48
73
  # only once. All directories in this set must also be present in +autoload_paths+.
49
- mattr_accessor :autoload_once_paths
50
- self.autoload_once_paths = []
74
+ mattr_accessor :autoload_once_paths, default: []
75
+
76
+ # This is a private set that collects all eager load paths during bootstrap.
77
+ # Useful for Zeitwerk integration. Its public interface is the config.* path
78
+ # accessors of each engine.
79
+ mattr_accessor :_eager_load_paths, default: Set.new
51
80
 
52
81
  # An array of qualified constant names that have been loaded. Adding a name
53
82
  # to this array will cause it to be unloaded the next time Dependencies are
54
83
  # cleared.
55
- mattr_accessor :autoloaded_constants
56
- self.autoloaded_constants = []
84
+ mattr_accessor :autoloaded_constants, default: []
57
85
 
58
86
  # An array of constant names that need to be unloaded on every request. Used
59
87
  # to allow arbitrary constants to be marked for unloading.
60
- mattr_accessor :explicitly_unloadable_constants
61
- self.explicitly_unloadable_constants = []
88
+ mattr_accessor :explicitly_unloadable_constants, default: []
62
89
 
63
- # The logger is used for generating information on the action run-time
64
- # (including benchmarking) if available. Can be set to nil for no logging.
65
- # Compatible with both Ruby's own Logger and Log4r loggers.
90
+ # The logger used when tracing autoloads.
66
91
  mattr_accessor :logger
67
92
 
68
- # Set to +true+ to enable logging of const_missing and file loads.
69
- mattr_accessor :log_activity
70
- self.log_activity = false
93
+ # If true, trace autoloads with +logger.debug+.
94
+ mattr_accessor :verbose, default: false
71
95
 
72
96
  # The WatchStack keeps a stack of the modules being watched as files are
73
97
  # loaded. If a file in the process of being loaded (parent.rb) triggers the
@@ -75,7 +99,7 @@ module ActiveSupport #:nodoc:
75
99
  # handles the new constants.
76
100
  #
77
101
  # If child.rb is being autoloaded, its constants will be added to
78
- # autoloaded_constants. If it was being `require`d, they will be discarded.
102
+ # autoloaded_constants. If it was being required, they will be discarded.
79
103
  #
80
104
  # This is handled by walking back up the watch stack and adding the constants
81
105
  # found by child.rb to the list of original constants in parent.rb.
@@ -87,9 +111,11 @@ module ActiveSupport #:nodoc:
87
111
  # parent.rb then requires namespace/child.rb, the stack will look like
88
112
  # [[Object], [Namespace]].
89
113
 
114
+ attr_reader :watching
115
+
90
116
  def initialize
91
117
  @watching = []
92
- @stack = Hash.new { |h,k| h[k] = [] }
118
+ @stack = Hash.new { |h, k| h[k] = [] }
93
119
  end
94
120
 
95
121
  def each(&block)
@@ -115,11 +141,11 @@ module ActiveSupport #:nodoc:
115
141
  next unless mod.is_a?(Module)
116
142
 
117
143
  # Get a list of the constants that were added
118
- new_constants = mod.local_constants - original_constants
144
+ new_constants = mod.constants(false) - original_constants
119
145
 
120
- # self[namespace] returns an Array of the constants that are being evaluated
146
+ # @stack[namespace] returns an Array of the constants that are being evaluated
121
147
  # for that namespace. For instance, if parent.rb requires child.rb, the first
122
- # element of self[Object] will be an Array of the constants that were present
148
+ # element of @stack[Object] will be an Array of the constants that were present
123
149
  # before parent.rb was required. The second element will be an Array of the
124
150
  # constants that were present before child.rb was required.
125
151
  @stack[namespace].each do |namespace_constants|
@@ -143,7 +169,7 @@ module ActiveSupport #:nodoc:
143
169
  @watching << namespaces.map do |namespace|
144
170
  module_name = Dependencies.to_constant_name(namespace)
145
171
  original_constants = Dependencies.qualified_const_defined?(module_name) ?
146
- Inflector.constantize(module_name).local_constants : []
172
+ Inflector.constantize(module_name).constants(false) : []
147
173
 
148
174
  @stack[module_name] << original_constants
149
175
  module_name
@@ -151,14 +177,13 @@ module ActiveSupport #:nodoc:
151
177
  end
152
178
 
153
179
  private
154
- def pop_modules(modules)
155
- modules.each { |mod| @stack[mod].pop }
156
- end
180
+ def pop_modules(modules)
181
+ modules.each { |mod| @stack[mod].pop }
182
+ end
157
183
  end
158
184
 
159
185
  # An internal stack used to record which constants are loaded by any block.
160
- mattr_accessor :constant_watch_stack
161
- self.constant_watch_stack = WatchStack.new
186
+ mattr_accessor :constant_watch_stack, default: WatchStack.new
162
187
 
163
188
  # Module includes this module.
164
189
  module ModuleConstMissing #:nodoc:
@@ -179,6 +204,11 @@ module ActiveSupport #:nodoc:
179
204
  end
180
205
  end
181
206
 
207
+ def self.include_into(base)
208
+ base.include(self)
209
+ append_features(base)
210
+ end
211
+
182
212
  def const_missing(const_name)
183
213
  from_mod = anonymous? ? guess_for_anonymous(const_name) : self
184
214
  Dependencies.load_missing_constant(from_mod, const_name)
@@ -208,6 +238,21 @@ module ActiveSupport #:nodoc:
208
238
  base.class_eval do
209
239
  define_method(:load, Kernel.instance_method(:load))
210
240
  private :load
241
+
242
+ define_method(:require, Kernel.instance_method(:require))
243
+ private :require
244
+ end
245
+ end
246
+
247
+ def self.include_into(base)
248
+ base.include(self)
249
+
250
+ if base.instance_method(:load).owner == base
251
+ base.remove_method(:load)
252
+ end
253
+
254
+ if base.instance_method(:require).owner == base
255
+ base.remove_method(:require)
211
256
  end
212
257
  end
213
258
 
@@ -215,6 +260,8 @@ module ActiveSupport #:nodoc:
215
260
  Dependencies.require_or_load(file_name)
216
261
  end
217
262
 
263
+ # :doc:
264
+
218
265
  # Interprets a file using <tt>mechanism</tt> and marks its defined
219
266
  # constants as autoloaded. <tt>file_name</tt> can be either a string or
220
267
  # respond to <tt>to_path</tt>.
@@ -224,7 +271,7 @@ module ActiveSupport #:nodoc:
224
271
  # resolution deterministic for constants with the same relative name in
225
272
  # different namespaces whose evaluation would depend on load order
226
273
  # otherwise.
227
- def require_dependency(file_name, message = "No such file to load -- %s")
274
+ def require_dependency(file_name, message = "No such file to load -- %s.rb")
228
275
  file_name = file_name.to_path if file_name.respond_to?(:to_path)
229
276
  unless file_name.is_a?(String)
230
277
  raise ArgumentError, "the file name must either be a String or implement #to_path -- you passed #{file_name.inspect}"
@@ -233,9 +280,13 @@ module ActiveSupport #:nodoc:
233
280
  Dependencies.depend_on(file_name, message)
234
281
  end
235
282
 
283
+ # :nodoc:
284
+
236
285
  def load_dependency(file)
237
- if Dependencies.load? && ActiveSupport::Dependencies.constant_watch_stack.watching?
238
- Dependencies.new_constants_in(Object) { yield }
286
+ if Dependencies.load? && Dependencies.constant_watch_stack.watching?
287
+ descs = Dependencies.constant_watch_stack.watching.flatten.uniq
288
+
289
+ Dependencies.new_constants_in(*descs) { yield }
239
290
  else
240
291
  yield
241
292
  end
@@ -262,18 +313,17 @@ module ActiveSupport #:nodoc:
262
313
  end
263
314
 
264
315
  private
316
+ def load(file, wrap = false)
317
+ result = false
318
+ load_dependency(file) { result = super }
319
+ result
320
+ end
265
321
 
266
- def load(file, wrap = false)
267
- result = false
268
- load_dependency(file) { result = super }
269
- result
270
- end
271
-
272
- def require(file)
273
- result = false
274
- load_dependency(file) { result = super }
275
- result
276
- end
322
+ def require(file)
323
+ result = false
324
+ load_dependency(file) { result = super }
325
+ result
326
+ end
277
327
  end
278
328
 
279
329
  # Exception file-blaming.
@@ -298,9 +348,9 @@ module ActiveSupport #:nodoc:
298
348
  end
299
349
 
300
350
  def hook!
301
- Object.class_eval { include Loadable }
302
- Module.class_eval { include ModuleConstMissing }
303
- Exception.class_eval { include Blamable }
351
+ Loadable.include_into(Object)
352
+ ModuleConstMissing.include_into(Module)
353
+ Exception.include(Blamable)
304
354
  end
305
355
 
306
356
  def unhook!
@@ -324,75 +374,77 @@ module ActiveSupport #:nodoc:
324
374
  end
325
375
 
326
376
  def clear
327
- log_call
328
- loaded.clear
329
- loading.clear
330
- remove_unloadable_constants!
377
+ Dependencies.unload_interlock do
378
+ loaded.clear
379
+ loading.clear
380
+ remove_unloadable_constants!
381
+ end
331
382
  end
332
383
 
333
384
  def require_or_load(file_name, const_path = nil)
334
- log_call file_name, const_path
335
- file_name = $` if file_name =~ /\.rb\z/
385
+ file_name = file_name.chomp(".rb")
336
386
  expanded = File.expand_path(file_name)
337
387
  return if loaded.include?(expanded)
338
388
 
339
- # Record that we've seen this file *before* loading it to avoid an
340
- # infinite loop with mutual dependencies.
341
- loaded << expanded
342
- loading << expanded
343
-
344
- begin
345
- if load?
346
- log "loading #{file_name}"
389
+ Dependencies.load_interlock do
390
+ # Maybe it got loaded while we were waiting for our lock:
391
+ return if loaded.include?(expanded)
347
392
 
348
- # Enable warnings if this file has not been loaded before and
349
- # warnings_on_first_load is set.
350
- load_args = ["#{file_name}.rb"]
351
- load_args << const_path unless const_path.nil?
393
+ # Record that we've seen this file *before* loading it to avoid an
394
+ # infinite loop with mutual dependencies.
395
+ loaded << expanded
396
+ loading << expanded
352
397
 
353
- if !warnings_on_first_load or history.include?(expanded)
354
- result = load_file(*load_args)
398
+ begin
399
+ if load?
400
+ # Enable warnings if this file has not been loaded before and
401
+ # warnings_on_first_load is set.
402
+ load_args = ["#{file_name}.rb"]
403
+ load_args << const_path unless const_path.nil?
404
+
405
+ if !warnings_on_first_load || history.include?(expanded)
406
+ result = load_file(*load_args)
407
+ else
408
+ enable_warnings { result = load_file(*load_args) }
409
+ end
355
410
  else
356
- enable_warnings { result = load_file(*load_args) }
411
+ result = require file_name
357
412
  end
358
- else
359
- log "requiring #{file_name}"
360
- result = require file_name
413
+ rescue Exception
414
+ loaded.delete expanded
415
+ raise
416
+ ensure
417
+ loading.pop
361
418
  end
362
- rescue Exception
363
- loaded.delete expanded
364
- raise
365
- ensure
366
- loading.pop
367
- end
368
419
 
369
- # Record history *after* loading so first load gets warnings.
370
- history << expanded
371
- result
420
+ # Record history *after* loading so first load gets warnings.
421
+ history << expanded
422
+ result
423
+ end
372
424
  end
373
425
 
374
426
  # Is the provided constant path defined?
375
427
  def qualified_const_defined?(path)
376
- Object.qualified_const_defined?(path.sub(/^::/, ''), false)
428
+ Object.const_defined?(path, false)
377
429
  end
378
430
 
379
431
  # Given +path+, a filesystem path to a ruby file, return an array of
380
432
  # constant paths which would cause Dependencies to attempt to load this
381
433
  # file.
382
434
  def loadable_constants_for_path(path, bases = autoload_paths)
383
- path = $` if path =~ /\.rb\z/
435
+ path = path.chomp(".rb")
384
436
  expanded_path = File.expand_path(path)
385
437
  paths = []
386
438
 
387
439
  bases.each do |root|
388
440
  expanded_root = File.expand_path(root)
389
- next unless %r{\A#{Regexp.escape(expanded_root)}(/|\\)} =~ expanded_path
441
+ next unless expanded_path.start_with?(expanded_root)
390
442
 
391
- nesting = expanded_path[(expanded_root.size)..-1]
392
- nesting = nesting[1..-1] if nesting && nesting[0] == ?/
393
- next if nesting.blank?
443
+ root_size = expanded_root.size
444
+ next if expanded_path[root_size] != ?/
394
445
 
395
- paths << nesting.camelize
446
+ nesting = expanded_path[(root_size + 1)..-1]
447
+ paths << nesting.camelize unless nesting.blank?
396
448
  end
397
449
 
398
450
  paths.uniq!
@@ -401,7 +453,7 @@ module ActiveSupport #:nodoc:
401
453
 
402
454
  # Search for a file in autoload_paths matching the provided suffix.
403
455
  def search_for_file(path_suffix)
404
- path_suffix = path_suffix.sub(/(\.rb)?$/, ".rb")
456
+ path_suffix += ".rb" unless path_suffix.ends_with?(".rb")
405
457
 
406
458
  autoload_paths.each do |root|
407
459
  path = File.join(root, path_suffix)
@@ -421,7 +473,7 @@ module ActiveSupport #:nodoc:
421
473
  end
422
474
 
423
475
  def load_once_path?(path)
424
- # to_s works around a ruby1.9 issue where String#starts_with?(Pathname)
476
+ # to_s works around a ruby issue where String#starts_with?(Pathname)
425
477
  # will raise a TypeError: no implicit conversion of Pathname into String
426
478
  autoload_once_paths.any? { |base| path.starts_with? base.to_s }
427
479
  end
@@ -435,7 +487,9 @@ module ActiveSupport #:nodoc:
435
487
  return nil unless base_path = autoloadable_module?(path_suffix)
436
488
  mod = Module.new
437
489
  into.const_set const_name, mod
490
+ log("constant #{qualified_name} autoloaded (module autovivified from #{File.join(base_path, path_suffix)})")
438
491
  autoloaded_constants << qualified_name unless autoload_once_paths.include?(base_path)
492
+ autoloaded_constants.uniq!
439
493
  mod
440
494
  end
441
495
 
@@ -448,7 +502,6 @@ module ActiveSupport #:nodoc:
448
502
  # set of names that the file at +path+ may define. See
449
503
  # +loadable_constants_for_path+ for more details.
450
504
  def load_file(path, const_paths = loadable_constants_for_path(path))
451
- log_call path, const_paths
452
505
  const_paths = [const_paths].compact unless const_paths.is_a? Array
453
506
  parent_paths = const_paths.collect { |const_path| const_path[/.*(?=::)/] || ::Object }
454
507
 
@@ -459,7 +512,6 @@ module ActiveSupport #:nodoc:
459
512
 
460
513
  autoloaded_constants.concat newly_defined_paths unless load_once_path?(path)
461
514
  autoloaded_constants.uniq!
462
- log "loading #{path} defined #{newly_defined_paths * ', '}" unless newly_defined_paths.empty?
463
515
  result
464
516
  end
465
517
 
@@ -473,32 +525,35 @@ module ActiveSupport #:nodoc:
473
525
  # it is not possible to load the constant into from_mod, try its parent
474
526
  # module using +const_missing+.
475
527
  def load_missing_constant(from_mod, const_name)
476
- log_call from_mod, const_name
477
-
478
528
  unless qualified_const_defined?(from_mod.name) && Inflector.constantize(from_mod.name).equal?(from_mod)
479
529
  raise ArgumentError, "A copy of #{from_mod} has been removed from the module tree but is still active!"
480
530
  end
481
531
 
482
- qualified_name = qualified_name_for from_mod, const_name
532
+ qualified_name = qualified_name_for(from_mod, const_name)
483
533
  path_suffix = qualified_name.underscore
484
534
 
485
535
  file_path = search_for_file(path_suffix)
486
536
 
487
537
  if file_path
488
538
  expanded = File.expand_path(file_path)
489
- expanded.sub!(/\.rb\z/, '')
539
+ expanded.sub!(/\.rb\z/, "")
490
540
 
491
541
  if loading.include?(expanded)
492
542
  raise "Circular dependency detected while autoloading constant #{qualified_name}"
493
543
  else
494
544
  require_or_load(expanded, qualified_name)
495
- raise LoadError, "Unable to autoload constant #{qualified_name}, expected #{file_path} to define it" unless from_mod.const_defined?(const_name, false)
496
- return from_mod.const_get(const_name)
545
+
546
+ if from_mod.const_defined?(const_name, false)
547
+ log("constant #{qualified_name} autoloaded from #{expanded}.rb")
548
+ return from_mod.const_get(const_name)
549
+ else
550
+ raise LoadError, "Unable to autoload constant #{qualified_name}, expected #{file_path} to define it"
551
+ end
497
552
  end
498
553
  elsif mod = autoload_module!(from_mod, const_name, qualified_name, path_suffix)
499
554
  return mod
500
- elsif (parent = from_mod.parent) && parent != from_mod &&
501
- ! from_mod.parents.any? { |p| p.const_defined?(const_name, false) }
555
+ elsif (parent = from_mod.module_parent) && parent != from_mod &&
556
+ ! from_mod.module_parents.any? { |p| p.const_defined?(const_name, false) }
502
557
  # If our parents do not have a constant named +const_name+ then we are free
503
558
  # to attempt to load upwards. If they do have such a constant, then this
504
559
  # const_missing must be due to from_mod::const_name, which should not
@@ -530,7 +585,7 @@ module ActiveSupport #:nodoc:
530
585
  end
531
586
 
532
587
  name_error = NameError.new("uninitialized constant #{qualified_name}", const_name)
533
- name_error.set_backtrace(caller.reject {|l| l.starts_with? __FILE__ })
588
+ name_error.set_backtrace(caller.reject { |l| l.starts_with? __FILE__ })
534
589
  raise name_error
535
590
  end
536
591
 
@@ -542,6 +597,7 @@ module ActiveSupport #:nodoc:
542
597
  # as the environment will be in an inconsistent state, e.g. other constants
543
598
  # may have already been unloaded and not accessible.
544
599
  def remove_unloadable_constants!
600
+ log("removing unloadable constants")
545
601
  autoloaded_constants.each { |const| remove_constant const }
546
602
  autoloaded_constants.clear
547
603
  Reference.clear!
@@ -550,7 +606,7 @@ module ActiveSupport #:nodoc:
550
606
 
551
607
  class ClassCache
552
608
  def initialize
553
- @store = ThreadSafe::Cache.new
609
+ @store = Concurrent::Map.new
554
610
  end
555
611
 
556
612
  def empty?
@@ -574,7 +630,7 @@ module ActiveSupport #:nodoc:
574
630
 
575
631
  def store(klass)
576
632
  return self unless klass.respond_to?(:name)
577
- raise(ArgumentError, 'anonymous classes cannot be cached') if klass.name.empty?
633
+ raise(ArgumentError, "anonymous classes cannot be cached") if klass.name.empty?
578
634
  @store[klass.name] = klass
579
635
  self
580
636
  end
@@ -605,10 +661,10 @@ module ActiveSupport #:nodoc:
605
661
 
606
662
  # Determine if the given constant has been automatically loaded.
607
663
  def autoloaded?(desc)
608
- return false if desc.is_a?(Module) && desc.anonymous?
664
+ return false if desc.is_a?(Module) && real_mod_name(desc).nil?
609
665
  name = to_constant_name desc
610
- return false unless qualified_const_defined? name
611
- return autoloaded_constants.include?(name)
666
+ return false unless qualified_const_defined?(name)
667
+ autoloaded_constants.include?(name)
612
668
  end
613
669
 
614
670
  # Will the provided constant descriptor be unloaded?
@@ -638,54 +694,49 @@ module ActiveSupport #:nodoc:
638
694
  # exception, any new constants are regarded as being only partially defined
639
695
  # and will be removed immediately.
640
696
  def new_constants_in(*descs)
641
- log_call(*descs)
642
-
643
697
  constant_watch_stack.watch_namespaces(descs)
644
- aborting = true
698
+ success = false
645
699
 
646
700
  begin
647
701
  yield # Now yield to the code that is to define new constants.
648
- aborting = false
702
+ success = true
649
703
  ensure
650
704
  new_constants = constant_watch_stack.new_constants
651
705
 
652
- log "New constants: #{new_constants * ', '}"
653
- return new_constants unless aborting
706
+ return new_constants if success
654
707
 
655
- log "Error during loading, removing partially loaded constants "
656
- new_constants.each { |c| remove_constant(c) }.clear
708
+ # Remove partially loaded constants.
709
+ new_constants.each { |c| remove_constant(c) }
657
710
  end
658
-
659
- []
660
711
  end
661
712
 
662
713
  # Convert the provided const desc to a qualified constant name (as a string).
663
714
  # A module, class, symbol, or string may be provided.
664
715
  def to_constant_name(desc) #:nodoc:
665
716
  case desc
666
- when String then desc.sub(/^::/, '')
667
- when Symbol then desc.to_s
668
- when Module
669
- desc.name ||
670
- raise(ArgumentError, "Anonymous modules have no name to be referenced by")
671
- else raise TypeError, "Not a valid constant descriptor: #{desc.inspect}"
717
+ when String then desc.sub(/^::/, "")
718
+ when Symbol then desc.to_s
719
+ when Module
720
+ real_mod_name(desc) ||
721
+ raise(ArgumentError, "Anonymous modules have no name to be referenced by")
722
+ else raise TypeError, "Not a valid constant descriptor: #{desc.inspect}"
672
723
  end
673
724
  end
674
725
 
675
726
  def remove_constant(const) #:nodoc:
676
727
  # Normalize ::Foo, ::Object::Foo, Object::Foo, Object::Object::Foo, etc. as Foo.
677
- normalized = const.to_s.sub(/\A::/, '')
678
- normalized.sub!(/\A(Object::)+/, '')
728
+ normalized = const.to_s.sub(/\A::/, "")
729
+ normalized.sub!(/\A(Object::)+/, "")
679
730
 
680
- constants = normalized.split('::')
731
+ constants = normalized.split("::")
681
732
  to_remove = constants.pop
682
733
 
683
734
  # Remove the file path from the loaded list.
684
735
  file_path = search_for_file(const.underscore)
685
736
  if file_path
686
737
  expanded = File.expand_path(file_path)
687
- expanded.sub!(/\.rb\z/, '')
688
- self.loaded.delete(expanded)
738
+ expanded.sub!(/\.rb\z/, "")
739
+ loaded.delete(expanded)
689
740
  end
690
741
 
691
742
  if constants.empty?
@@ -698,13 +749,11 @@ module ActiveSupport #:nodoc:
698
749
  # here than require the caller to be clever. We check the parent
699
750
  # rather than the very const argument because we do not want to
700
751
  # trigger Kernel#autoloads, see the comment below.
701
- parent_name = constants.join('::')
752
+ parent_name = constants.join("::")
702
753
  return unless qualified_const_defined?(parent_name)
703
754
  parent = constantize(parent_name)
704
755
  end
705
756
 
706
- log "removing constant #{const}"
707
-
708
757
  # In an autoloaded user.rb like this
709
758
  #
710
759
  # autoload :Foo, 'foo'
@@ -725,7 +774,7 @@ module ActiveSupport #:nodoc:
725
774
  begin
726
775
  constantized = parent.const_get(to_remove, false)
727
776
  rescue NameError
728
- log "the constant #{const} is not reachable anymore, skipping"
777
+ # The constant is no longer reachable, just skip it.
729
778
  return
730
779
  else
731
780
  constantized.before_remove_const if constantized.respond_to?(:before_remove_const)
@@ -735,26 +784,19 @@ module ActiveSupport #:nodoc:
735
784
  begin
736
785
  parent.instance_eval { remove_const to_remove }
737
786
  rescue NameError
738
- log "the constant #{const} is not reachable anymore, skipping"
787
+ # The constant is no longer reachable, just skip it.
739
788
  end
740
789
  end
741
790
 
742
- protected
743
- def log_call(*args)
744
- if log_activity?
745
- arg_str = args.collect { |arg| arg.inspect } * ', '
746
- /in `([a-z_\?\!]+)'/ =~ caller(1).first
747
- selector = $1 || '<unknown>'
748
- log "called #{selector}(#{arg_str})"
749
- end
750
- end
751
-
752
- def log(msg)
753
- logger.debug "Dependencies: #{msg}" if log_activity?
754
- end
791
+ def log(message)
792
+ logger.debug("autoloading: #{message}") if logger && verbose
793
+ end
755
794
 
756
- def log_activity?
757
- logger && log_activity
795
+ private
796
+ # Returns the original name of a class or module even if `name` has been
797
+ # overridden.
798
+ def real_mod_name(mod)
799
+ UNBOUND_METHOD_MODULE_NAME.bind(mod).call
758
800
  end
759
801
  end
760
802
  end