activesupport 4.0.12 → 7.0.2.4

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 (295) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +249 -501
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +10 -5
  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 +41 -13
  9. data/lib/active_support/benchmarkable.rb +7 -15
  10. data/lib/active_support/builder.rb +3 -1
  11. data/lib/active_support/cache/file_store.rb +96 -74
  12. data/lib/active_support/cache/mem_cache_store.rb +211 -103
  13. data/lib/active_support/cache/memory_store.rb +90 -58
  14. data/lib/active_support/cache/null_store.rb +19 -7
  15. data/lib/active_support/cache/redis_cache_store.rb +468 -0
  16. data/lib/active_support/cache/strategy/local_cache.rb +86 -83
  17. data/lib/active_support/cache/strategy/local_cache_middleware.rb +45 -0
  18. data/lib/active_support/cache.rb +580 -241
  19. data/lib/active_support/callbacks.rb +812 -425
  20. data/lib/active_support/code_generator.rb +65 -0
  21. data/lib/active_support/concern.rb +103 -14
  22. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +33 -0
  23. data/lib/active_support/concurrency/share_lock.rb +226 -0
  24. data/lib/active_support/configurable.rb +21 -19
  25. data/lib/active_support/configuration_file.rb +51 -0
  26. data/lib/active_support/core_ext/array/access.rb +47 -1
  27. data/lib/active_support/core_ext/array/conversions.rb +35 -44
  28. data/lib/active_support/core_ext/array/deprecated_conversions.rb +25 -0
  29. data/lib/active_support/core_ext/array/extract.rb +21 -0
  30. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  31. data/lib/active_support/core_ext/array/grouping.rb +26 -16
  32. data/lib/active_support/core_ext/array/inquiry.rb +19 -0
  33. data/lib/active_support/core_ext/array/wrap.rb +7 -4
  34. data/lib/active_support/core_ext/array.rb +10 -7
  35. data/lib/active_support/core_ext/benchmark.rb +5 -3
  36. data/lib/active_support/core_ext/big_decimal/conversions.rb +9 -26
  37. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  38. data/lib/active_support/core_ext/class/attribute.rb +52 -49
  39. data/lib/active_support/core_ext/class/attribute_accessors.rb +5 -169
  40. data/lib/active_support/core_ext/class/subclasses.rb +25 -26
  41. data/lib/active_support/core_ext/class.rb +4 -4
  42. data/lib/active_support/core_ext/date/acts_like.rb +3 -1
  43. data/lib/active_support/core_ext/date/blank.rb +14 -0
  44. data/lib/active_support/core_ext/date/calculations.rb +31 -18
  45. data/lib/active_support/core_ext/date/conversions.rb +43 -32
  46. data/lib/active_support/core_ext/date/deprecated_conversions.rb +26 -0
  47. data/lib/active_support/core_ext/date/zones.rb +5 -34
  48. data/lib/active_support/core_ext/date.rb +7 -4
  49. data/lib/active_support/core_ext/date_and_time/calculations.rb +198 -66
  50. data/lib/active_support/core_ext/date_and_time/compatibility.rb +31 -0
  51. data/lib/active_support/core_ext/date_and_time/zones.rb +40 -0
  52. data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
  53. data/lib/active_support/core_ext/date_time/blank.rb +14 -0
  54. data/lib/active_support/core_ext/date_time/calculations.rb +79 -38
  55. data/lib/active_support/core_ext/date_time/compatibility.rb +18 -0
  56. data/lib/active_support/core_ext/date_time/conversions.rb +31 -26
  57. data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +22 -0
  58. data/lib/active_support/core_ext/date_time.rb +8 -4
  59. data/lib/active_support/core_ext/digest/uuid.rb +79 -0
  60. data/lib/active_support/core_ext/digest.rb +3 -0
  61. data/lib/active_support/core_ext/enumerable.rb +249 -17
  62. data/lib/active_support/core_ext/file/atomic.rb +41 -32
  63. data/lib/active_support/core_ext/file.rb +3 -1
  64. data/lib/active_support/core_ext/hash/conversions.rb +71 -49
  65. data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
  66. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  67. data/lib/active_support/core_ext/hash/except.rb +14 -5
  68. data/lib/active_support/core_ext/hash/indifferent_access.rb +5 -3
  69. data/lib/active_support/core_ext/hash/keys.rb +39 -56
  70. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  71. data/lib/active_support/core_ext/hash/slice.rb +8 -23
  72. data/lib/active_support/core_ext/hash.rb +10 -8
  73. data/lib/active_support/core_ext/integer/inflections.rb +3 -1
  74. data/lib/active_support/core_ext/integer/multiple.rb +3 -1
  75. data/lib/active_support/core_ext/integer/time.rb +11 -33
  76. data/lib/active_support/core_ext/integer.rb +5 -3
  77. data/lib/active_support/core_ext/kernel/concern.rb +14 -0
  78. data/lib/active_support/core_ext/kernel/reporting.rb +9 -78
  79. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  80. data/lib/active_support/core_ext/kernel.rb +5 -4
  81. data/lib/active_support/core_ext/load_error.rb +5 -21
  82. data/lib/active_support/core_ext/module/aliasing.rb +6 -44
  83. data/lib/active_support/core_ext/module/anonymous.rb +12 -1
  84. data/lib/active_support/core_ext/module/attr_internal.rb +8 -8
  85. data/lib/active_support/core_ext/module/attribute_accessors.rb +186 -44
  86. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +157 -0
  87. data/lib/active_support/core_ext/module/concerning.rb +140 -0
  88. data/lib/active_support/core_ext/module/delegation.rb +172 -45
  89. data/lib/active_support/core_ext/module/deprecation.rb +3 -3
  90. data/lib/active_support/core_ext/module/introspection.rb +23 -38
  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 -10
  94. data/lib/active_support/core_ext/name_error.rb +45 -4
  95. data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
  96. data/lib/active_support/core_ext/numeric/conversions.rb +135 -127
  97. data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +60 -0
  98. data/lib/active_support/core_ext/numeric/time.rb +37 -50
  99. data/lib/active_support/core_ext/numeric.rb +6 -3
  100. data/lib/active_support/core_ext/object/acts_like.rb +41 -6
  101. data/lib/active_support/core_ext/object/blank.rb +70 -20
  102. data/lib/active_support/core_ext/object/conversions.rb +6 -4
  103. data/lib/active_support/core_ext/object/deep_dup.rb +19 -10
  104. data/lib/active_support/core_ext/object/duplicable.rb +17 -47
  105. data/lib/active_support/core_ext/object/inclusion.rb +18 -15
  106. data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
  107. data/lib/active_support/core_ext/object/json.rb +244 -0
  108. data/lib/active_support/core_ext/object/to_param.rb +3 -1
  109. data/lib/active_support/core_ext/object/to_query.rb +21 -8
  110. data/lib/active_support/core_ext/object/try.rb +106 -26
  111. data/lib/active_support/core_ext/object/with_options.rb +64 -5
  112. data/lib/active_support/core_ext/object.rb +14 -12
  113. data/lib/active_support/core_ext/pathname/existence.rb +21 -0
  114. data/lib/active_support/core_ext/pathname.rb +3 -0
  115. data/lib/active_support/core_ext/range/compare_range.rb +57 -0
  116. data/lib/active_support/core_ext/range/conversions.rb +37 -15
  117. data/lib/active_support/core_ext/range/deprecated_conversions.rb +26 -0
  118. data/lib/active_support/core_ext/range/each.rb +18 -17
  119. data/lib/active_support/core_ext/range/include_time_with_zone.rb +7 -0
  120. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  121. data/lib/active_support/core_ext/range.rb +7 -4
  122. data/lib/active_support/core_ext/regexp.rb +10 -1
  123. data/lib/active_support/core_ext/securerandom.rb +45 -0
  124. data/lib/active_support/core_ext/string/access.rb +42 -51
  125. data/lib/active_support/core_ext/string/behavior.rb +3 -1
  126. data/lib/active_support/core_ext/string/conversions.rb +18 -13
  127. data/lib/active_support/core_ext/string/exclude.rb +5 -3
  128. data/lib/active_support/core_ext/string/filters.rb +97 -7
  129. data/lib/active_support/core_ext/string/indent.rb +6 -4
  130. data/lib/active_support/core_ext/string/inflections.rb +106 -25
  131. data/lib/active_support/core_ext/string/inquiry.rb +4 -1
  132. data/lib/active_support/core_ext/string/multibyte.rb +18 -9
  133. data/lib/active_support/core_ext/string/output_safety.rb +227 -54
  134. data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
  135. data/lib/active_support/core_ext/string/strip.rb +6 -5
  136. data/lib/active_support/core_ext/string/zones.rb +4 -1
  137. data/lib/active_support/core_ext/string.rb +15 -13
  138. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +6 -0
  139. data/lib/active_support/core_ext/symbol.rb +3 -0
  140. data/lib/active_support/core_ext/time/acts_like.rb +3 -1
  141. data/lib/active_support/core_ext/time/calculations.rb +178 -116
  142. data/lib/active_support/core_ext/time/compatibility.rb +16 -0
  143. data/lib/active_support/core_ext/time/conversions.rb +37 -25
  144. data/lib/active_support/core_ext/time/deprecated_conversions.rb +22 -0
  145. data/lib/active_support/core_ext/time/zones.rb +44 -42
  146. data/lib/active_support/core_ext/time.rb +8 -5
  147. data/lib/active_support/core_ext/uri.rb +4 -25
  148. data/lib/active_support/core_ext.rb +4 -2
  149. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  150. data/lib/active_support/current_attributes.rb +226 -0
  151. data/lib/active_support/dependencies/autoload.rb +3 -1
  152. data/lib/active_support/dependencies/interlock.rb +49 -0
  153. data/lib/active_support/dependencies/require_dependency.rb +28 -0
  154. data/lib/active_support/dependencies.rb +71 -696
  155. data/lib/active_support/deprecation/behaviors.rb +65 -16
  156. data/lib/active_support/deprecation/constant_accessor.rb +52 -0
  157. data/lib/active_support/deprecation/disallowed.rb +56 -0
  158. data/lib/active_support/deprecation/instance_delegator.rb +16 -2
  159. data/lib/active_support/deprecation/method_wrappers.rb +62 -21
  160. data/lib/active_support/deprecation/proxy_wrappers.rb +82 -31
  161. data/lib/active_support/deprecation/reporting.rb +81 -18
  162. data/lib/active_support/deprecation.rb +19 -11
  163. data/lib/active_support/descendants_tracker.rb +192 -34
  164. data/lib/active_support/digest.rb +22 -0
  165. data/lib/active_support/duration/iso8601_parser.rb +123 -0
  166. data/lib/active_support/duration/iso8601_serializer.rb +67 -0
  167. data/lib/active_support/duration.rb +437 -39
  168. data/lib/active_support/encrypted_configuration.rb +56 -0
  169. data/lib/active_support/encrypted_file.rb +117 -0
  170. data/lib/active_support/environment_inquirer.rb +20 -0
  171. data/lib/active_support/error_reporter.rb +117 -0
  172. data/lib/active_support/evented_file_update_checker.rb +170 -0
  173. data/lib/active_support/execution_context/test_helper.rb +13 -0
  174. data/lib/active_support/execution_context.rb +53 -0
  175. data/lib/active_support/execution_wrapper.rb +151 -0
  176. data/lib/active_support/executor/test_helper.rb +7 -0
  177. data/lib/active_support/executor.rb +8 -0
  178. data/lib/active_support/file_update_checker.rb +62 -37
  179. data/lib/active_support/fork_tracker.rb +71 -0
  180. data/lib/active_support/gem_version.rb +17 -0
  181. data/lib/active_support/gzip.rb +7 -5
  182. data/lib/active_support/hash_with_indifferent_access.rb +207 -54
  183. data/lib/active_support/html_safe_translation.rb +43 -0
  184. data/lib/active_support/i18n.rb +10 -6
  185. data/lib/active_support/i18n_railtie.rb +48 -19
  186. data/lib/active_support/inflections.rb +19 -12
  187. data/lib/active_support/inflector/inflections.rb +97 -37
  188. data/lib/active_support/inflector/methods.rb +192 -157
  189. data/lib/active_support/inflector/transliterate.rb +83 -33
  190. data/lib/active_support/inflector.rb +7 -5
  191. data/lib/active_support/isolated_execution_state.rb +64 -0
  192. data/lib/active_support/json/decoding.rb +37 -42
  193. data/lib/active_support/json/encoding.rb +93 -293
  194. data/lib/active_support/json.rb +4 -2
  195. data/lib/active_support/key_generator.rb +30 -47
  196. data/lib/active_support/lazy_load_hooks.rb +54 -21
  197. data/lib/active_support/locale/en.rb +33 -0
  198. data/lib/active_support/locale/en.yml +10 -4
  199. data/lib/active_support/log_subscriber/test_helper.rb +14 -12
  200. data/lib/active_support/log_subscriber.rb +61 -18
  201. data/lib/active_support/logger.rb +40 -4
  202. data/lib/active_support/logger_silence.rb +17 -20
  203. data/lib/active_support/logger_thread_safe_level.rb +69 -0
  204. data/lib/active_support/message_encryptor.rb +178 -55
  205. data/lib/active_support/message_verifier.rb +195 -26
  206. data/lib/active_support/messages/metadata.rb +80 -0
  207. data/lib/active_support/messages/rotation_configuration.rb +23 -0
  208. data/lib/active_support/messages/rotator.rb +57 -0
  209. data/lib/active_support/multibyte/chars.rb +45 -92
  210. data/lib/active_support/multibyte/unicode.rb +44 -377
  211. data/lib/active_support/multibyte.rb +5 -3
  212. data/lib/active_support/notifications/fanout.rb +177 -44
  213. data/lib/active_support/notifications/instrumenter.rb +117 -17
  214. data/lib/active_support/notifications.rb +106 -39
  215. data/lib/active_support/number_helper/number_converter.rb +181 -0
  216. data/lib/active_support/number_helper/number_to_currency_converter.rb +46 -0
  217. data/lib/active_support/number_helper/number_to_delimited_converter.rb +30 -0
  218. data/lib/active_support/number_helper/number_to_human_converter.rb +69 -0
  219. data/lib/active_support/number_helper/number_to_human_size_converter.rb +60 -0
  220. data/lib/active_support/number_helper/number_to_percentage_converter.rb +16 -0
  221. data/lib/active_support/number_helper/number_to_phone_converter.rb +59 -0
  222. data/lib/active_support/number_helper/number_to_rounded_converter.rb +59 -0
  223. data/lib/active_support/number_helper/rounding_helper.rb +46 -0
  224. data/lib/active_support/number_helper.rb +152 -394
  225. data/lib/active_support/option_merger.rb +18 -5
  226. data/lib/active_support/ordered_hash.rb +8 -6
  227. data/lib/active_support/ordered_options.rb +43 -7
  228. data/lib/active_support/parameter_filter.rb +138 -0
  229. data/lib/active_support/per_thread_registry.rb +24 -11
  230. data/lib/active_support/proxy_object.rb +2 -0
  231. data/lib/active_support/rails.rb +10 -11
  232. data/lib/active_support/railtie.rb +118 -12
  233. data/lib/active_support/reloader.rb +130 -0
  234. data/lib/active_support/rescuable.rb +112 -57
  235. data/lib/active_support/ruby_features.rb +7 -0
  236. data/lib/active_support/secure_compare_rotator.rb +51 -0
  237. data/lib/active_support/security_utils.rb +38 -0
  238. data/lib/active_support/string_inquirer.rb +11 -4
  239. data/lib/active_support/subscriber.rb +109 -39
  240. data/lib/active_support/tagged_logging.rb +54 -17
  241. data/lib/active_support/test_case.rb +121 -37
  242. data/lib/active_support/testing/assertions.rb +177 -39
  243. data/lib/active_support/testing/autorun.rb +5 -3
  244. data/lib/active_support/testing/constant_lookup.rb +3 -6
  245. data/lib/active_support/testing/declarative.rb +10 -22
  246. data/lib/active_support/testing/deprecation.rb +65 -11
  247. data/lib/active_support/testing/file_fixtures.rb +38 -0
  248. data/lib/active_support/testing/isolation.rb +56 -87
  249. data/lib/active_support/testing/method_call_assertions.rb +70 -0
  250. data/lib/active_support/testing/parallelization/server.rb +82 -0
  251. data/lib/active_support/testing/parallelization/worker.rb +103 -0
  252. data/lib/active_support/testing/parallelization.rb +55 -0
  253. data/lib/active_support/testing/parallelize_executor.rb +76 -0
  254. data/lib/active_support/testing/setup_and_teardown.rb +30 -10
  255. data/lib/active_support/testing/stream.rb +41 -0
  256. data/lib/active_support/testing/tagged_logging.rb +6 -4
  257. data/lib/active_support/testing/time_helpers.rb +246 -0
  258. data/lib/active_support/time.rb +13 -13
  259. data/lib/active_support/time_with_zone.rb +315 -90
  260. data/lib/active_support/values/time_zone.rb +306 -135
  261. data/lib/active_support/version.rb +6 -7
  262. data/lib/active_support/xml_mini/jdom.rb +117 -115
  263. data/lib/active_support/xml_mini/libxml.rb +22 -21
  264. data/lib/active_support/xml_mini/libxmlsax.rb +17 -19
  265. data/lib/active_support/xml_mini/nokogiri.rb +19 -19
  266. data/lib/active_support/xml_mini/nokogirisax.rb +16 -17
  267. data/lib/active_support/xml_mini/rexml.rb +25 -17
  268. data/lib/active_support/xml_mini.rb +67 -56
  269. data/lib/active_support.rb +58 -3
  270. metadata +125 -66
  271. data/lib/active_support/basic_object.rb +0 -11
  272. data/lib/active_support/buffered_logger.rb +0 -21
  273. data/lib/active_support/concurrency/latch.rb +0 -27
  274. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
  275. data/lib/active_support/core_ext/array/uniq_by.rb +0 -19
  276. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -40
  277. data/lib/active_support/core_ext/date_time/zones.rb +0 -24
  278. data/lib/active_support/core_ext/hash/diff.rb +0 -14
  279. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
  280. data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
  281. data/lib/active_support/core_ext/logger.rb +0 -67
  282. data/lib/active_support/core_ext/marshal.rb +0 -21
  283. data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
  284. data/lib/active_support/core_ext/module/reachable.rb +0 -8
  285. data/lib/active_support/core_ext/object/to_json.rb +0 -27
  286. data/lib/active_support/core_ext/proc.rb +0 -17
  287. data/lib/active_support/core_ext/range/include_range.rb +0 -23
  288. data/lib/active_support/core_ext/string/encoding.rb +0 -8
  289. data/lib/active_support/core_ext/struct.rb +0 -6
  290. data/lib/active_support/core_ext/thread.rb +0 -79
  291. data/lib/active_support/core_ext/time/marshal.rb +0 -30
  292. data/lib/active_support/file_watcher.rb +0 -36
  293. data/lib/active_support/json/variable.rb +0 -18
  294. data/lib/active_support/testing/pending.rb +0 -14
  295. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,3 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/time/calculations"
