activesupport 4.2.0 → 5.2.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 (254) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +366 -232
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +4 -5
  5. data/lib/active_support.rb +17 -7
  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 +7 -5
  9. data/lib/active_support/benchmarkable.rb +6 -4
  10. data/lib/active_support/builder.rb +3 -1
  11. data/lib/active_support/cache.rb +271 -177
  12. data/lib/active_support/cache/file_store.rb +41 -35
  13. data/lib/active_support/cache/mem_cache_store.rb +97 -88
  14. data/lib/active_support/cache/memory_store.rb +27 -30
  15. data/lib/active_support/cache/null_store.rb +7 -8
  16. data/lib/active_support/cache/redis_cache_store.rb +454 -0
  17. data/lib/active_support/cache/strategy/local_cache.rb +67 -34
  18. data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
  19. data/lib/active_support/callbacks.rb +654 -560
  20. data/lib/active_support/concern.rb +5 -3
  21. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +17 -0
  22. data/lib/active_support/concurrency/share_lock.rb +227 -0
  23. data/lib/active_support/configurable.rb +8 -5
  24. data/lib/active_support/core_ext.rb +3 -1
  25. data/lib/active_support/core_ext/array.rb +9 -6
  26. data/lib/active_support/core_ext/array/access.rb +29 -1
  27. data/lib/active_support/core_ext/array/conversions.rb +22 -18
  28. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  29. data/lib/active_support/core_ext/array/grouping.rb +11 -18
  30. data/lib/active_support/core_ext/array/inquiry.rb +19 -0
  31. data/lib/active_support/core_ext/array/prepend_and_append.rb +5 -3
  32. data/lib/active_support/core_ext/array/wrap.rb +7 -4
  33. data/lib/active_support/core_ext/benchmark.rb +3 -1
  34. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  35. data/lib/active_support/core_ext/big_decimal/conversions.rb +10 -12
  36. data/lib/active_support/core_ext/class.rb +4 -3
  37. data/lib/active_support/core_ext/class/attribute.rb +41 -22
  38. data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
  39. data/lib/active_support/core_ext/class/subclasses.rb +20 -8
  40. data/lib/active_support/core_ext/date.rb +6 -4
  41. data/lib/active_support/core_ext/date/acts_like.rb +3 -1
  42. data/lib/active_support/core_ext/date/blank.rb +14 -0
  43. data/lib/active_support/core_ext/date/calculations.rb +11 -9
  44. data/lib/active_support/core_ext/date/conversions.rb +31 -23
  45. data/lib/active_support/core_ext/date/zones.rb +4 -2
  46. data/lib/active_support/core_ext/date_and_time/calculations.rb +179 -56
  47. data/lib/active_support/core_ext/date_and_time/compatibility.rb +16 -0
  48. data/lib/active_support/core_ext/date_and_time/zones.rb +12 -12
  49. data/lib/active_support/core_ext/date_time.rb +7 -4
  50. data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
  51. data/lib/active_support/core_ext/date_time/blank.rb +14 -0
  52. data/lib/active_support/core_ext/date_time/calculations.rb +58 -20
  53. data/lib/active_support/core_ext/date_time/compatibility.rb +18 -0
  54. data/lib/active_support/core_ext/date_time/conversions.rb +16 -12
  55. data/lib/active_support/core_ext/digest/uuid.rb +7 -5
  56. data/lib/active_support/core_ext/enumerable.rb +107 -28
  57. data/lib/active_support/core_ext/file.rb +3 -1
  58. data/lib/active_support/core_ext/file/atomic.rb +38 -31
  59. data/lib/active_support/core_ext/hash.rb +11 -9
  60. data/lib/active_support/core_ext/hash/compact.rb +24 -15
  61. data/lib/active_support/core_ext/hash/conversions.rb +63 -43
  62. data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
  63. data/lib/active_support/core_ext/hash/except.rb +11 -8
  64. data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -3
  65. data/lib/active_support/core_ext/hash/keys.rb +33 -27
  66. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  67. data/lib/active_support/core_ext/hash/slice.rb +8 -8
  68. data/lib/active_support/core_ext/hash/transform_values.rb +16 -7
  69. data/lib/active_support/core_ext/integer.rb +5 -3
  70. data/lib/active_support/core_ext/integer/inflections.rb +3 -1
  71. data/lib/active_support/core_ext/integer/multiple.rb +2 -0
  72. data/lib/active_support/core_ext/integer/time.rb +11 -33
  73. data/lib/active_support/core_ext/kernel.rb +6 -5
  74. data/lib/active_support/core_ext/kernel/agnostics.rb +2 -0
  75. data/lib/active_support/core_ext/kernel/concern.rb +5 -1
  76. data/lib/active_support/core_ext/kernel/reporting.rb +4 -83
  77. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  78. data/lib/active_support/core_ext/load_error.rb +3 -22
  79. data/lib/active_support/core_ext/marshal.rb +13 -10
  80. data/lib/active_support/core_ext/module.rb +14 -11
  81. data/lib/active_support/core_ext/module/aliasing.rb +6 -44
  82. data/lib/active_support/core_ext/module/anonymous.rb +12 -1
  83. data/lib/active_support/core_ext/module/attr_internal.rb +8 -9
  84. data/lib/active_support/core_ext/module/attribute_accessors.rb +43 -40
  85. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +150 -0
  86. data/lib/active_support/core_ext/module/concerning.rb +11 -12
  87. data/lib/active_support/core_ext/module/delegation.rb +121 -39
  88. data/lib/active_support/core_ext/module/deprecation.rb +4 -2
  89. data/lib/active_support/core_ext/module/introspection.rb +9 -9
  90. data/lib/active_support/core_ext/module/reachable.rb +5 -2
  91. data/lib/active_support/core_ext/module/redefine_method.rb +49 -0
  92. data/lib/active_support/core_ext/module/remove_method.rb +8 -3
  93. data/lib/active_support/core_ext/name_error.rb +22 -2
  94. data/lib/active_support/core_ext/numeric.rb +6 -3
  95. data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
  96. data/lib/active_support/core_ext/numeric/conversions.rb +79 -74
  97. data/lib/active_support/core_ext/numeric/inquiry.rb +28 -0
  98. data/lib/active_support/core_ext/numeric/time.rb +35 -38
  99. data/lib/active_support/core_ext/object.rb +14 -13
  100. data/lib/active_support/core_ext/object/acts_like.rb +12 -1
  101. data/lib/active_support/core_ext/object/blank.rb +29 -4
  102. data/lib/active_support/core_ext/object/conversions.rb +6 -4
  103. data/lib/active_support/core_ext/object/deep_dup.rb +13 -4
  104. data/lib/active_support/core_ext/object/duplicable.rb +98 -45
  105. data/lib/active_support/core_ext/object/inclusion.rb +5 -3
  106. data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
  107. data/lib/active_support/core_ext/object/json.rb +49 -19
  108. data/lib/active_support/core_ext/object/to_param.rb +3 -1
  109. data/lib/active_support/core_ext/object/to_query.rb +6 -4
  110. data/lib/active_support/core_ext/object/try.rb +70 -22
  111. data/lib/active_support/core_ext/object/with_options.rb +16 -3
  112. data/lib/active_support/core_ext/range.rb +7 -4
  113. data/lib/active_support/core_ext/range/conversions.rb +27 -7
  114. data/lib/active_support/core_ext/range/each.rb +19 -17
  115. data/lib/active_support/core_ext/range/include_range.rb +21 -19
  116. data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -0
  117. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  118. data/lib/active_support/core_ext/regexp.rb +6 -0
  119. data/lib/active_support/core_ext/securerandom.rb +25 -0
  120. data/lib/active_support/core_ext/string.rb +15 -13
  121. data/lib/active_support/core_ext/string/access.rb +9 -7
  122. data/lib/active_support/core_ext/string/behavior.rb +3 -1
  123. data/lib/active_support/core_ext/string/conversions.rb +8 -5
  124. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  125. data/lib/active_support/core_ext/string/filters.rb +10 -8
  126. data/lib/active_support/core_ext/string/indent.rb +6 -4
  127. data/lib/active_support/core_ext/string/inflections.rb +61 -24
  128. data/lib/active_support/core_ext/string/inquiry.rb +3 -1
  129. data/lib/active_support/core_ext/string/multibyte.rb +15 -7
  130. data/lib/active_support/core_ext/string/output_safety.rb +35 -35
  131. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
  132. data/lib/active_support/core_ext/string/strip.rb +4 -5
  133. data/lib/active_support/core_ext/string/zones.rb +4 -2
  134. data/lib/active_support/core_ext/time.rb +7 -5
  135. data/lib/active_support/core_ext/time/acts_like.rb +3 -1
  136. data/lib/active_support/core_ext/time/calculations.rb +101 -51
  137. data/lib/active_support/core_ext/time/compatibility.rb +16 -0
  138. data/lib/active_support/core_ext/time/conversions.rb +20 -13
  139. data/lib/active_support/core_ext/time/zones.rb +41 -7
  140. data/lib/active_support/core_ext/uri.rb +5 -4
  141. data/lib/active_support/current_attributes.rb +195 -0
  142. data/lib/active_support/dependencies.rb +143 -160
  143. data/lib/active_support/dependencies/autoload.rb +2 -0
  144. data/lib/active_support/dependencies/interlock.rb +57 -0
  145. data/lib/active_support/deprecation.rb +12 -9
  146. data/lib/active_support/deprecation/behaviors.rb +41 -12
  147. data/lib/active_support/deprecation/constant_accessor.rb +52 -0
  148. data/lib/active_support/deprecation/instance_delegator.rb +17 -2
  149. data/lib/active_support/deprecation/method_wrappers.rb +54 -21
  150. data/lib/active_support/deprecation/proxy_wrappers.rb +56 -28
  151. data/lib/active_support/deprecation/reporting.rb +32 -12
  152. data/lib/active_support/descendants_tracker.rb +2 -0
  153. data/lib/active_support/digest.rb +20 -0
  154. data/lib/active_support/duration.rb +326 -30
  155. data/lib/active_support/duration/iso8601_parser.rb +125 -0
  156. data/lib/active_support/duration/iso8601_serializer.rb +55 -0
  157. data/lib/active_support/encrypted_configuration.rb +49 -0
  158. data/lib/active_support/encrypted_file.rb +99 -0
  159. data/lib/active_support/evented_file_update_checker.rb +205 -0
  160. data/lib/active_support/execution_wrapper.rb +128 -0
  161. data/lib/active_support/executor.rb +8 -0
  162. data/lib/active_support/file_update_checker.rb +63 -37
  163. data/lib/active_support/gem_version.rb +4 -2
  164. data/lib/active_support/gzip.rb +7 -5
  165. data/lib/active_support/hash_with_indifferent_access.rb +130 -30
  166. data/lib/active_support/i18n.rb +8 -6
  167. data/lib/active_support/i18n_railtie.rb +34 -14
  168. data/lib/active_support/inflections.rb +13 -11
  169. data/lib/active_support/inflector.rb +7 -5
  170. data/lib/active_support/inflector/inflections.rb +61 -12
  171. data/lib/active_support/inflector/methods.rb +161 -136
  172. data/lib/active_support/inflector/transliterate.rb +48 -27
  173. data/lib/active_support/json.rb +4 -2
  174. data/lib/active_support/json/decoding.rb +16 -13
  175. data/lib/active_support/json/encoding.rb +15 -57
  176. data/lib/active_support/key_generator.rb +25 -25
  177. data/lib/active_support/lazy_load_hooks.rb +50 -20
  178. data/lib/active_support/locale/en.yml +2 -0
  179. data/lib/active_support/log_subscriber.rb +13 -10
  180. data/lib/active_support/log_subscriber/test_helper.rb +14 -12
  181. data/lib/active_support/logger.rb +54 -3
  182. data/lib/active_support/logger_silence.rb +12 -7
  183. data/lib/active_support/logger_thread_safe_level.rb +33 -0
  184. data/lib/active_support/message_encryptor.rb +173 -51
  185. data/lib/active_support/message_verifier.rb +150 -17
  186. data/lib/active_support/messages/metadata.rb +71 -0
  187. data/lib/active_support/messages/rotation_configuration.rb +22 -0
  188. data/lib/active_support/messages/rotator.rb +56 -0
  189. data/lib/active_support/multibyte.rb +4 -2
  190. data/lib/active_support/multibyte/chars.rb +37 -24
  191. data/lib/active_support/multibyte/unicode.rb +100 -96
  192. data/lib/active_support/notifications.rb +11 -7
  193. data/lib/active_support/notifications/fanout.rb +10 -8
  194. data/lib/active_support/notifications/instrumenter.rb +27 -7
  195. data/lib/active_support/number_helper.rb +94 -68
  196. data/lib/active_support/number_helper/number_converter.rb +13 -11
  197. data/lib/active_support/number_helper/number_to_currency_converter.rb +9 -9
  198. data/lib/active_support/number_helper/number_to_delimited_converter.rb +9 -3
  199. data/lib/active_support/number_helper/number_to_human_converter.rb +11 -9
  200. data/lib/active_support/number_helper/number_to_human_size_converter.rb +9 -8
  201. data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
  202. data/lib/active_support/number_helper/number_to_phone_converter.rb +13 -4
  203. data/lib/active_support/number_helper/number_to_rounded_converter.rb +23 -56
  204. data/lib/active_support/number_helper/rounding_helper.rb +66 -0
  205. data/lib/active_support/option_merger.rb +3 -1
  206. data/lib/active_support/ordered_hash.rb +6 -4
  207. data/lib/active_support/ordered_options.rb +22 -4
  208. data/lib/active_support/per_thread_registry.rb +13 -6
  209. data/lib/active_support/proxy_object.rb +2 -0
  210. data/lib/active_support/rails.rb +16 -8
  211. data/lib/active_support/railtie.rb +43 -9
  212. data/lib/active_support/reloader.rb +131 -0
  213. data/lib/active_support/rescuable.rb +108 -53
  214. data/lib/active_support/security_utils.rb +17 -6
  215. data/lib/active_support/string_inquirer.rb +11 -3
  216. data/lib/active_support/subscriber.rb +15 -14
  217. data/lib/active_support/tagged_logging.rb +14 -11
  218. data/lib/active_support/test_case.rb +18 -46
  219. data/lib/active_support/testing/assertions.rb +137 -20
  220. data/lib/active_support/testing/autorun.rb +4 -2
  221. data/lib/active_support/testing/constant_lookup.rb +2 -1
  222. data/lib/active_support/testing/declarative.rb +3 -1
  223. data/lib/active_support/testing/deprecation.rb +14 -10
  224. data/lib/active_support/testing/file_fixtures.rb +36 -0
  225. data/lib/active_support/testing/isolation.rb +34 -25
  226. data/lib/active_support/testing/method_call_assertions.rb +43 -0
  227. data/lib/active_support/testing/setup_and_teardown.rb +12 -3
  228. data/lib/active_support/testing/stream.rb +44 -0
  229. data/lib/active_support/testing/tagged_logging.rb +3 -1
  230. data/lib/active_support/testing/time_helpers.rb +96 -27
  231. data/lib/active_support/time.rb +14 -12
  232. data/lib/active_support/time_with_zone.rb +195 -53
  233. data/lib/active_support/values/time_zone.rb +200 -61
  234. data/lib/active_support/values/unicode_tables.dat +0 -0
  235. data/lib/active_support/version.rb +3 -1
  236. data/lib/active_support/xml_mini.rb +69 -51
  237. data/lib/active_support/xml_mini/jdom.rb +116 -113
  238. data/lib/active_support/xml_mini/libxml.rb +17 -16
  239. data/lib/active_support/xml_mini/libxmlsax.rb +16 -18
  240. data/lib/active_support/xml_mini/nokogiri.rb +15 -15
  241. data/lib/active_support/xml_mini/nokogirisax.rb +15 -16
  242. data/lib/active_support/xml_mini/rexml.rb +17 -16
  243. metadata +55 -43
  244. data/lib/active_support/concurrency/latch.rb +0 -27
  245. data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -14
  246. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
  247. data/lib/active_support/core_ext/date_time/zones.rb +0 -6
  248. data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
  249. data/lib/active_support/core_ext/module/method_transplanting.rb +0 -11
  250. data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
  251. data/lib/active_support/core_ext/object/itself.rb +0 -15
  252. data/lib/active_support/core_ext/struct.rb +0 -6
  253. data/lib/active_support/core_ext/thread.rb +0 -86
  254. data/lib/active_support/core_ext/time/marshal.rb +0 -30
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support"
2
4
  require "active_support/i18n_railtie"
