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
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2005-2013 David Heinemeier Hansson
1
+ Copyright (c) 2005-2022 David Heinemeier Hansson
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
@@ -17,4 +17,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
17
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
18
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
19
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc CHANGED
@@ -5,31 +5,36 @@ extensions that were found useful for the Rails framework. These additions
5
5
  reside in this package so they can be loaded as needed in Ruby projects
6
6
  outside of Rails.
7
7
 
8
+ You can read more about the extensions in the {Active Support Core Extensions}[https://edgeguides.rubyonrails.org/active_support_core_extensions.html] guide.
8
9
 
9
10
  == Download and installation
10
11
 
11
12
  The latest version of Active Support can be installed with RubyGems:
12
13
 
13
- % [sudo] gem install activesupport
14
+ $ gem install activesupport
14
15
 
15
16
  Source code can be downloaded as part of the Rails project on GitHub:
16
17
 
17
- * https://github.com/rails/rails/tree/4-0-stable/activesupport
18
+ * https://github.com/rails/rails/tree/main/activesupport
18
19
 
19
20
 
20
21
  == License
21
22
 
22
23
  Active Support is released under the MIT license:
23
24
 
24
- * http://www.opensource.org/licenses/MIT
25
+ * https://opensource.org/licenses/MIT
25
26
 
26
27
 
27
28
  == Support
28
29
 
29
30
  API documentation is at:
30
31
 
31
- * http://api.rubyonrails.org
32
+ * https://api.rubyonrails.org
32
33
 
33
- Bug reports and feature requests can be filed with the rest for the Ruby on Rails project here:
34
+ Bug reports for the Ruby on Rails project can be filed here:
34
35
 
35
36
  * https://github.com/rails/rails/issues
37
+
38
+ Feature requests should be discussed on the rails-core mailing list here:
39
+
40
+ * https://discuss.rubyonrails.org/c/rubyonrails-core
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ # Actionable errors lets you define actions to resolve an error.
5
+ #
6
+ # To make an error actionable, include the <tt>ActiveSupport::ActionableError</tt>
7
+ # module and invoke the +action+ class macro to define the action. An action
8
+ # needs a name and a block to execute.
9
+ module ActionableError
10
+ extend Concern
11
+
12
+ class NonActionable < StandardError; end
13
+
14
+ included do
15
+ class_attribute :_actions, default: {}
16
+ end
17
+
18
+ def self.actions(error) # :nodoc:
19
+ case error
20
+ when ActionableError, -> it { Class === it && it < ActionableError }
21
+ error._actions
22
+ else
23
+ {}
24
+ end
25
+ end
26
+
27
+ def self.dispatch(error, name) # :nodoc:
28
+ actions(error).fetch(name).call
29
+ rescue KeyError
30
+ raise NonActionable, "Cannot find action \"#{name}\""
31
+ end
32
+
33
+ module ClassMethods
34
+ # Defines an action that can resolve the error.
35
+ #
36
+ # class PendingMigrationError < MigrationError
37
+ # include ActiveSupport::ActionableError
38
+ #
39
+ # action "Run pending migrations" do
40
+ # ActiveRecord::Tasks::DatabaseTasks.migrate
41
+ # end
42
+ # end
43
+ def action(name, &block)
44
+ _actions[name] = block
45
+ end
46
+ end
47
+ end
48
+ end
@@ -1,3 +1,5 @@
1
- require 'active_support'
2
- require 'active_support/time'
3
- require 'active_support/core_ext'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support"
4
+ require "active_support/time"
5
+ require "active_support/core_ext"
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ # Wrapping an array in an +ArrayInquirer+ gives a friendlier way to check
5
+ # its string-like contents:
6
+ #
7
+ # variants = ActiveSupport::ArrayInquirer.new([:phone, :tablet])
8
+ #
9
+ # variants.phone? # => true
10
+ # variants.tablet? # => true
11
+ # variants.desktop? # => false
12
+ class ArrayInquirer < Array
13
+ # Passes each element of +candidates+ collection to ArrayInquirer collection.
14
+ # The method returns true if any element from the ArrayInquirer collection
15
+ # is equal to the stringified or symbolized form of any element in the +candidates+ collection.
16
+ #
17
+ # If +candidates+ collection is not given, method returns true.
18
+ #
19
+ # variants = ActiveSupport::ArrayInquirer.new([:phone, :tablet])
20
+ #
21
+ # variants.any? # => true
22
+ # variants.any?(:phone, :tablet) # => true
23
+ # variants.any?('phone', 'desktop') # => true
24
+ # variants.any?(:desktop, :watch) # => false
25
+ def any?(*candidates)
26
+ if candidates.none?
27
+ super
28
+ else
29
+ candidates.any? do |candidate|
30
+ include?(candidate.to_sym) || include?(candidate.to_s)
31
+ end
32
+ end
33
+ end
34
+
35
+ private
36
+ def respond_to_missing?(name, include_private = false)
37
+ name.end_with?("?") || super
38
+ end
39
+
40
+ def method_missing(name, *args)
41
+ if name.end_with?("?")
42
+ any?(name[0..-2])
43
+ else
44
+ super
45
+ end
46
+ end
47
+ end
48
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveSupport
2
4
  # Backtraces often include many lines that are not relevant for the context
3
5
  # under review. This makes it hard to find the signal amongst the backtrace
@@ -12,23 +14,26 @@ module ActiveSupport
12
14
  # is to exclude the output of a noisy library from the backtrace, so that you
13
15
  # can focus on the rest.
14
16
  #
15
- # bc = BacktraceCleaner.new
16
- # bc.add_filter { |line| line.gsub(Rails.root, '') }
17
- # bc.add_silencer { |line| line =~ /mongrel|rubygems/ }
18
- # bc.clean(exception.backtrace) # will strip the Rails.root prefix and skip any lines from mongrel or rubygems
17
+ # bc = ActiveSupport::BacktraceCleaner.new
18
+ # bc.add_filter { |line| line.gsub(Rails.root.to_s, '') } # strip the Rails.root prefix
19
+ # bc.add_silencer { |line| /puma|rubygems/.match?(line) } # skip any lines from puma or rubygems
20
+ # bc.clean(exception.backtrace) # perform the cleanup
19
21
  #
20
22
  # To reconfigure an existing BacktraceCleaner (like the default one in Rails)
21
23
  # and show as much data as possible, you can always call
22
24
  # <tt>BacktraceCleaner#remove_silencers!</tt>, which will restore the
23
25
  # backtrace to a pristine state. If you need to reconfigure an existing
24
26
  # BacktraceCleaner so that it does not filter or modify the paths of any lines
25
- # of the backtrace, you can call BacktraceCleaner#remove_filters! These two
26
- # methods will give you a completely untouched backtrace.
27
+ # of the backtrace, you can call <tt>BacktraceCleaner#remove_filters!</tt>
28
+ # These two methods will give you a completely untouched backtrace.
27
29
  #
28
- # Inspired by the Quiet Backtrace gem by Thoughtbot.
30
+ # Inspired by the Quiet Backtrace gem by thoughtbot.
29
31
  class BacktraceCleaner
30
32
  def initialize
31
33
  @filters, @silencers = [], []
34
+ add_gem_filter
35
+ add_gem_silencer
36
+ add_stdlib_silencer
32
37
  end
33
38
 
34
39
  # Returns the backtrace after all filters and silencers have been run
@@ -59,20 +64,20 @@ module ActiveSupport
59
64
  # Adds a silencer from the block provided. If the silencer returns +true+
60
65
  # for a given line, it will be excluded from the clean backtrace.
61
66
  #
62
- # # Will reject all lines that include the word "mongrel", like "/gems/mongrel/server.rb" or "/app/my_mongrel_server/rb"
63
- # backtrace_cleaner.add_silencer { |line| line =~ /mongrel/ }
67
+ # # Will reject all lines that include the word "puma", like "/gems/puma/server.rb" or "/app/my_puma_server/rb"
68
+ # backtrace_cleaner.add_silencer { |line| /puma/.match?(line) }
64
69
  def add_silencer(&block)
65
70
  @silencers << block
66
71
  end
67
72
 
68
- # Will remove all silencers, but leave in the filters. This is useful if
69
- # your context of debugging suddenly expands as you suspect a bug in one of
73
+ # Removes all silencers, but leaves in the filters. Useful if your
74
+ # context of debugging suddenly expands as you suspect a bug in one of
70
75
  # the libraries you use.
71
76
  def remove_silencers!
72
77
  @silencers = []
73
78
  end
74
79
 
75
- # Removes all filters, but leaves in silencers. Useful if you suddenly
80
+ # Removes all filters, but leaves in the silencers. Useful if you suddenly
76
81
  # need to see entire filepaths in the backtrace that you had already
77
82
  # filtered out.
78
83
  def remove_filters!
@@ -80,6 +85,25 @@ module ActiveSupport
80
85
  end
81
86
 
82
87
  private
88
+ FORMATTED_GEMS_PATTERN = /\A[^\/]+ \([\w.]+\) /
89
+
90
+ def add_gem_filter
91
+ gems_paths = (Gem.path | [Gem.default_dir]).map { |p| Regexp.escape(p) }
92
+ return if gems_paths.empty?
93
+
94
+ gems_regexp = %r{\A(#{gems_paths.join('|')})/(bundler/)?gems/([^/]+)-([\w.]+)/(.*)}
95
+ gems_result = '\3 (\4) \5'
96
+ add_filter { |line| line.sub(gems_regexp, gems_result) }
97
+ end
98
+
99
+ def add_gem_silencer
100
+ add_silencer { |line| FORMATTED_GEMS_PATTERN.match?(line) }
101
+ end
102
+
103
+ def add_stdlib_silencer
104
+ add_silencer { |line| line.start_with?(RbConfig::CONFIG["rubylibdir"]) }
105
+ end
106
+
83
107
  def filter_backtrace(backtrace)
84
108
  @filters.each do |f|
85
109
  backtrace = backtrace.map { |line| f.call(line) }
@@ -97,7 +121,11 @@ module ActiveSupport
97
121
  end
98
122
 
99
123
  def noise(backtrace)
100
- backtrace - silence(backtrace)
124
+ backtrace.select do |line|
125
+ @silencers.any? do |s|
126
+ s.call(line)
127
+ end
128
+ end
101
129
  end
102
130
  end
103
131
  end
@@ -1,5 +1,7 @@
1
- require 'active_support/core_ext/benchmark'
2
- require 'active_support/core_ext/hash/keys'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/benchmark"
4
+ require "active_support/core_ext/hash/keys"
3
5
 
4
6
  module ActiveSupport
5
7
  module Benchmarkable
@@ -32,28 +34,18 @@ module ActiveSupport
32
34
  # <% benchmark 'Process data files', level: :info, silence: true do %>
33
35
  # <%= expensive_and_chatty_files_operation %>
34
36
  # <% end %>
35
- def benchmark(message = "Benchmarking", options = {})
37
+ def benchmark(message = "Benchmarking", options = {}, &block)
36
38
  if logger
37
39
  options.assert_valid_keys(:level, :silence)
38
40
  options[:level] ||= :info
39
41
 
40
42
  result = nil
41
- ms = Benchmark.ms { result = options[:silence] ? silence { yield } : yield }
42
- logger.send(options[:level], '%s (%.1fms)' % [ message, ms ])
43
+ ms = Benchmark.ms { result = options[:silence] ? logger.silence(&block) : yield }
44
+ logger.public_send(options[:level], "%s (%.1fms)" % [ message, ms ])
43
45
  result
44
46
  else
45
47
  yield
46
48
  end
47
49
  end
48
-
49
- # Silence the logger during the execution of the block.
50
- def silence
51
- message = "ActiveSupport::Benchmarkable#silence is deprecated. It will be removed from Rails 4.1."
52
- ActiveSupport::Deprecation.warn message
53
- old_logger_level, logger.level = logger.level, ::Logger::ERROR if logger
54
- yield
55
- ensure
56
- logger.level = old_logger_level if logger
57
- end
58
50
  end
59
51
  end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  begin
2
- require 'builder'
4
+ require "builder"
3
5
  rescue LoadError => e
4
6
  $stderr.puts "You don't have builder installed in your application. Please add it to your Gemfile and run bundle install"
5
7
  raise e
@@ -1,7 +1,8 @@
1
- require 'active_support/core_ext/marshal'
2
- require 'active_support/core_ext/file/atomic'
3
- require 'active_support/core_ext/string/conversions'
4
- require 'uri/common'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/file/atomic"
4
+ require "active_support/core_ext/string/conversions"
5
+ require "uri/common"
5
6
 
6
7
  module ActiveSupport
7
8
  module Cache
@@ -13,55 +14,48 @@ module ActiveSupport
13
14
  attr_reader :cache_path
14
15
 
15
16
  DIR_FORMATTER = "%03X"
16
- FILENAME_MAX_SIZE = 228 # max filename size on file system is 255, minus room for timestamp and random characters appended by Tempfile (used by atomic write)
17
- EXCLUDED_DIRS = ['.', '..'].freeze
17
+ FILENAME_MAX_SIZE = 226 # max filename size on file system is 255, minus room for timestamp, pid, and random characters appended by Tempfile (used by atomic write)
18
+ FILEPATH_MAX_SIZE = 900 # max is 1024, plus some room
19
+ GITKEEP_FILES = [".gitkeep", ".keep"].freeze
18
20
 
19
- def initialize(cache_path, options = nil)
21
+ def initialize(cache_path, **options)
20
22
  super(options)
21
23
  @cache_path = cache_path.to_s
22
- extend Strategy::LocalCache
23
24
  end
24
25
 
26
+ # Advertise cache versioning support.
27
+ def self.supports_cache_versioning?
28
+ true
29
+ end
30
+
31
+ # Deletes all items from the cache. In this case it deletes all the entries in the specified
32
+ # file store directory except for .keep or .gitkeep. Be careful which directory is specified in your
33
+ # config file when using +FileStore+ because everything in that directory will be deleted.
25
34
  def clear(options = nil)
26
- root_dirs = Dir.entries(cache_path).reject {|f| (EXCLUDED_DIRS + [".gitkeep"]).include?(f)}
27
- FileUtils.rm_r(root_dirs.collect{|f| File.join(cache_path, f)})
35
+ root_dirs = (Dir.children(cache_path) - GITKEEP_FILES)
36
+ FileUtils.rm_r(root_dirs.collect { |f| File.join(cache_path, f) })
37
+ rescue Errno::ENOENT, Errno::ENOTEMPTY
28
38
  end
29
39
 
40
+ # Preemptively iterates through all stored keys and removes the ones which have expired.
30
41
  def cleanup(options = nil)
31
42
  options = merged_options(options)
32
43
  search_dir(cache_path) do |fname|
33
- key = file_path_key(fname)
34
- entry = read_entry(key, options)
35
- delete_entry(key, options) if entry && entry.expired?
44
+ entry = read_entry(fname, **options)
45
+ delete_entry(fname, **options) if entry && entry.expired?
36
46
  end
37
47
  end
38
48
 
49
+ # Increments an already existing integer value that is stored in the cache.
50
+ # If the key is not found nothing is done.
39
51
  def increment(name, amount = 1, options = nil)
40
- file_name = key_file_path(namespaced_key(name, options))
41
- lock_file(file_name) do
42
- options = merged_options(options)
43
- if num = read(name, options)
44
- num = num.to_i + amount
45
- write(name, num, options)
46
- num
47
- else
48
- nil
49
- end
50
- end
52
+ modify_value(name, amount, options)
51
53
  end
52
54
 
55
+ # Decrements an already existing integer value that is stored in the cache.
56
+ # If the key is not found nothing is done.
53
57
  def decrement(name, amount = 1, options = nil)
54
- file_name = key_file_path(namespaced_key(name, options))
55
- lock_file(file_name) do
56
- options = merged_options(options)
57
- if num = read(name, options)
58
- num = num.to_i - amount
59
- write(name, num, options)
60
- num
61
- else
62
- nil
63
- end
64
- end
58
+ modify_value(name, -amount, options)
65
59
  end
66
60
 
67
61
  def delete_matched(matcher, options = nil)
@@ -70,56 +64,59 @@ module ActiveSupport
70
64
  matcher = key_matcher(matcher, options)
71
65
  search_dir(cache_path) do |path|
72
66
  key = file_path_key(path)
73
- delete_entry(key, options) if key.match(matcher)
67
+ delete_entry(path, **options) if key.match(matcher)
74
68
  end
75
69
  end
76
70
  end
77
71
 
78
- protected
79
-
80
- def read_entry(key, options)
81
- file_name = key_file_path(key)
82
- if File.exist?(file_name)
83
- File.open(file_name) { |f| Marshal.load(f) }
72
+ private
73
+ def read_entry(key, **options)
74
+ if payload = read_serialized_entry(key, **options)
75
+ entry = deserialize_entry(payload)
76
+ entry if entry.is_a?(Cache::Entry)
84
77
  end
85
- rescue => e
86
- logger.error("FileStoreError (#{e}): #{e.message}") if logger
78
+ end
79
+
80
+ def read_serialized_entry(key, **)
81
+ File.binread(key) if File.exist?(key)
82
+ rescue => error
83
+ logger.error("FileStoreError (#{error}): #{error.message}") if logger
87
84
  nil
88
85
  end
89
86
 
90
- def write_entry(key, entry, options)
91
- file_name = key_file_path(key)
92
- ensure_cache_path(File.dirname(file_name))
93
- File.atomic_write(file_name, cache_path) {|f| Marshal.dump(entry, f)}
87
+ def write_entry(key, entry, **options)
88
+ write_serialized_entry(key, serialize_entry(entry, **options), **options)
89
+ end
90
+
91
+ def write_serialized_entry(key, payload, **options)
92
+ return false if options[:unless_exist] && File.exist?(key)
93
+ ensure_cache_path(File.dirname(key))
94
+ File.atomic_write(key, cache_path) { |f| f.write(payload) }
94
95
  true
95
96
  end
96
97
 
97
- def delete_entry(key, options)
98
- file_name = key_file_path(key)
99
- if File.exist?(file_name)
98
+ def delete_entry(key, **options)
99
+ if File.exist?(key)
100
100
  begin
101
- File.delete(file_name)
102
- delete_empty_directories(File.dirname(file_name))
101
+ File.delete(key)
102
+ delete_empty_directories(File.dirname(key))
103
103
  true
104
- rescue => e
104
+ rescue
105
105
  # Just in case the error was caused by another process deleting the file first.
106
- raise e if File.exist?(file_name)
106
+ raise if File.exist?(key)
107
107
  false
108
108
  end
109
109
  end
110
110
  end
111
111
 
112
- private
113
112
  # Lock a file for a block so only one process can modify it at a time.
114
- def lock_file(file_name, &block) # :nodoc:
113
+ def lock_file(file_name, &block)
115
114
  if File.exist?(file_name)
116
- File.open(file_name, 'r+') do |f|
117
- begin
118
- f.flock File::LOCK_EX
119
- yield
120
- ensure
121
- f.flock File::LOCK_UN
122
- end
115
+ File.open(file_name, "r+") do |f|
116
+ f.flock File::LOCK_EX
117
+ yield
118
+ ensure
119
+ f.flock File::LOCK_UN
123
120
  end
124
121
  else
125
122
  yield
@@ -127,20 +124,30 @@ module ActiveSupport
127
124
  end
128
125
 
129
126
  # Translate a key into a file path.
130
- def key_file_path(key)
127
+ def normalize_key(key, options)
128
+ key = super
131
129
  fname = URI.encode_www_form_component(key)
130
+
131
+ if fname.size > FILEPATH_MAX_SIZE
132
+ fname = ActiveSupport::Digest.hexdigest(key)
133
+ end
134
+
132
135
  hash = Zlib.adler32(fname)
133
136
  hash, dir_1 = hash.divmod(0x1000)
134
137
  dir_2 = hash.modulo(0x1000)
135
- fname_paths = []
136
138
 
137
139
  # Make sure file name doesn't exceed file system limits.
138
- begin
139
- fname_paths << fname[0, FILENAME_MAX_SIZE]
140
- fname = fname[FILENAME_MAX_SIZE..-1]
141
- end until fname.blank?
140
+ if fname.length < FILENAME_MAX_SIZE
141
+ fname_paths = fname
142
+ else
143
+ fname_paths = []
144
+ begin
145
+ fname_paths << fname[0, FILENAME_MAX_SIZE]
146
+ fname = fname[FILENAME_MAX_SIZE..-1]
147
+ end until fname.blank?
148
+ end
142
149
 
143
- File.join(cache_path, DIR_FORMATTER % dir_1, DIR_FORMATTER % dir_2, *fname_paths)
150
+ File.join(cache_path, DIR_FORMATTER % dir_1, DIR_FORMATTER % dir_2, fname_paths)
144
151
  end
145
152
 
146
153
  # Translate a file path into a key.
@@ -152,7 +159,7 @@ module ActiveSupport
152
159
  # Delete empty directories in the cache.
153
160
  def delete_empty_directories(dir)
154
161
  return if File.realpath(dir) == File.realpath(cache_path)
155
- if Dir.entries(dir).reject {|f| EXCLUDED_DIRS.include?(f)}.empty?
162
+ if Dir.children(dir).empty?
156
163
  Dir.delete(dir) rescue nil
157
164
  delete_empty_directories(File.dirname(dir))
158
165
  end
@@ -165,8 +172,7 @@ module ActiveSupport
165
172
 
166
173
  def search_dir(dir, &callback)
167
174
  return if !File.exist?(dir)
168
- Dir.foreach(dir) do |d|
169
- next if EXCLUDED_DIRS.include?(d)
175
+ Dir.each_child(dir) do |d|
170
176
  name = File.join(dir, d)
171
177
  if File.directory?(name)
172
178
  search_dir(name, &callback)
@@ -175,6 +181,22 @@ module ActiveSupport
175
181
  end
176
182
  end
177
183
  end
184
+
185
+ # Modifies the amount of an already existing integer value that is stored in the cache.
186
+ # If the key is not found nothing is done.
187
+ def modify_value(name, amount, options)
188
+ file_name = normalize_key(name, options)
189
+
190
+ lock_file(file_name) do
191
+ options = merged_options(options)
192
+
193
+ if num = read(name, options)
194
+ num = num.to_i + amount
195
+ write(name, num, options)
196
+ num
197
+ end
198
+ end
199
+ end
178
200
  end
179
201
  end
180
202
  end