4
+
1
5
  module ActiveSupport
2
6
  # FileUpdateChecker specifies the API used by Rails to watch files
3
7
  # and control reloading. The API depends on four methods:
@@ -23,7 +27,7 @@ module ActiveSupport
23
27
  # I18n.reload!
24
28
  # end
25
29
  #
26
- # ActionDispatch::Reloader.to_prepare do
30
+ # ActiveSupport::Reloader.to_prepare do
27
31
  # i18n_reloader.execute_if_updated
28
32
  # end
29
33
  class FileUpdateChecker
@@ -35,7 +39,11 @@ module ActiveSupport
35
39
  # This method must also receive a block that will be called once a path
36
40
  # changes. The array of files and list of directories cannot be changed
37
41
  # after FileUpdateChecker has been initialized.
38
- def initialize(files, dirs={}, &block)
42
+ def initialize(files, dirs = {}, &block)
43
+ unless block
44
+ raise ArgumentError, "A block is required to initialize a FileUpdateChecker"
45
+ end
46
+
39
47
  @files = files.freeze
40
48
  @glob = compile_glob(dirs)
41
49
  @block = block
@@ -81,6 +89,7 @@ module ActiveSupport
81
89
  # Execute the block given if updated.
82
90
  def execute_if_updated
83
91
  if updated?