3
5
 
@@ -7,6 +9,21 @@ module ActiveSupport
7
9
 
8
10
  config.eager_load_namespaces << ActiveSupport
9
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
+
10
27
  initializer "active_support.deprecation_behavior" do |app|
11
28
  if deprecation = app.config.active_support.deprecation
12
29
  ActiveSupport::Deprecation.behavior = deprecation
@@ -16,31 +33,48 @@ module ActiveSupport
16
33
  # Sets the default value for Time.zone
17
34
  # If assigned value cannot be matched to a TimeZone, an exception will be raised.
18
35
  initializer "active_support.initialize_time_zone" do |app|
19
- require 'active_support/core_ext/time/zones'
20
- zone_default = Time.find_zone!(app.config.time_zone)
21
-
22
- unless zone_default
23
- raise 'Value assigned to config.time_zone not recognized. ' \
24
- 'Run "rake -D time" for a list of tasks for finding appropriate time zone names.'
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"
25
40
  end
26
-
27
- Time.zone_default = zone_default
41
+ require "active_support/core_ext/time/zones"
42
+ Time.zone_default = Time.find_zone!(app.config.time_zone)
28
43
  end
29
44
 
30
45
  # Sets the default week start
31
46
  # If assigned value is not a valid day symbol (e.g. :sunday, :monday, ...), an exception will be raised.
