activesupport 6.0.0

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

Potentially problematic release.


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

Files changed (250) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +572 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +40 -0
  5. data/lib/active_support.rb +96 -0
  6. data/lib/active_support/actionable_error.rb +48 -0
  7. data/lib/active_support/all.rb +5 -0
  8. data/lib/active_support/array_inquirer.rb +48 -0
  9. data/lib/active_support/backtrace_cleaner.rb +132 -0
  10. data/lib/active_support/benchmarkable.rb +51 -0
  11. data/lib/active_support/builder.rb +8 -0
  12. data/lib/active_support/cache.rb +830 -0
  13. data/lib/active_support/cache/file_store.rb +196 -0
  14. data/lib/active_support/cache/mem_cache_store.rb +212 -0
  15. data/lib/active_support/cache/memory_store.rb +174 -0
  16. data/lib/active_support/cache/null_store.rb +48 -0
  17. data/lib/active_support/cache/redis_cache_store.rb +488 -0
  18. data/lib/active_support/cache/strategy/local_cache.rb +194 -0
  19. data/lib/active_support/cache/strategy/local_cache_middleware.rb +45 -0
  20. data/lib/active_support/callbacks.rb +856 -0
  21. data/lib/active_support/concern.rb +171 -0
  22. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +17 -0
  23. data/lib/active_support/concurrency/share_lock.rb +227 -0
  24. data/lib/active_support/configurable.rb +146 -0
  25. data/lib/active_support/core_ext.rb +5 -0
  26. data/lib/active_support/core_ext/array.rb +9 -0
  27. data/lib/active_support/core_ext/array/access.rb +104 -0
  28. data/lib/active_support/core_ext/array/conversions.rb +213 -0
  29. data/lib/active_support/core_ext/array/extract.rb +21 -0
  30. data/lib/active_support/core_ext/array/extract_options.rb +31 -0
  31. data/lib/active_support/core_ext/array/grouping.rb +109 -0
  32. data/lib/active_support/core_ext/array/inquiry.rb +19 -0
  33. data/lib/active_support/core_ext/array/prepend_and_append.rb +5 -0
  34. data/lib/active_support/core_ext/array/wrap.rb +48 -0
  35. data/lib/active_support/core_ext/benchmark.rb +16 -0
  36. data/lib/active_support/core_ext/big_decimal.rb +3 -0
  37. data/lib/active_support/core_ext/big_decimal/conversions.rb +14 -0
  38. data/lib/active_support/core_ext/class.rb +4 -0
  39. data/lib/active_support/core_ext/class/attribute.rb +141 -0
  40. data/lib/active_support/core_ext/class/attribute_accessors.rb +6 -0
  41. data/lib/active_support/core_ext/class/subclasses.rb +54 -0
  42. data/lib/active_support/core_ext/date.rb +7 -0
  43. data/lib/active_support/core_ext/date/acts_like.rb +10 -0
  44. data/lib/active_support/core_ext/date/blank.rb +14 -0
  45. data/lib/active_support/core_ext/date/calculations.rb +146 -0
  46. data/lib/active_support/core_ext/date/conversions.rb +96 -0
  47. data/lib/active_support/core_ext/date/zones.rb +8 -0
  48. data/lib/active_support/core_ext/date_and_time/calculations.rb +351 -0
  49. data/lib/active_support/core_ext/date_and_time/compatibility.rb +16 -0
  50. data/lib/active_support/core_ext/date_and_time/zones.rb +41 -0
  51. data/lib/active_support/core_ext/date_time.rb +7 -0
  52. data/lib/active_support/core_ext/date_time/acts_like.rb +16 -0
  53. data/lib/active_support/core_ext/date_time/blank.rb +14 -0
  54. data/lib/active_support/core_ext/date_time/calculations.rb +211 -0
  55. data/lib/active_support/core_ext/date_time/compatibility.rb +18 -0
  56. data/lib/active_support/core_ext/date_time/conversions.rb +107 -0
  57. data/lib/active_support/core_ext/digest.rb +3 -0
  58. data/lib/active_support/core_ext/digest/uuid.rb +53 -0
  59. data/lib/active_support/core_ext/enumerable.rb +188 -0
  60. data/lib/active_support/core_ext/file.rb +3 -0
  61. data/lib/active_support/core_ext/file/atomic.rb +70 -0
  62. data/lib/active_support/core_ext/hash.rb +10 -0
  63. data/lib/active_support/core_ext/hash/compact.rb +5 -0
  64. data/lib/active_support/core_ext/hash/conversions.rb +263 -0
  65. data/lib/active_support/core_ext/hash/deep_merge.rb +34 -0
  66. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  67. data/lib/active_support/core_ext/hash/except.rb +24 -0
  68. data/lib/active_support/core_ext/hash/indifferent_access.rb +24 -0
  69. data/lib/active_support/core_ext/hash/keys.rb +143 -0
  70. data/lib/active_support/core_ext/hash/reverse_merge.rb +25 -0
  71. data/lib/active_support/core_ext/hash/slice.rb +26 -0
  72. data/lib/active_support/core_ext/hash/transform_values.rb +5 -0
  73. data/lib/active_support/core_ext/integer.rb +5 -0
  74. data/lib/active_support/core_ext/integer/inflections.rb +31 -0
  75. data/lib/active_support/core_ext/integer/multiple.rb +12 -0
  76. data/lib/active_support/core_ext/integer/time.rb +22 -0
  77. data/lib/active_support/core_ext/kernel.rb +5 -0
  78. data/lib/active_support/core_ext/kernel/concern.rb +14 -0
  79. data/lib/active_support/core_ext/kernel/reporting.rb +45 -0
  80. data/lib/active_support/core_ext/kernel/singleton_class.rb +8 -0
  81. data/lib/active_support/core_ext/load_error.rb +9 -0
  82. data/lib/active_support/core_ext/marshal.rb +24 -0
  83. data/lib/active_support/core_ext/module.rb +13 -0
  84. data/lib/active_support/core_ext/module/aliasing.rb +31 -0
  85. data/lib/active_support/core_ext/module/anonymous.rb +30 -0
  86. data/lib/active_support/core_ext/module/attr_internal.rb +38 -0
  87. data/lib/active_support/core_ext/module/attribute_accessors.rb +212 -0
  88. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +144 -0
  89. data/lib/active_support/core_ext/module/concerning.rb +134 -0
  90. data/lib/active_support/core_ext/module/delegation.rb +313 -0
  91. data/lib/active_support/core_ext/module/deprecation.rb +25 -0
  92. data/lib/active_support/core_ext/module/introspection.rb +86 -0
  93. data/lib/active_support/core_ext/module/reachable.rb +6 -0
  94. data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
  95. data/lib/active_support/core_ext/module/remove_method.rb +17 -0
  96. data/lib/active_support/core_ext/name_error.rb +38 -0
  97. data/lib/active_support/core_ext/numeric.rb +5 -0
  98. data/lib/active_support/core_ext/numeric/bytes.rb +66 -0
  99. data/lib/active_support/core_ext/numeric/conversions.rb +136 -0
  100. data/lib/active_support/core_ext/numeric/inquiry.rb +5 -0
  101. data/lib/active_support/core_ext/numeric/time.rb +66 -0
  102. data/lib/active_support/core_ext/object.rb +16 -0
  103. data/lib/active_support/core_ext/object/acts_like.rb +21 -0
  104. data/lib/active_support/core_ext/object/blank.rb +155 -0
  105. data/lib/active_support/core_ext/object/conversions.rb +6 -0
  106. data/lib/active_support/core_ext/object/deep_dup.rb +55 -0
  107. data/lib/active_support/core_ext/object/duplicable.rb +49 -0
  108. data/lib/active_support/core_ext/object/inclusion.rb +29 -0
  109. data/lib/active_support/core_ext/object/instance_variables.rb +30 -0
  110. data/lib/active_support/core_ext/object/json.rb +228 -0
  111. data/lib/active_support/core_ext/object/to_param.rb +3 -0
  112. data/lib/active_support/core_ext/object/to_query.rb +89 -0
  113. data/lib/active_support/core_ext/object/try.rb +156 -0
  114. data/lib/active_support/core_ext/object/with_options.rb +82 -0
  115. data/lib/active_support/core_ext/range.rb +7 -0
  116. data/lib/active_support/core_ext/range/compare_range.rb +70 -0
  117. data/lib/active_support/core_ext/range/conversions.rb +41 -0
  118. data/lib/active_support/core_ext/range/each.rb +25 -0
  119. data/lib/active_support/core_ext/range/include_range.rb +9 -0
  120. data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -0
  121. data/lib/active_support/core_ext/range/overlaps.rb +10 -0
  122. data/lib/active_support/core_ext/regexp.rb +7 -0
  123. data/lib/active_support/core_ext/securerandom.rb +45 -0
  124. data/lib/active_support/core_ext/string.rb +15 -0
  125. data/lib/active_support/core_ext/string/access.rb +114 -0
  126. data/lib/active_support/core_ext/string/behavior.rb +8 -0
  127. data/lib/active_support/core_ext/string/conversions.rb +59 -0
  128. data/lib/active_support/core_ext/string/exclude.rb +13 -0
  129. data/lib/active_support/core_ext/string/filters.rb +145 -0
  130. data/lib/active_support/core_ext/string/indent.rb +45 -0
  131. data/lib/active_support/core_ext/string/inflections.rb +259 -0
  132. data/lib/active_support/core_ext/string/inquiry.rb +15 -0
  133. data/lib/active_support/core_ext/string/multibyte.rb +58 -0
  134. data/lib/active_support/core_ext/string/output_safety.rb +314 -0
  135. data/lib/active_support/core_ext/string/starts_ends_with.rb +6 -0
  136. data/lib/active_support/core_ext/string/strip.rb +27 -0
  137. data/lib/active_support/core_ext/string/zones.rb +16 -0
  138. data/lib/active_support/core_ext/time.rb +7 -0
  139. data/lib/active_support/core_ext/time/acts_like.rb +10 -0
  140. data/lib/active_support/core_ext/time/calculations.rb +344 -0
  141. data/lib/active_support/core_ext/time/compatibility.rb +16 -0
  142. data/lib/active_support/core_ext/time/conversions.rb +72 -0
  143. data/lib/active_support/core_ext/time/zones.rb +113 -0
  144. data/lib/active_support/core_ext/uri.rb +25 -0
  145. data/lib/active_support/current_attributes.rb +203 -0
  146. data/lib/active_support/dependencies.rb +806 -0
  147. data/lib/active_support/dependencies/autoload.rb +79 -0
  148. data/lib/active_support/dependencies/interlock.rb +57 -0
  149. data/lib/active_support/dependencies/zeitwerk_integration.rb +110 -0
  150. data/lib/active_support/deprecation.rb +46 -0
  151. data/lib/active_support/deprecation/behaviors.rb +109 -0
  152. data/lib/active_support/deprecation/constant_accessor.rb +52 -0
  153. data/lib/active_support/deprecation/instance_delegator.rb +39 -0
  154. data/lib/active_support/deprecation/method_wrappers.rb +78 -0
  155. data/lib/active_support/deprecation/proxy_wrappers.rb +173 -0
  156. data/lib/active_support/deprecation/reporting.rb +114 -0
  157. data/lib/active_support/descendants_tracker.rb +109 -0
  158. data/lib/active_support/digest.rb +20 -0
  159. data/lib/active_support/duration.rb +433 -0
  160. data/lib/active_support/duration/iso8601_parser.rb +124 -0
  161. data/lib/active_support/duration/iso8601_serializer.rb +54 -0
  162. data/lib/active_support/encrypted_configuration.rb +45 -0
  163. data/lib/active_support/encrypted_file.rb +100 -0
  164. data/lib/active_support/evented_file_update_checker.rb +235 -0
  165. data/lib/active_support/execution_wrapper.rb +129 -0
  166. data/lib/active_support/executor.rb +8 -0
  167. data/lib/active_support/file_update_checker.rb +163 -0
  168. data/lib/active_support/gem_version.rb +17 -0
  169. data/lib/active_support/gzip.rb +38 -0
  170. data/lib/active_support/hash_with_indifferent_access.rb +399 -0
  171. data/lib/active_support/i18n.rb +16 -0
  172. data/lib/active_support/i18n_railtie.rb +126 -0
  173. data/lib/active_support/inflections.rb +72 -0
  174. data/lib/active_support/inflector.rb +9 -0
  175. data/lib/active_support/inflector/inflections.rb +257 -0
  176. data/lib/active_support/inflector/methods.rb +398 -0
  177. data/lib/active_support/inflector/transliterate.rb +147 -0
  178. data/lib/active_support/json.rb +4 -0
  179. data/lib/active_support/json/decoding.rb +76 -0
  180. data/lib/active_support/json/encoding.rb +134 -0
  181. data/lib/active_support/key_generator.rb +41 -0
  182. data/lib/active_support/lazy_load_hooks.rb +82 -0
  183. data/lib/active_support/locale/en.rb +31 -0
  184. data/lib/active_support/locale/en.yml +135 -0
  185. data/lib/active_support/log_subscriber.rb +135 -0
  186. data/lib/active_support/log_subscriber/test_helper.rb +106 -0
  187. data/lib/active_support/logger.rb +93 -0
  188. data/lib/active_support/logger_silence.rb +45 -0
  189. data/lib/active_support/logger_thread_safe_level.rb +56 -0
  190. data/lib/active_support/message_encryptor.rb +227 -0
  191. data/lib/active_support/message_verifier.rb +205 -0
  192. data/lib/active_support/messages/metadata.rb +71 -0
  193. data/lib/active_support/messages/rotation_configuration.rb +22 -0
  194. data/lib/active_support/messages/rotator.rb +56 -0
  195. data/lib/active_support/multibyte.rb +23 -0
  196. data/lib/active_support/multibyte/chars.rb +216 -0
  197. data/lib/active_support/multibyte/unicode.rb +157 -0
  198. data/lib/active_support/notifications.rb +253 -0
  199. data/lib/active_support/notifications/fanout.rb +244 -0
  200. data/lib/active_support/notifications/instrumenter.rb +164 -0
  201. data/lib/active_support/number_helper.rb +378 -0
  202. data/lib/active_support/number_helper/number_converter.rb +184 -0
  203. data/lib/active_support/number_helper/number_to_currency_converter.rb +46 -0
  204. data/lib/active_support/number_helper/number_to_delimited_converter.rb +31 -0
  205. data/lib/active_support/number_helper/number_to_human_converter.rb +70 -0
  206. data/lib/active_support/number_helper/number_to_human_size_converter.rb +61 -0
  207. data/lib/active_support/number_helper/number_to_percentage_converter.rb +16 -0
  208. data/lib/active_support/number_helper/number_to_phone_converter.rb +60 -0
  209. data/lib/active_support/number_helper/number_to_rounded_converter.rb +56 -0
  210. data/lib/active_support/number_helper/rounding_helper.rb +66 -0
  211. data/lib/active_support/option_merger.rb +27 -0
  212. data/lib/active_support/ordered_hash.rb +50 -0
  213. data/lib/active_support/ordered_options.rb +85 -0
  214. data/lib/active_support/parameter_filter.rb +129 -0
  215. data/lib/active_support/per_thread_registry.rb +60 -0
  216. data/lib/active_support/proxy_object.rb +15 -0
  217. data/lib/active_support/rails.rb +29 -0
  218. data/lib/active_support/railtie.rb +80 -0
  219. data/lib/active_support/reloader.rb +130 -0
  220. data/lib/active_support/rescuable.rb +174 -0
  221. data/lib/active_support/security_utils.rb +31 -0
  222. data/lib/active_support/string_inquirer.rb +34 -0
  223. data/lib/active_support/subscriber.rb +169 -0
  224. data/lib/active_support/tagged_logging.rb +88 -0
  225. data/lib/active_support/test_case.rb +163 -0
  226. data/lib/active_support/testing/assertions.rb +228 -0
  227. data/lib/active_support/testing/autorun.rb +7 -0
  228. data/lib/active_support/testing/constant_lookup.rb +51 -0
  229. data/lib/active_support/testing/declarative.rb +28 -0
  230. data/lib/active_support/testing/deprecation.rb +38 -0
  231. data/lib/active_support/testing/file_fixtures.rb +38 -0
  232. data/lib/active_support/testing/isolation.rb +110 -0
  233. data/lib/active_support/testing/method_call_assertions.rb +70 -0
  234. data/lib/active_support/testing/parallelization.rb +128 -0
  235. data/lib/active_support/testing/setup_and_teardown.rb +55 -0
  236. data/lib/active_support/testing/stream.rb +44 -0
  237. data/lib/active_support/testing/tagged_logging.rb +27 -0
  238. data/lib/active_support/testing/time_helpers.rb +200 -0
  239. data/lib/active_support/time.rb +20 -0
  240. data/lib/active_support/time_with_zone.rb +561 -0
  241. data/lib/active_support/values/time_zone.rb +570 -0
  242. data/lib/active_support/version.rb +10 -0
  243. data/lib/active_support/xml_mini.rb +202 -0
  244. data/lib/active_support/xml_mini/jdom.rb +183 -0
  245. data/lib/active_support/xml_mini/libxml.rb +80 -0
  246. data/lib/active_support/xml_mini/libxmlsax.rb +83 -0
  247. data/lib/active_support/xml_mini/nokogiri.rb +83 -0
  248. data/lib/active_support/xml_mini/nokogirisax.rb +86 -0
  249. data/lib/active_support/xml_mini/rexml.rb +130 -0
  250. metadata +385 -0
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ # A class with no predefined methods that behaves similarly to Builder's
5
+ # BlankSlate. Used for proxy classes.
6
+ class ProxyObject < ::BasicObject
7
+ undef_method :==
8
+ undef_method :equal?
9
+
10
+ # Let ActiveSupport::ProxyObject at least raise exceptions.
11
+ def raise(*args)
12
+ ::Object.send(:raise, *args)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This is private interface.
4
+ #
5
+ # Rails components cherry pick from Active Support as needed, but there are a
6
+ # few features that are used for sure in some way or another and it is not worth
7
+ # putting individual requires absolutely everywhere. Think blank? for example.
8
+ #
9
+ # This file is loaded by every Rails component except Active Support itself,
10
+ # but it does not belong to the Rails public interface. It is internal to
11
+ # Rails and can change anytime.
12
+
13
+ # Defines Object#blank? and Object#present?.
14
+ require "active_support/core_ext/object/blank"
15
+
16
+ # Rails own autoload, eager_load, etc.
17
+ require "active_support/dependencies/autoload"
18
+
19
+ # Support for ClassMethods and the included macro.
20
+ require "active_support/concern"
21
+
22
+ # Defines Class#class_attribute.
23
+ require "active_support/core_ext/class/attribute"
24
+
25
+ # Defines Module#delegate.
26
+ require "active_support/core_ext/module/delegation"
27
+
28
+ # Defines ActiveSupport::Deprecation.
29
+ require "active_support/deprecation"
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support"
4
+ require "active_support/i18n_railtie"
5
+
6
+ module ActiveSupport
7
+ class Railtie < Rails::Railtie # :nodoc:
8
+ config.active_support = ActiveSupport::OrderedOptions.new
9
+
10
+ config.eager_load_namespaces << ActiveSupport
11
+
12
+ initializer "active_support.set_authenticated_message_encryption" do |app|
13
+ config.after_initialize do
14
+ unless app.config.active_support.use_authenticated_message_encryption.nil?
15
+ ActiveSupport::MessageEncryptor.use_authenticated_message_encryption =
16
+ app.config.active_support.use_authenticated_message_encryption
17
+ end
18
+ end
19
+ end
20
+
21
+ initializer "active_support.reset_all_current_attributes_instances" do |app|
22
+ app.reloader.before_class_unload { ActiveSupport::CurrentAttributes.clear_all }
23
+ app.executor.to_run { ActiveSupport::CurrentAttributes.reset_all }
24
+ app.executor.to_complete { ActiveSupport::CurrentAttributes.reset_all }
25
+ end
26
+
27
+ initializer "active_support.deprecation_behavior" do |app|
28
+ if deprecation = app.config.active_support.deprecation
29
+ ActiveSupport::Deprecation.behavior = deprecation
30
+ end
31
+ end
32
+
33
+ # Sets the default value for Time.zone
34
+ # If assigned value cannot be matched to a TimeZone, an exception will be raised.
35
+ initializer "active_support.initialize_time_zone" do |app|
36
+ begin
37
+ TZInfo::DataSource.get
38
+ rescue TZInfo::DataSourceNotFound => e
39
+ raise e.exception "tzinfo-data is not present. Please add gem 'tzinfo-data' to your Gemfile and run bundle install"
40
+ end
41
+ require "active_support/core_ext/time/zones"
42
+ Time.zone_default = Time.find_zone!(app.config.time_zone)
43
+ end
44
+
45
+ # Sets the default week start
46
+ # If assigned value is not a valid day symbol (e.g. :sunday, :monday, ...), an exception will be raised.
47
+ initializer "active_support.initialize_beginning_of_week" do |app|
48
+ require "active_support/core_ext/date/calculations"
49
+ beginning_of_week_default = Date.find_beginning_of_week!(app.config.beginning_of_week)
50
+
51
+ Date.beginning_of_week_default = beginning_of_week_default
52
+ end
53
+
54
+ initializer "active_support.require_master_key" do |app|
55
+ if app.config.respond_to?(:require_master_key) && app.config.require_master_key
56
+ begin
57
+ app.credentials.key
58
+ rescue ActiveSupport::EncryptedFile::MissingKeyError => error
59
+ $stderr.puts error.message
60
+ exit 1
61
+ end
62
+ end
63
+ end
64
+
65
+ initializer "active_support.set_configs" do |app|
66
+ app.config.active_support.each do |k, v|
67
+ k = "#{k}="
68
+ ActiveSupport.send(k, v) if ActiveSupport.respond_to? k
69
+ end
70
+ end
71
+
72
+ initializer "active_support.set_hash_digest_class" do |app|
73
+ config.after_initialize do
74
+ if app.config.active_support.use_sha1_digests
75
+ ActiveSupport::Digest.hash_digest_class = ::Digest::SHA1
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/execution_wrapper"
4
+ require "active_support/executor"
5
+
6
+ module ActiveSupport
7
+ #--
8
+ # This class defines several callbacks:
9
+ #
10
+ # to_prepare -- Run once at application startup, and also from
11
+ # +to_run+.
12
+ #
13
+ # to_run -- Run before a work run that is reloading. If
14
+ # +reload_classes_only_on_change+ is true (the default), the class
15
+ # unload will have already occurred.
16
+ #
17
+ # to_complete -- Run after a work run that has reloaded. If
18
+ # +reload_classes_only_on_change+ is false, the class unload will
19
+ # have occurred after the work run, but before this callback.
20
+ #
21
+ # before_class_unload -- Run immediately before the classes are
22
+ # unloaded.
23
+ #
24
+ # after_class_unload -- Run immediately after the classes are
25
+ # unloaded.
26
+ #
27
+ class Reloader < ExecutionWrapper
28
+ define_callbacks :prepare
29
+
30
+ define_callbacks :class_unload
31
+
32
+ # Registers a callback that will run once at application startup and every time the code is reloaded.
33
+ def self.to_prepare(*args, &block)
34
+ set_callback(:prepare, *args, &block)
35
+ end
36
+
37
+ # Registers a callback that will run immediately before the classes are unloaded.
38
+ def self.before_class_unload(*args, &block)
39
+ set_callback(:class_unload, *args, &block)
40
+ end
41
+
42
+ # Registers a callback that will run immediately after the classes are unloaded.
43
+ def self.after_class_unload(*args, &block)
44
+ set_callback(:class_unload, :after, *args, &block)
45
+ end
46
+
47
+ to_run(:after) { self.class.prepare! }
48
+
49
+ # Initiate a manual reload
50
+ def self.reload!
51
+ executor.wrap do
52
+ new.tap do |instance|
53
+ instance.run!
54
+ ensure
55
+ instance.complete!
56
+ end
57
+ end
58
+ prepare!
59
+ end
60
+
61
+ def self.run! # :nodoc:
62
+ if check!
63
+ super
64
+ else
65
+ Null
66
+ end
67
+ end
68
+
69
+ # Run the supplied block as a work unit, reloading code as needed
70
+ def self.wrap
71
+ executor.wrap do
72
+ super
73
+ end
74
+ end
75
+
76
+ class_attribute :executor, default: Executor
77
+ class_attribute :check, default: lambda { false }
78
+
79
+ def self.check! # :nodoc:
80
+ @should_reload ||= check.call
81
+ end
82
+
83
+ def self.reloaded! # :nodoc:
84
+ @should_reload = false
85
+ end
86
+
87
+ def self.prepare! # :nodoc:
88
+ new.run_callbacks(:prepare)
89
+ end
90
+
91
+ def initialize
92
+ super
93
+ @locked = false
94
+ end
95
+
96
+ # Acquire the ActiveSupport::Dependencies::Interlock unload lock,
97
+ # ensuring it will be released automatically
98
+ def require_unload_lock!
99
+ unless @locked
100
+ ActiveSupport::Dependencies.interlock.start_unloading
101
+ @locked = true
102
+ end
103
+ end
104
+
105
+ # Release the unload lock if it has been previously obtained
106
+ def release_unload_lock!
107
+ if @locked
108
+ @locked = false
109
+ ActiveSupport::Dependencies.interlock.done_unloading
110
+ end
111
+ end
112
+
113
+ def run! # :nodoc:
114
+ super
115
+ release_unload_lock!
116
+ end
117
+
118
+ def class_unload!(&block) # :nodoc:
119
+ require_unload_lock!
120
+ run_callbacks(:class_unload, &block)
121
+ end
122
+
123
+ def complete! # :nodoc:
124
+ super
125
+ self.class.reloaded!
126
+ ensure
127
+ release_unload_lock!
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,174 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+ require "active_support/core_ext/class/attribute"
5
+ require "active_support/core_ext/string/inflections"
6
+
7
+ module ActiveSupport
8
+ # Rescuable module adds support for easier exception handling.
9
+ module Rescuable
10
+ extend Concern
11
+
12
+ included do
13
+ class_attribute :rescue_handlers, default: []
14
+ end
15
+
16
+ module ClassMethods
17
+ # Rescue exceptions raised in controller actions.
18
+ #
19
+ # <tt>rescue_from</tt> receives a series of exception classes or class
20
+ # names, and a trailing <tt>:with</tt> option with the name of a method
21
+ # or a Proc object to be called to handle them. Alternatively a block can
22
+ # be given.
23
+ #
24
+ # Handlers that take one argument will be called with the exception, so
25
+ # that the exception can be inspected when dealing with it.
26
+ #
27
+ # Handlers are inherited. They are searched from right to left, from
28
+ # bottom to top, and up the hierarchy. The handler of the first class for
29
+ # which <tt>exception.is_a?(klass)</tt> holds true is the one invoked, if
30
+ # any.
31
+ #
32
+ # class ApplicationController < ActionController::Base
33
+ # rescue_from User::NotAuthorized, with: :deny_access # self defined exception
34
+ # rescue_from ActiveRecord::RecordInvalid, with: :show_errors
35
+ #
36
+ # rescue_from 'MyAppError::Base' do |exception|
37
+ # render xml: exception, status: 500
38
+ # end
39
+ #
40
+ # private
41
+ # def deny_access
42
+ # ...
43
+ # end
44
+ #
45
+ # def show_errors(exception)
46
+ # exception.record.new_record? ? ...
47
+ # end
48
+ # end
49
+ #
50
+ # Exceptions raised inside exception handlers are not propagated up.
51
+ def rescue_from(*klasses, with: nil, &block)
52
+ unless with
53
+ if block_given?
54
+ with = block
55
+ else
56
+ raise ArgumentError, "Need a handler. Pass the with: keyword argument or provide a block."
57
+ end
58
+ end
59
+
60
+ klasses.each do |klass|
61
+ key = if klass.is_a?(Module) && klass.respond_to?(:===)
62
+ klass.name
63
+ elsif klass.is_a?(String)
64
+ klass
65
+ else
66
+ raise ArgumentError, "#{klass.inspect} must be an Exception class or a String referencing an Exception class"
67
+ end
68
+
69
+ # Put the new handler at the end because the list is read in reverse.
70
+ self.rescue_handlers += [[key, with]]
71
+ end
72
+ end
73
+
74
+ # Matches an exception to a handler based on the exception class.
75
+ #
76
+ # If no handler matches the exception, check for a handler matching the
77
+ # (optional) exception.cause. If no handler matches the exception or its
78
+ # cause, this returns +nil+, so you can deal with unhandled exceptions.
79
+ # Be sure to re-raise unhandled exceptions if this is what you expect.
80
+ #
81
+ # begin
82
+ # …
83
+ # rescue => exception
84
+ # rescue_with_handler(exception) || raise
85
+ # end
86
+ #
87
+ # Returns the exception if it was handled and +nil+ if it was not.
88
+ def rescue_with_handler(exception, object: self, visited_exceptions: [])
89
+ visited_exceptions << exception
90
+
91
+ if handler = handler_for_rescue(exception, object: object)
92
+ handler.call exception
93
+ exception
94
+ elsif exception
95
+ if visited_exceptions.include?(exception.cause)
96
+ nil
97
+ else
98
+ rescue_with_handler(exception.cause, object: object, visited_exceptions: visited_exceptions)
99
+ end
100
+ end
101
+ end
102
+
103
+ def handler_for_rescue(exception, object: self) #:nodoc:
104
+ case rescuer = find_rescue_handler(exception)
105
+ when Symbol
106
+ method = object.method(rescuer)
107
+ if method.arity == 0
108
+ -> e { method.call }
109
+ else
110
+ method
111
+ end
112
+ when Proc
113
+ if rescuer.arity == 0
114
+ -> e { object.instance_exec(&rescuer) }
115
+ else
116
+ -> e { object.instance_exec(e, &rescuer) }
117
+ end
118
+ end
119
+ end
120
+
121
+ private
122
+ def find_rescue_handler(exception)
123
+ if exception
124
+ # Handlers are in order of declaration but the most recently declared
125
+ # is the highest priority match, so we search for matching handlers
126
+ # in reverse.
127
+ _, handler = rescue_handlers.reverse_each.detect do |class_or_name, _|
128
+ if klass = constantize_rescue_handler_class(class_or_name)
129
+ klass === exception
130
+ end
131
+ end
132
+
133
+ handler
134
+ end
135
+ end
136
+
137
+ def constantize_rescue_handler_class(class_or_name)
138
+ case class_or_name
139
+ when String, Symbol
140
+ begin
141
+ # Try a lexical lookup first since we support
142
+ #
143
+ # class Super
144
+ # rescue_from 'Error', with: …
145
+ # end
146
+ #
147
+ # class Sub
148
+ # class Error < StandardError; end
149
+ # end
150
+ #
151
+ # so an Error raised in Sub will hit the 'Error' handler.
152
+ const_get class_or_name
153
+ rescue NameError
154
+ class_or_name.safe_constantize
155
+ end
156
+ else
157
+ class_or_name
158
+ end
159
+ end
160
+ end
161
+
162
+ # Delegates to the class method, but uses the instance as the subject for
163
+ # rescue_from handlers (method calls, instance_exec blocks).
164
+ def rescue_with_handler(exception)
165
+ self.class.rescue_with_handler exception, object: self
166
+ end
167
+
168
+ # Internal handler lookup. Delegates to class method. Some libraries call
169
+ # this directly, so keeping it around for compatibility.
170
+ def handler_for_rescue(exception) #:nodoc:
171
+ self.class.handler_for_rescue exception, object: self
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "digest/sha2"
4
+
5
+ module ActiveSupport
6
+ module SecurityUtils
7
+ # Constant time string comparison, for fixed length strings.
8
+ #
9
+ # The values compared should be of fixed length, such as strings
10
+ # that have already been processed by HMAC. Raises in case of length mismatch.
11
+ def fixed_length_secure_compare(a, b)
12
+ raise ArgumentError, "string length mismatch." unless a.bytesize == b.bytesize
13
+
14
+ l = a.unpack "C#{a.bytesize}"
15
+
16
+ res = 0
17
+ b.each_byte { |byte| res |= byte ^ l.shift }
18
+ res == 0
19
+ end
20
+ module_function :fixed_length_secure_compare
21
+
22
+ # Constant time string comparison, for variable length strings.
23
+ #
24
+ # The values are first processed by SHA256, so that we don't leak length info
25
+ # via timing attacks.
26
+ def secure_compare(a, b)
27
+ fixed_length_secure_compare(::Digest::SHA256.digest(a), ::Digest::SHA256.digest(b)) && a == b
28
+ end
29
+ module_function :secure_compare
30
+ end
31
+ end