92
+ yield if block_given?
84
93
  execute
85
94
  true
86
95
  else
@@ -89,49 +98,65 @@ module ActiveSupport
89
98
  end
90
99
 
91
100
  private
101
+ def watched
102
+ @watched || begin
103
+ all = @files.select { |f| File.exist?(f) }
104
+ all.concat(Dir[@glob]) if @glob
105
+ all
106
+ end
107
+ end
92
108
 
93
- def watched
94
- @watched || begin
95
- all = @files.select { |f| File.exist?(f) }
96
- all.concat(Dir[@glob]) if @glob
97
- all
109
+ def updated_at(paths)
110
+ @updated_at || max_mtime(paths) || Time.at(0)
98
111
  end
99
- end
100
112
 
101
- def updated_at(paths)
102
- @updated_at || max_mtime(paths) || Time.at(0)
103
- end
113
+ # This method returns the maximum mtime of the files in +paths+, or +nil+
114
+ # if the array is empty.
115
+ #
116
+ # Files with a mtime in the future are ignored. Such abnormal situation
117
+ # can happen for example if the user changes the clock by hand. It is
118
+ # healthy to consider this edge case because with mtimes in the future
119
+ # reloading is not triggered.
120
+ def max_mtime(paths)
121
+ time_now = Time.now
122
+ max_mtime = nil
104
123
 