32
47
  initializer "active_support.initialize_beginning_of_week" do |app|
33
- require 'active_support/core_ext/date/calculations'
48
+ require "active_support/core_ext/date/calculations"
34
49
  beginning_of_week_default = Date.find_beginning_of_week!(app.config.beginning_of_week)
35
50
 
36
51
  Date.beginning_of_week_default = beginning_of_week_default
37
52
  end
38
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
+
39
65
  initializer "active_support.set_configs" do |app|
40
66
  app.config.active_support.each do |k, v|
41
67
  k = "#{k}="
42
68
  ActiveSupport.send(k, v) if ActiveSupport.respond_to? k
43
69
  end
44
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
45
79
  end
46
80
  end
@@ -0,0 +1,131 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/execution_wrapper"
4
+
5
+ module ActiveSupport
6
+ #--
7
+ # This class defines several callbacks:
8
+ #
9
+ # to_prepare -- Run once at application startup, and also from
10
+ # +to_run+.
11
+ #
12
+ # to_run -- Run before a work run that is reloading. If
13
+ # +reload_classes_only_on_change+ is true (the default), the class
14
+ # unload will have already occurred.
15
+ #
16
+ # to_complete -- Run after a work run that has reloaded. If
17
+ # +reload_classes_only_on_change+ is false, the class unload will
18
+ # have occurred after the work run, but before this callback.
19
+ #
20
+ # before_class_unload -- Run immediately before the classes are
21
+ # unloaded.
22
+ #
23
+ # after_class_unload -- Run immediately after the classes are
24
+ # unloaded.
25
+ #
26
+ class Reloader < ExecutionWrapper
27
+ define_callbacks :prepare
28
+
29
+ define_callbacks :class_unload
30
+
31
+ # Registers a callback that will run once at application startup and every time the code is reloaded.
32
+ def self.to_prepare(*args, &block)
33
+ set_callback(:prepare, *args, &block)
34
+ end
35
+
36
+ # Registers a callback that will run immediately before the classes are unloaded.
37
+ def self.before_class_unload(*args, &block)
38
+ set_callback(:class_unload, *args, &block)
39
+ end
40
+
41
+ # Registers a callback that will run immediately after the classes are unloaded.
42
+ def self.after_class_unload(*args, &block)
43
+ set_callback(:class_unload, :after, *args, &block)
44
+ end
45
+
46
+ to_run(:after) { self.class.prepare! }
47
+
48
+ # Initiate a manual reload
49
+ def self.reload!
50
+ executor.wrap do
51
+ new.tap do |instance|
52
+ begin
53
+ instance.run!
54
+ ensure
55
+ instance.complete!
56
+ end
57
+ end
58
+ end
59
+ prepare!
60
+ end
61
+
62
+ def self.run! # :nodoc:
63
+ if check!
64
+ super
65
+ else
66
+ Null
67
+ end
68
+ end
69
+
70
+ # Run the supplied block as a work unit, reloading code as needed
71
+ def self.wrap
72
+ executor.wrap do
73
+ super
74
+ end
75
+ end
76
+
77
+ class_attribute :executor, default: Executor
78
+ class_attribute :check, default: lambda { false }
79
+
80
+ def self.check! # :nodoc:
81
+ @should_reload ||= check.call
82
+ end
83
+
84
+ def self.reloaded! # :nodoc:
85
+ @should_reload = false
86
+ end
87
+
88
+ def self.prepare! # :nodoc:
89
+ new.run_callbacks(:prepare)
90
+ end
91
+
92
+ def initialize
93
+ super
94
+ @locked = false
95
+ end
96
+
97
+ # Acquire the ActiveSupport::Dependencies::Interlock unload lock,
98
+ # ensuring it will be released automatically
99
+ def require_unload_lock!
100
+ unless @locked
101
+ ActiveSupport::Dependencies.interlock.start_unloading
102
+ @locked = true
103
+ end
104
+ end
105
+
106
+ # Release the unload lock if it has been previously obtained
107
+ def release_unload_lock!
108
+ if @locked
109
+ @locked = false
110
+ ActiveSupport::Dependencies.interlock.done_unloading
111
+ end
112
+ end
113
+
114
+ def run! # :nodoc:
115
+ super
116
+ release_unload_lock!
117
+ end
118
+
119
+ def class_unload!(&block) # :nodoc:
120
+ require_unload_lock!
121
+ run_callbacks(:class_unload, &block)
122
+ end
123
+
124
+ def complete! # :nodoc:
125
+ super
126
+ self.class.reloaded!
127
+ ensure
128
+ release_unload_lock!
129
+ end
130
+ end
131
+ end
@@ -1,7 +1,8 @@
1
- require 'active_support/concern'
2
- require 'active_support/core_ext/class/attribute'
3
- require 'active_support/core_ext/string/inflections'
4
- require 'active_support/core_ext/array/extract_options'
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"
5
6
 