105
- # This method returns the maximum mtime of the files in +paths+, or +nil+
106
- # if the array is empty.
107
- #
108
- # Files with a mtime in the future are ignored. Such abnormal situation
109
- # can happen for example if the user changes the clock by hand. It is
110
- # healthy to consider this edge case because with mtimes in the future
111
- # reloading is not triggered.
112
- def max_mtime(paths)
113
- time_now = Time.now
114
- paths.map {|path| File.mtime(path)}.reject {|mtime| time_now < mtime}.max
115
- end
124
+ # Time comparisons are performed with #compare_without_coercion because
125
+ # AS redefines these operators in a way that is much slower and does not
126
+ # bring any benefit in this particular code.
127
+ #
128
+ # Read t1.compare_without_coercion(t2) < 0 as t1 < t2.
129
+ paths.each do |path|
130
+ mtime = File.mtime(path)
116
131
 
117
- def compile_glob(hash)
118
- hash.freeze # Freeze so changes aren't accidently pushed
119
- return if hash.empty?
132
+ next if time_now.compare_without_coercion(mtime) < 0
120
133
 
121
- globs = hash.map do |key, value|
122
- "#{escape(key)}/**/*#{compile_ext(value)}"
134
+ if max_mtime.nil? || max_mtime.compare_without_coercion(mtime) < 0
135
+ max_mtime = mtime
136
+ end
137
+ end
138
+
139
+ max_mtime
123
140
  end
124
- "{#{globs.join(",")}}"
125
- end
126
141
 
127
- def escape(key)
128
- key.gsub(',','\,')
129
- end
142
+ def compile_glob(hash)
143
+ hash.freeze # Freeze so changes aren't accidentally pushed
144
+ return if hash.empty?
130
145
 
131
- def compile_ext(array)
132
- array = Array(array)
133
- return if array.empty?
134
- ".{#{array.join(",")}}"
135
- end
146
+ globs = hash.map do |key, value|
147
+ "#{escape(key)}/**/*#{compile_ext(value)}"
148
+ end
149
+ "{#{globs.join(",")}}"
150
+ end
151
+
152
+ def escape(key)
153
+ key.gsub(",", '\,')
154
+ end
155
+
156
+ def compile_ext(array)
157
+ array = Array(array)
158
+ return if array.empty?
159
+ ".{#{array.join(",")}}"
160
+ end
136
161
  end
137
162
  end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ module ForkTracker # :nodoc:
5
+ module ModernCoreExt
6
+ def _fork
7
+ pid = super
8
+ if pid == 0
9
+ ForkTracker.check!
10
+ end
11
+ pid
12
+ end
13
+ end
14
+
15
+ module CoreExt
16
+ def fork(...)
17
+ if block_given?
18
+ super do
19
+ ForkTracker.check!
20
+ yield
21
+ end
22
+ else
23
+ unless pid = super
24
+ ForkTracker.check!
25
+ end
26
+ pid
27
+ end
28
+ end
29
+ end
30
+
31
+ module CoreExtPrivate
32
+ include CoreExt
33
+ private :fork
34
+ end
35
+
36
+ @pid = Process.pid
37
+ @callbacks = []
38
+
39
+ class << self
40
+ def check!
41
+ new_pid = Process.pid
42
+ if @pid != new_pid
43
+ @callbacks.each(&:call)
44
+ @pid = new_pid
45
+ end
46
+ end
47
+
48
+ def hook!
49
+ if Process.respond_to?(:_fork) # Ruby 3.1+
50
+ ::Process.singleton_class.prepend(ModernCoreExt)
51
+ elsif Process.respond_to?(:fork)
52
+ ::Object.prepend(CoreExtPrivate) if RUBY_VERSION < "3.0"
53
+ ::Kernel.prepend(CoreExtPrivate)
54
+ ::Kernel.singleton_class.prepend(CoreExt)
55
+ ::Process.singleton_class.prepend(CoreExt)
56
+ end
57
+ end
58
+
59
+ def after_fork(&block)
60
+ @callbacks << block
61
+ block
62
+ end
63
+
64
+ def unregister(callback)
65
+ @callbacks.delete(callback)
66
+ end
67
+ end
68
+ end
69
+ end
70
+
71
+ ActiveSupport::ForkTracker.hook!
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ # Returns the version of the currently loaded Active Support as a <tt>Gem::Version</tt>.
5
+ def self.gem_version
6
+ Gem::Version.new VERSION::STRING
7
+ end
8
+
9
+ module VERSION
10
+ MAJOR = 7
11
+ MINOR = 0
12
+ TINY = 2
13
+ PRE = "4"
14
+
15
+ STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
+ end
17
+ end
@@ -1,5 +1,7 @@
1
- require 'zlib'
2
- require 'stringio'
1
+ # frozen_string_literal: true
2
+
3
+ require "zlib"
4
+ require "stringio"
3
5
 
4
6
  module ActiveSupport
5
7
  # A convenient wrapper for the zlib standard library that allows
@@ -9,7 +11,7 @@ module ActiveSupport
9
11
  # # => "\x1F\x8B\b\x00o\x8D\xCDO\x00\x03K\xCE\xCF-(J-.V\xC8MU\x04\x00R>n\x83\f\x00\x00\x00"
10
12
  #
11
13
  # ActiveSupport::Gzip.decompress(gzip)
12
- # # => "compress me!"
14
+ # # => "compress me!"
13
15
  module Gzip
14
16
  class Stream < StringIO
15
17
  def initialize(*)
@@ -21,11 +23,11 @@ module ActiveSupport
21
23
 
22
24
  # Decompresses a gzipped string.
23
25
  def self.decompress(source)
24
- Zlib::GzipReader.new(StringIO.new(source)).read
26
+ Zlib::GzipReader.wrap(StringIO.new(source), &:read)
25
27
  end
26
28
 
27
29
  # Compresses a string using gzip.
28
- def self.compress(source, level=Zlib::DEFAULT_COMPRESSION, strategy=Zlib::DEFAULT_STRATEGY)
30
+ def self.compress(source, level = Zlib::DEFAULT_COMPRESSION, strategy = Zlib::DEFAULT_STRATEGY)
29
31
  output = Stream.new
30
32
  gz = Zlib::GzipWriter.new(output, level, strategy)
31
33
  gz.write(source)