6
7
  module ActiveSupport
7
8
  # Rescuable module adds support for easier exception handling.
@@ -9,8 +10,7 @@ module ActiveSupport
9
10
  extend Concern
10
11
 
11
12
  included do
12
- class_attribute :rescue_handlers
13
- self.rescue_handlers = []
13
+ class_attribute :rescue_handlers, default: []
14
14
  end
15
15
 
16
16
  module ClassMethods
@@ -37,7 +37,7 @@ module ActiveSupport
37
37
  # render xml: exception, status: 500
38
38
  # end
39
39
  #
40
- # protected
40
+ # private
41
41
  # def deny_access
42
42
  # ...
43
43
  # end
@@ -48,72 +48,127 @@ module ActiveSupport
48
48
  # end
49
49
  #
50
50
  # Exceptions raised inside exception handlers are not propagated up.
51
- def rescue_from(*klasses, &block)
52
- options = klasses.extract_options!
53
-
54
- unless options.has_key?(:with)
51
+ def rescue_from(*klasses, with: nil, &block)
52
+ unless with
55
53
  if block_given?
56
- options[:with] = block
54
+ with = block
57
55
  else
58
- raise ArgumentError, "Need a handler. Supply an options hash that has a :with key as the last argument."
56
+ raise ArgumentError, "Need a handler. Pass the with: keyword argument or provide a block."
59
57
  end
60
58
  end
61
59
 
62
60
  klasses.each do |klass|
63
- key = if klass.is_a?(Class) && klass <= Exception
61
+ key = if klass.is_a?(Module) && klass.respond_to?(:===)
64
62
  klass.name
65
63
  elsif klass.is_a?(String)
66
64
  klass
67
65
  else
68
- raise ArgumentError, "#{klass} is neither an Exception nor a String"
66
+ raise ArgumentError, "#{klass.inspect} must be an Exception class or a String referencing an Exception class"
69
67
  end
70
68
 
71
- # put the new handler at the end because the list is read in reverse
72
- self.rescue_handlers += [[key, options[:with]]]
69
+ # Put the new handler at the end because the list is read in reverse.
70
+ self.rescue_handlers += [[key, with]]
73
71
  end
74
72
  end
75
- end
76
73
 
77
- # Tries to rescue the exception by looking up and calling a registered handler.
78
- def rescue_with_handler(exception)
79
- if handler = handler_for_rescue(exception)
80
- handler.arity != 0 ? handler.call(exception) : handler.call
81
- true # don't rely on the return value of the handler
82
- end
83
- end
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
84
90
 
85
- def handler_for_rescue(exception)
86
- # We go from right to left because pairs are pushed onto rescue_handlers
87
- # as rescue_from declarations are found.
88
- _, rescuer = self.class.rescue_handlers.reverse.detect do |klass_name, handler|
89
- # The purpose of allowing strings in rescue_from is to support the
90
- # declaration of handler associations for exception classes whose
91
- # definition is yet unknown.
92
- #
93
- # Since this loop needs the constants it would be inconsistent to
94
- # assume they should exist at this point. An early raised exception
95
- # could trigger some other handler and the array could include
96
- # precisely a string whose corresponding constant has not yet been
97
- # seen. This is why we are tolerant to unknown constants.
98
- #
99
- # Note that this tolerance only matters if the exception was given as
100
- # a string, otherwise a NameError will be raised by the interpreter
101
- # itself when rescue_from CONSTANT is executed.
102
- klass = self.class.const_get(klass_name) rescue nil
103
- klass ||= klass_name.constantize rescue nil
104
- exception.is_a?(klass) if klass
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
105
101
  end