@@ -1,4 +1,9 @@
1
- require 'active_support/core_ext/hash/keys'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/hash/keys"
4
+ require "active_support/core_ext/hash/reverse_merge"
5
+ require "active_support/core_ext/hash/except"
6
+ require "active_support/core_ext/hash/slice"
2
7
 
3
8
  module ActiveSupport
4
9
  # Implements a hash where keys <tt>:foo</tt> and <tt>"foo"</tt> are considered
@@ -39,6 +44,12 @@ module ActiveSupport
39
44
  # rgb = { black: '#000000', white: '#FFFFFF' }.with_indifferent_access
40
45
  #
41
46
  # which may be handy.
47
+ #
48
+ # To access this class outside of Rails, require the core extension with:
49
+ #
50
+ # require "active_support/core_ext/hash/indifferent_access"
51
+ #
52
+ # which will, in turn, require this file.
42
53
  class HashWithIndifferentAccess < Hash
43
54
  # Returns +true+ so that <tt>Array#extract_options!</tt> finds members of
44
55
  # this class.
@@ -54,27 +65,18 @@ module ActiveSupport
54
65
  self
55
66
  end
56
67
 
57
- def initialize(constructor = {})
58
- if constructor.is_a?(Hash)
68
+ def initialize(constructor = nil)
69
+ if constructor.respond_to?(:to_hash)
59
70
  super()
60
71
  update(constructor)
61
- else
62
- super(constructor)
63
- end
64
- end
65
72
 
66
- def default(key = nil)
67
- if key.is_a?(Symbol) && include?(key = key.to_s)
68
- self[key]
73
+ hash = constructor.is_a?(Hash) ? constructor : constructor.to_hash
74
+ self.default = hash.default if hash.default
75
+ self.default_proc = hash.default_proc if hash.default_proc
76
+ elsif constructor.nil?
77
+ super()
69
78
  else
70
- super
71
- end
72
- end
73
-
74
- def self.new_from_hash_copying_default(hash)
75
- hash = hash.to_hash
76
- new(hash).tap do |new_hash|
77
- new_hash.default = hash.default
79
+ super(constructor)
78
80
  end
79
81
  end
80
82
 
@@ -90,14 +92,14 @@ module ActiveSupport
90
92
  # hash = ActiveSupport::HashWithIndifferentAccess.new
91
93
  # hash[:key] = 'value'
92
94
  #
93
- # This value can be later fetched using either +:key+ or +'key'+.
95
+ # This value can be later fetched using either +:key+ or <tt>'key'</tt>.
94
96
  def []=(key, value)
95
- regular_writer(convert_key(key), convert_value(value, for: :assignment))
97
+ regular_writer(convert_key(key), convert_value(value, conversion: :assignment))
96
98
  end
97
99
 
98
100
  alias_method :store, :[]=
99
101
 
100
- # Updates the receiver in-place, merging in the hash passed as argument:
102
+ # Updates the receiver in-place, merging in the hashes passed as arguments:
101
103
  #
102
104
  # hash_1 = ActiveSupport::HashWithIndifferentAccess.new
103
105
  # hash_1[:key] = 'value'
@@ -107,11 +109,14 @@ module ActiveSupport
107
109
  #
108
110
  # hash_1.update(hash_2) # => {"key"=>"New Value!"}
109
111
  #
110
- # The argument can be either an
112
+ # hash = ActiveSupport::HashWithIndifferentAccess.new
113
+ # hash.update({ "a" => 1 }, { "b" => 2 }) # => { "a" => 1, "b" => 2 }
114
+ #
115
+ # The arguments can be either an
111
116
  # <tt>ActiveSupport::HashWithIndifferentAccess</tt> or a regular +Hash+.
112
117
  # In either case the merge respects the semantics of indifferent access.
113
118
  #
114
- # If the argument is a regular hash with keys +:key+ and +"key"+ only one
119
+ # If the argument is a regular hash with keys +:key+ and <tt>"key"</tt> only one
115
120
  # of the values end up in the receiver, but which one is unspecified.
116
121
  #
117
122
  # When given a block, the value for duplicated keys will be determined
@@ -122,18 +127,15 @@ module ActiveSupport
122
127
  # hash_1[:key] = 10
123
128
  # hash_2['key'] = 12
124
129
  # hash_1.update(hash_2) { |key, old, new| old + new } # => {"key"=>22}
125
- def update(other_hash)
126
- if other_hash.is_a? HashWithIndifferentAccess
127
- super(other_hash)
130
+ def update(*other_hashes, &block)
131
+ if other_hashes.size == 1
132
+ update_with_single_argument(other_hashes.first, block)
128
133
  else
129
- other_hash.to_hash.each_pair do |key, value|
130
- if block_given? && key?(key)
131
- value = yield(convert_key(key), self[key], value)
132
- end
133
- regular_writer(convert_key(key), convert_value(value))
134
+ other_hashes.each do |other_hash|
135
+ update_with_single_argument(other_hash, block)
134
136
  end
135
- self
136
137
  end
138
+ self
137
139
  end
138
140
 
139
141
  alias_method :merge!, :update
@@ -152,6 +154,32 @@ module ActiveSupport
152
154
  alias_method :has_key?, :key?
153
155
  alias_method :member?, :key?
154
156
 
157
+ # Same as <tt>Hash#[]</tt> where the key passed as argument can be
158
+ # either a string or a symbol:
159
+ #
160
+ # counters = ActiveSupport::HashWithIndifferentAccess.new
161
+ # counters[:foo] = 1
162
+ #
163
+ # counters['foo'] # => 1
164
+ # counters[:foo] # => 1
165
+ # counters[:zoo] # => nil
166
+ def [](key)
167
+ super(convert_key(key))
168
+ end
169
+
170
+ # Same as <tt>Hash#assoc</tt> where the key passed as argument can be
171
+ # either a string or a symbol:
172
+ #
173
+ # counters = ActiveSupport::HashWithIndifferentAccess.new
174
+ # counters[:foo] = 1
175
+ #
176
+ # counters.assoc('foo') # => ["foo", 1]
177
+ # counters.assoc(:foo) # => ["foo", 1]
178
+ # counters.assoc(:zoo) # => nil
179
+ def assoc(key)
180
+ super(convert_key(key))
181
+ end
182
+
155
183
  # Same as <tt>Hash#fetch</tt> where the key passed as argument can be
156
184
  # either a string or a symbol:
157
185
  #
@@ -160,34 +188,82 @@ module ActiveSupport
160
188
  #
161
189
  # counters.fetch('foo') # => 1
162
190
  # counters.fetch(:bar, 0) # => 0
163
- # counters.fetch(:bar) {|key| 0} # => 0
191
+ # counters.fetch(:bar) { |key| 0 } # => 0
164
192
  # counters.fetch(:zoo) # => KeyError: key not found: "zoo"
165
193
  def fetch(key, *extras)
166
194
  super(convert_key(key), *extras)
167
195
  end
168
196
 
197
+ # Same as <tt>Hash#dig</tt> where the key passed as argument can be
198
+ # either a string or a symbol:
199
+ #
200
+ # counters = ActiveSupport::HashWithIndifferentAccess.new
201
+ # counters[:foo] = { bar: 1 }
202
+ #
203
+ # counters.dig('foo', 'bar') # => 1
204
+ # counters.dig(:foo, :bar) # => 1
205
+ # counters.dig(:zoo) # => nil
206
+ def dig(*args)
207
+ args[0] = convert_key(args[0]) if args.size > 0
208
+ super(*args)
209
+ end
210
+
211
+ # Same as <tt>Hash#default</tt> where the key passed as argument can be
212
+ # either a string or a symbol:
213
+ #
214
+ # hash = ActiveSupport::HashWithIndifferentAccess.new(1)
215
+ # hash.default # => 1
216
+ #
217
+ # hash = ActiveSupport::HashWithIndifferentAccess.new { |hash, key| key }
218
+ # hash.default # => nil
219
+ # hash.default('foo') # => 'foo'
220
+ # hash.default(:foo) # => 'foo'
221
+ def default(*args)
222
+ super(*args.map { |arg| convert_key(arg) })
223
+ end
224
+
169
225
  # Returns an array of the values at the specified indices:
170
226
  #
171
227
  # hash = ActiveSupport::HashWithIndifferentAccess.new
172
228
  # hash[:a] = 'x'
173
229
  # hash[:b] = 'y'
174
230
  # hash.values_at('a', 'b') # => ["x", "y"]
175
- def values_at(*indices)
176
- indices.collect {|key| self[convert_key(key)]}
231
+ def values_at(*keys)
232
+ super(*keys.map { |key| convert_key(key) })
177
233
  end
178
234
 
179
- # Returns an exact copy of the hash.
235
+ # Returns an array of the values at the specified indices, but also
236
+ # raises an exception when one of the keys can't be found.
237
+ #
238
+ # hash = ActiveSupport::HashWithIndifferentAccess.new
239
+ # hash[:a] = 'x'
240
+ # hash[:b] = 'y'
241
+ # hash.fetch_values('a', 'b') # => ["x", "y"]
242
+ # hash.fetch_values('a', 'c') { |key| 'z' } # => ["x", "z"]
243
+ # hash.fetch_values('a', 'c') # => KeyError: key not found: "c"
244
+ def fetch_values(*indices, &block)
245
+ super(*indices.map { |key| convert_key(key) }, &block)
246
+ end
247
+
248
+ # Returns a shallow copy of the hash.
249
+ #
250
+ # hash = ActiveSupport::HashWithIndifferentAccess.new({ a: { b: 'b' } })
251
+ # dup = hash.dup
252
+ # dup[:a][:c] = 'c'
253
+ #
254
+ # hash[:a][:c] # => "c"
255
+ # dup[:a][:c] # => "c"
180
256
  def dup
181
257
  self.class.new(self).tap do |new_hash|
182
- new_hash.default = default
258
+ set_defaults(new_hash)
183
259
  end
184
260
  end
185
261
 
186
262
  # This method has the same semantics of +update+, except it does not
187
263
  # modify the receiver but rather returns a new hash with indifferent
188
264
  # access with the result of the merge.
189
- def merge(hash, &block)
190
- self.dup.update(hash, &block)
265
+ def merge(*hashes, &block)
266
+ dup.update(*hashes, &block)
191
267
  end
192
268
 
193
269
  # Like +merge+ but the other way around: Merges the receiver into the
@@ -197,20 +273,22 @@ module ActiveSupport
197
273
  # hash['a'] = nil
198
274
  # hash.reverse_merge(a: 0, b: 1) # => {"a"=>nil, "b"=>1}
199
275
  def reverse_merge(other_hash)
200
- super(self.class.new_from_hash_copying_default(other_hash))
276
+ super(self.class.new(other_hash))
201
277
  end
278
+ alias_method :with_defaults, :reverse_merge
202
279
 
203
280
  # Same semantics as +reverse_merge+ but modifies the receiver in-place.
204
281
  def reverse_merge!(other_hash)
205
- replace(reverse_merge( other_hash ))
282
+ super(self.class.new(other_hash))
206
283
  end
284
+ alias_method :with_defaults!, :reverse_merge!
207
285
 
208
286
  # Replaces the contents of this hash with other_hash.
209
287
  #