106
102
 
107
- case rescuer
108
- when Symbol
109
- method(rescuer)
110
- when Proc
111
- if rescuer.arity == 0
112
- Proc.new { instance_exec(&rescuer) }
113
- else
114
- Proc.new { |_exception| instance_exec(_exception, &rescuer) }
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
115
118
  end
116
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
117
172
  end
118
173
  end
119
174
  end
@@ -1,13 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "digest/sha2"
4
+
1
5
  module ActiveSupport
2
6
  module SecurityUtils
3
- # Constant time string comparison.
7
+ # Constant time string comparison, for fixed length strings.
4
8
  #
5
9
  # The values compared should be of fixed length, such as strings
6
- # that have already been processed by HMAC. This should not be used
7
- # on variable length plaintext strings because it could leak length info
8
- # via timing attacks.
9
- def secure_compare(a, b)
10
- return false unless a.bytesize == b.bytesize
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
11
13
 
12
14
  l = a.unpack "C#{a.bytesize}"
13
15
 
@@ -15,6 +17,15 @@ module ActiveSupport
15
17
  b.each_byte { |byte| res |= byte ^ l.shift }
16
18
  res == 0
17
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.hexdigest(a), ::Digest::SHA256.hexdigest(b)) && a == b
28
+ end
18
29
  module_function :secure_compare
19
30
  end
20
31
  end