210
288
  # h = { "a" => 100, "b" => 200 }
211
- # h.replace({ "c" => 300, "d" => 400 }) #=> {"c"=>300, "d"=>400}
289
+ # h.replace({ "c" => 300, "d" => 400 }) # => {"c"=>300, "d"=>400}
212
290
  def replace(other_hash)
213
- super(self.class.new_from_hash_copying_default(other_hash))
291
+ super(self.class.new(other_hash))
214
292
  end
215
293
 
216
294
  # Removes the specified key from the hash.
@@ -218,6 +296,15 @@ module ActiveSupport
218
296
  super(convert_key(key))
219
297
  end
220
298
 
299
+ # Returns a hash with indifferent access that includes everything except given keys.
300
+ # hash = { a: "x", b: "y", c: 10 }.with_indifferent_access
301
+ # hash.except(:a, "b") # => {c: 10}.with_indifferent_access
302
+ # hash # => { a: "x", b: "y", c: 10 }.with_indifferent_access
303
+ def except(*keys)
304
+ slice(*self.keys - keys.map { |key| convert_key(key) })
305
+ end
306
+ alias_method :without, :except
307
+
221
308
  def stringify_keys!; self end
222
309
  def deep_stringify_keys!; self end
223
310
  def stringify_keys; dup end
@@ -225,48 +312,114 @@ module ActiveSupport
225
312
  undef :symbolize_keys!
226
313
  undef :deep_symbolize_keys!
227
314
  def symbolize_keys; to_hash.symbolize_keys! end
228
- def deep_symbolize_keys; to_hash.deep_symbolize_keys end
315
+ alias_method :to_options, :symbolize_keys
316
+ def deep_symbolize_keys; to_hash.deep_symbolize_keys! end
229
317
  def to_options!; self end
230
318
 
231
319
  def select(*args, &block)
320
+ return to_enum(:select) unless block_given?
232
321
  dup.tap { |hash| hash.select!(*args, &block) }
233
322
  end
234
323
 
235
324
  def reject(*args, &block)
325
+ return to_enum(:reject) unless block_given?
236
326
  dup.tap { |hash| hash.reject!(*args, &block) }
237
327
  end
238
328
 
329
+ def transform_values(*args, &block)
330
+ return to_enum(:transform_values) unless block_given?
331
+ dup.tap { |hash| hash.transform_values!(*args, &block) }
332
+ end
333
+
334
+ def transform_keys(*args, &block)
335
+ return to_enum(:transform_keys) unless block_given?
336
+ dup.tap { |hash| hash.transform_keys!(*args, &block) }
337
+ end
338
+
339
+ def transform_keys!
340
+ return enum_for(:transform_keys!) { size } unless block_given?
341
+ keys.each do |key|
342
+ self[yield(key)] = delete(key)
343
+ end
344
+ self
345
+ end
346
+
347
+ def slice(*keys)
348
+ keys.map! { |key| convert_key(key) }
349
+ self.class.new(super)
350
+ end
351
+
352
+ def slice!(*keys)
353
+ keys.map! { |key| convert_key(key) }
354
+ super
355
+ end
356
+
357
+ def compact
358
+ dup.tap(&:compact!)
359
+ end
360
+
239
361
  # Convert to a regular hash with string keys.
240
362
  def to_hash
241
- _new_hash= {}
363
+ _new_hash = Hash.new
364
+ set_defaults(_new_hash)
365
+
242
366
  each do |key, value|
243
- _new_hash[convert_key(key)] = convert_value(value, for: :to_hash)
367
+ _new_hash[key] = convert_value(value, conversion: :to_hash)
244
368
  end
245
- Hash.new(default).merge!(_new_hash)
369
+ _new_hash
246
370
  end
247
371
 
248
- protected
249
- def convert_key(key)
250
- key.kind_of?(Symbol) ? key.to_s : key
372
+ private
373
+ if Symbol.method_defined?(:name)
374
+ def convert_key(key)
375
+ key.kind_of?(Symbol) ? key.name : key
376
+ end
377
+ else
378
+ def convert_key(key)
379
+ key.kind_of?(Symbol) ? key.to_s : key
380
+ end
251
381
  end
252
382
 
253
- def convert_value(value, options = {})
383
+ def convert_value(value, conversion: nil)
254
384
  if value.is_a? Hash
255
- if options[:for] == :to_hash
385
+ if conversion == :to_hash
256
386
  value.to_hash
257
387
  else
258
388
  value.nested_under_indifferent_access
259
389
  end
260
390
  elsif value.is_a?(Array)
261
- unless options[:for] == :assignment
391
+ if conversion != :assignment || value.frozen?
262
392
  value = value.dup
263
393
  end
264
- value.map! { |e| convert_value(e, options) }
394
+ value.map! { |e| convert_value(e, conversion: conversion) }
265
395
  else
266
396
  value
267
397
  end
268
398
  end
399
+
400
+ def set_defaults(target)
401
+ if default_proc
402
+ target.default_proc = default_proc.dup
403
+ else
404
+ target.default = default
405
+ end
406
+ end
407
+
408
+ def update_with_single_argument(other_hash, block)
409
+ if other_hash.is_a? HashWithIndifferentAccess
410
+ regular_update(other_hash, &block)
411
+ else
412
+ other_hash.to_hash.each_pair do |key, value|
413
+ if block && key?(key)
414
+ value = block.call(convert_key(key), self[key], value)
415
+ end
416
+ regular_writer(convert_key(key), convert_value(value))
417
+ end
418
+ end
419
+ end
269
420
  end
270
421
  end
271
422
 
423
+ # :stopdoc:
424
+
272
425
  HashWithIndifferentAccess = ActiveSupport::HashWithIndifferentAccess