activesupport 5.1.7 → 7.0.4.1

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

Potentially problematic release.


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

Files changed (279) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +259 -585
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +6 -5
  5. data/lib/active_support/actionable_error.rb +48 -0
  6. data/lib/active_support/all.rb +2 -0
  7. data/lib/active_support/array_inquirer.rb +4 -2
  8. data/lib/active_support/backtrace_cleaner.rb +33 -5
  9. data/lib/active_support/benchmarkable.rb +5 -3
  10. data/lib/active_support/builder.rb +2 -0
  11. data/lib/active_support/cache/file_store.rb +50 -43
  12. data/lib/active_support/cache/mem_cache_store.rb +194 -67
  13. data/lib/active_support/cache/memory_store.rb +70 -34
  14. data/lib/active_support/cache/null_store.rb +18 -3
  15. data/lib/active_support/cache/redis_cache_store.rb +474 -0
  16. data/lib/active_support/cache/strategy/local_cache.rb +73 -50
  17. data/lib/active_support/cache/strategy/local_cache_middleware.rb +2 -0
  18. data/lib/active_support/cache.rb +556 -220
  19. data/lib/active_support/callbacks.rb +264 -159
  20. data/lib/active_support/code_generator.rb +65 -0
  21. data/lib/active_support/concern.rb +81 -8
  22. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +16 -0
  23. data/lib/active_support/concurrency/share_lock.rb +4 -3
  24. data/lib/active_support/configurable.rb +17 -16
  25. data/lib/active_support/configuration_file.rb +51 -0
  26. data/lib/active_support/core_ext/array/access.rb +18 -8
  27. data/lib/active_support/core_ext/array/conversions.rb +20 -17
  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 +8 -6
  32. data/lib/active_support/core_ext/array/inquiry.rb +4 -2
  33. data/lib/active_support/core_ext/array/wrap.rb +2 -0
  34. data/lib/active_support/core_ext/array.rb +4 -1
  35. data/lib/active_support/core_ext/benchmark.rb +4 -2
  36. data/lib/active_support/core_ext/big_decimal/conversions.rb +3 -1
  37. data/lib/active_support/core_ext/big_decimal.rb +2 -0
  38. data/lib/active_support/core_ext/class/attribute.rb +50 -47
  39. data/lib/active_support/core_ext/class/attribute_accessors.rb +2 -0
  40. data/lib/active_support/core_ext/class/subclasses.rb +10 -24
  41. data/lib/active_support/core_ext/class.rb +2 -0
  42. data/lib/active_support/core_ext/date/acts_like.rb +2 -0
  43. data/lib/active_support/core_ext/date/blank.rb +3 -1
  44. data/lib/active_support/core_ext/date/calculations.rb +17 -14
  45. data/lib/active_support/core_ext/date/conversions.rb +24 -22
  46. data/lib/active_support/core_ext/date/deprecated_conversions.rb +26 -0
  47. data/lib/active_support/core_ext/date/zones.rb +2 -0
  48. data/lib/active_support/core_ext/date.rb +3 -0
  49. data/lib/active_support/core_ext/date_and_time/calculations.rb +65 -41
  50. data/lib/active_support/core_ext/date_and_time/compatibility.rb +18 -1
  51. data/lib/active_support/core_ext/date_and_time/zones.rb +2 -1
  52. data/lib/active_support/core_ext/date_time/acts_like.rb +2 -0
  53. data/lib/active_support/core_ext/date_time/blank.rb +3 -1
  54. data/lib/active_support/core_ext/date_time/calculations.rb +3 -1
  55. data/lib/active_support/core_ext/date_time/compatibility.rb +7 -5
  56. data/lib/active_support/core_ext/date_time/conversions.rb +15 -14
  57. data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +22 -0
  58. data/lib/active_support/core_ext/date_time.rb +3 -0
  59. data/lib/active_support/core_ext/digest/uuid.rb +42 -14
  60. data/lib/active_support/core_ext/digest.rb +3 -0
  61. data/lib/active_support/core_ext/enumerable.rb +244 -72
  62. data/lib/active_support/core_ext/file/atomic.rb +6 -2
  63. data/lib/active_support/core_ext/file.rb +2 -0
  64. data/lib/active_support/core_ext/hash/conversions.rb +7 -6
  65. data/lib/active_support/core_ext/hash/deep_merge.rb +8 -12
  66. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  67. data/lib/active_support/core_ext/hash/except.rb +4 -2
  68. data/lib/active_support/core_ext/hash/indifferent_access.rb +5 -3
  69. data/lib/active_support/core_ext/hash/keys.rb +4 -31
  70. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  71. data/lib/active_support/core_ext/hash/slice.rb +8 -29
  72. data/lib/active_support/core_ext/hash.rb +3 -2
  73. data/lib/active_support/core_ext/integer/inflections.rb +2 -0
  74. data/lib/active_support/core_ext/integer/multiple.rb +3 -1
  75. data/lib/active_support/core_ext/integer/time.rb +7 -14
  76. data/lib/active_support/core_ext/integer.rb +2 -0
  77. data/lib/active_support/core_ext/kernel/concern.rb +2 -0
  78. data/lib/active_support/core_ext/kernel/reporting.rb +6 -4
  79. data/lib/active_support/core_ext/kernel/singleton_class.rb +3 -1
  80. data/lib/active_support/core_ext/kernel.rb +2 -1
  81. data/lib/active_support/core_ext/load_error.rb +3 -8
  82. data/lib/active_support/core_ext/module/aliasing.rb +2 -0
  83. data/lib/active_support/core_ext/module/anonymous.rb +2 -0
  84. data/lib/active_support/core_ext/module/attr_internal.rb +4 -2
  85. data/lib/active_support/core_ext/module/attribute_accessors.rb +46 -56
  86. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +36 -27
  87. data/lib/active_support/core_ext/module/concerning.rb +15 -10
  88. data/lib/active_support/core_ext/module/delegation.rb +97 -58
  89. data/lib/active_support/core_ext/module/deprecation.rb +2 -0
  90. data/lib/active_support/core_ext/module/introspection.rb +18 -15
  91. data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
  92. data/lib/active_support/core_ext/module/remove_method.rb +5 -23
  93. data/lib/active_support/core_ext/module.rb +3 -1
  94. data/lib/active_support/core_ext/name_error.rb +30 -2
  95. data/lib/active_support/core_ext/numeric/bytes.rb +2 -0
  96. data/lib/active_support/core_ext/numeric/conversions.rb +134 -129
  97. data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +60 -0
  98. data/lib/active_support/core_ext/numeric/time.rb +7 -15
  99. data/lib/active_support/core_ext/numeric.rb +3 -1
  100. data/lib/active_support/core_ext/object/acts_like.rb +41 -6
  101. data/lib/active_support/core_ext/object/blank.rb +15 -5
  102. data/lib/active_support/core_ext/object/conversions.rb +2 -0
  103. data/lib/active_support/core_ext/object/deep_dup.rb +3 -1
  104. data/lib/active_support/core_ext/object/duplicable.rb +16 -110
  105. data/lib/active_support/core_ext/object/inclusion.rb +2 -0
  106. data/lib/active_support/core_ext/object/instance_variables.rb +2 -0
  107. data/lib/active_support/core_ext/object/json.rb +51 -26
  108. data/lib/active_support/core_ext/object/to_param.rb +2 -0
  109. data/lib/active_support/core_ext/object/to_query.rb +4 -2
  110. data/lib/active_support/core_ext/object/try.rb +26 -14
  111. data/lib/active_support/core_ext/object/with_options.rb +24 -3
  112. data/lib/active_support/core_ext/object.rb +2 -0
  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 +35 -25
  117. data/lib/active_support/core_ext/range/deprecated_conversions.rb +26 -0
  118. data/lib/active_support/core_ext/range/each.rb +6 -3
  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 +3 -1
  121. data/lib/active_support/core_ext/range.rb +4 -1
  122. data/lib/active_support/core_ext/regexp.rb +10 -5
  123. data/lib/active_support/core_ext/securerandom.rb +25 -3
  124. data/lib/active_support/core_ext/string/access.rb +7 -16
  125. data/lib/active_support/core_ext/string/behavior.rb +2 -0
  126. data/lib/active_support/core_ext/string/conversions.rb +5 -2
  127. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  128. data/lib/active_support/core_ext/string/filters.rb +44 -1
  129. data/lib/active_support/core_ext/string/indent.rb +2 -0
  130. data/lib/active_support/core_ext/string/inflections.rb +69 -16
  131. data/lib/active_support/core_ext/string/inquiry.rb +4 -1
  132. data/lib/active_support/core_ext/string/multibyte.rb +9 -4
  133. data/lib/active_support/core_ext/string/output_safety.rb +135 -27
  134. data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
  135. data/lib/active_support/core_ext/string/strip.rb +5 -1
  136. data/lib/active_support/core_ext/string/zones.rb +2 -0
  137. data/lib/active_support/core_ext/string.rb +2 -0
  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 +2 -0
  141. data/lib/active_support/core_ext/time/calculations.rb +81 -24
  142. data/lib/active_support/core_ext/time/compatibility.rb +4 -2
  143. data/lib/active_support/core_ext/time/conversions.rb +17 -12
  144. data/lib/active_support/core_ext/time/deprecated_conversions.rb +22 -0
  145. data/lib/active_support/core_ext/time/zones.rb +12 -25
  146. data/lib/active_support/core_ext/time.rb +3 -0
  147. data/lib/active_support/core_ext/uri.rb +4 -23
  148. data/lib/active_support/core_ext.rb +4 -1
  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 +2 -0
  152. data/lib/active_support/dependencies/interlock.rb +12 -18
  153. data/lib/active_support/dependencies/require_dependency.rb +28 -0
  154. data/lib/active_support/dependencies.rb +59 -715
  155. data/lib/active_support/deprecation/behaviors.rb +48 -13
  156. data/lib/active_support/deprecation/constant_accessor.rb +4 -2
  157. data/lib/active_support/deprecation/disallowed.rb +56 -0
  158. data/lib/active_support/deprecation/instance_delegator.rb +2 -1
  159. data/lib/active_support/deprecation/method_wrappers.rb +29 -21
  160. data/lib/active_support/deprecation/proxy_wrappers.rb +34 -8
  161. data/lib/active_support/deprecation/reporting.rb +54 -9
  162. data/lib/active_support/deprecation.rb +10 -3
  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 +9 -9
  166. data/lib/active_support/duration/iso8601_serializer.rb +29 -15
  167. data/lib/active_support/duration.rb +158 -72
  168. data/lib/active_support/encrypted_configuration.rb +56 -0
  169. data/lib/active_support/encrypted_file.rb +129 -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 +87 -122
  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 +46 -21
  176. data/lib/active_support/executor/test_helper.rb +7 -0
  177. data/lib/active_support/executor.rb +2 -0
  178. data/lib/active_support/file_update_checker.rb +2 -1
  179. data/lib/active_support/fork_tracker.rb +71 -0
  180. data/lib/active_support/gem_version.rb +7 -5
  181. data/lib/active_support/gzip.rb +2 -0
  182. data/lib/active_support/hash_with_indifferent_access.rb +126 -42
  183. data/lib/active_support/html_safe_translation.rb +43 -0
  184. data/lib/active_support/i18n.rb +5 -1
  185. data/lib/active_support/i18n_railtie.rb +19 -14
  186. data/lib/active_support/inflections.rb +2 -0
  187. data/lib/active_support/inflector/inflections.rb +41 -14
  188. data/lib/active_support/inflector/methods.rb +73 -87
  189. data/lib/active_support/inflector/transliterate.rb +56 -18
  190. data/lib/active_support/inflector.rb +2 -0
  191. data/lib/active_support/isolated_execution_state.rb +72 -0
  192. data/lib/active_support/json/decoding.rb +27 -26
  193. data/lib/active_support/json/encoding.rb +16 -6
  194. data/lib/active_support/json.rb +2 -0
  195. data/lib/active_support/key_generator.rb +25 -38
  196. data/lib/active_support/lazy_load_hooks.rb +35 -6
  197. data/lib/active_support/locale/en.rb +33 -0
  198. data/lib/active_support/locale/en.yml +8 -4
  199. data/lib/active_support/log_subscriber/test_helper.rb +4 -2
  200. data/lib/active_support/log_subscriber.rb +54 -13
  201. data/lib/active_support/logger.rb +4 -17
  202. data/lib/active_support/logger_silence.rb +13 -20
  203. data/lib/active_support/logger_thread_safe_level.rb +48 -10
  204. data/lib/active_support/message_encryptor.rb +111 -37
  205. data/lib/active_support/message_verifier.rb +124 -21
  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 +19 -76
  210. data/lib/active_support/multibyte/unicode.rb +9 -331
  211. data/lib/active_support/multibyte.rb +3 -1
  212. data/lib/active_support/notifications/fanout.rb +165 -37
  213. data/lib/active_support/notifications/instrumenter.rb +92 -11
  214. data/lib/active_support/notifications.rb +96 -30
  215. data/lib/active_support/number_helper/number_converter.rb +8 -9
  216. data/lib/active_support/number_helper/number_to_currency_converter.rb +14 -12
  217. data/lib/active_support/number_helper/number_to_delimited_converter.rb +6 -3
  218. data/lib/active_support/number_helper/number_to_human_converter.rb +6 -3
  219. data/lib/active_support/number_helper/number_to_human_size_converter.rb +7 -4
  220. data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
  221. data/lib/active_support/number_helper/number_to_phone_converter.rb +6 -3
  222. data/lib/active_support/number_helper/number_to_rounded_converter.rb +14 -27
  223. data/lib/active_support/number_helper/rounding_helper.rb +16 -34
  224. data/lib/active_support/number_helper.rb +38 -12
  225. data/lib/active_support/option_merger.rb +19 -6
  226. data/lib/active_support/ordered_hash.rb +4 -2
  227. data/lib/active_support/ordered_options.rb +18 -6
  228. data/lib/active_support/parameter_filter.rb +138 -0
  229. data/lib/active_support/per_thread_registry.rb +8 -1
  230. data/lib/active_support/proxy_object.rb +2 -0
  231. data/lib/active_support/rails.rb +3 -10
  232. data/lib/active_support/railtie.rb +112 -11
  233. data/lib/active_support/reloader.rb +12 -11
  234. data/lib/active_support/rescuable.rb +19 -18
  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 +26 -15
  238. data/lib/active_support/string_inquirer.rb +4 -3
  239. data/lib/active_support/subscriber.rb +81 -42
  240. data/lib/active_support/tagged_logging.rb +45 -9
  241. data/lib/active_support/test_case.rb +86 -2
  242. data/lib/active_support/testing/assertions.rb +89 -21
  243. data/lib/active_support/testing/autorun.rb +2 -0
  244. data/lib/active_support/testing/constant_lookup.rb +2 -0
  245. data/lib/active_support/testing/declarative.rb +2 -0
  246. data/lib/active_support/testing/deprecation.rb +54 -2
  247. data/lib/active_support/testing/file_fixtures.rb +4 -0
  248. data/lib/active_support/testing/isolation.rb +6 -4
  249. data/lib/active_support/testing/method_call_assertions.rb +34 -5
  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 +12 -7
  255. data/lib/active_support/testing/stream.rb +6 -7
  256. data/lib/active_support/testing/tagged_logging.rb +3 -1
  257. data/lib/active_support/testing/time_helpers.rb +91 -15
  258. data/lib/active_support/time.rb +2 -0
  259. data/lib/active_support/time_with_zone.rb +168 -56
  260. data/lib/active_support/values/time_zone.rb +85 -37
  261. data/lib/active_support/version.rb +3 -1
  262. data/lib/active_support/xml_mini/jdom.rb +6 -5
  263. data/lib/active_support/xml_mini/libxml.rb +9 -7
  264. data/lib/active_support/xml_mini/libxmlsax.rb +7 -5
  265. data/lib/active_support/xml_mini/nokogiri.rb +8 -6
  266. data/lib/active_support/xml_mini/nokogirisax.rb +6 -4
  267. data/lib/active_support/xml_mini/rexml.rb +13 -4
  268. data/lib/active_support/xml_mini.rb +10 -15
  269. data/lib/active_support.rb +30 -9
  270. metadata +76 -35
  271. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
  272. data/lib/active_support/core_ext/hash/compact.rb +0 -27
  273. data/lib/active_support/core_ext/hash/transform_values.rb +0 -30
  274. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
  275. data/lib/active_support/core_ext/marshal.rb +0 -22
  276. data/lib/active_support/core_ext/module/reachable.rb +0 -8
  277. data/lib/active_support/core_ext/numeric/inquiry.rb +0 -26
  278. data/lib/active_support/core_ext/range/include_range.rb +0 -23
  279. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "concurrent/map"
2
4
  require "openssl"
3
5
 
@@ -7,24 +9,41 @@ module ActiveSupport
7
9
  # This lets Rails applications have a single secure secret, but avoid reusing that
8
10
  # key in multiple incompatible contexts.
9
11
  class KeyGenerator
12
+ class << self
13
+ def hash_digest_class=(klass)
14
+ if klass.kind_of?(Class) && klass < OpenSSL::Digest
15
+ @hash_digest_class = klass
16
+ else
17
+ raise ArgumentError, "#{klass} is expected to be an OpenSSL::Digest subclass"
18
+ end
19
+ end
20
+
21
+ def hash_digest_class
22
+ @hash_digest_class ||= OpenSSL::Digest::SHA1
23
+ end
24
+ end
25
+
10
26
  def initialize(secret, options = {})
11
27
  @secret = secret
12
28
  # The default iterations are higher than required for our key derivation uses
13
29
  # on the off chance someone uses this for password storage
14
30
  @iterations = options[:iterations] || 2**16
31
+ # Also allow configuration here so people can use this to build a rotation
32
+ # scheme when switching the digest class.
33
+ @hash_digest_class = options[:hash_digest_class] || self.class.hash_digest_class
15
34
  end
16
35
 
17
- # Returns a derived key suitable for use. The default key_size is chosen
36
+ # Returns a derived key suitable for use. The default +key_size+ is chosen
18
37
  # to be compatible with the default settings of ActiveSupport::MessageVerifier.
19
- # i.e. OpenSSL::Digest::SHA1#block_length
38
+ # i.e. <tt>OpenSSL::Digest::SHA1#block_length</tt>
20
39
  def generate_key(salt, key_size = 64)
21
- OpenSSL::PKCS5.pbkdf2_hmac_sha1(@secret, salt, @iterations, key_size)
40
+ OpenSSL::PKCS5.pbkdf2_hmac(@secret, salt, @iterations, key_size, @hash_digest_class.new)
22
41
  end
23
42
  end
24
43
 
25
44
  # CachingKeyGenerator is a wrapper around KeyGenerator which allows users to avoid
26
- # re-executing the key generation process when it's called using the same salt and
27
- # key_size.
45
+ # re-executing the key generation process when it's called using the same +salt+ and
46
+ # +key_size+.
28
47
  class CachingKeyGenerator
29
48
  def initialize(key_generator)
30
49
  @key_generator = key_generator
@@ -33,39 +52,7 @@ module ActiveSupport
33
52
 
34
53
  # Returns a derived key suitable for use.
35
54
  def generate_key(*args)
36
- @cache_keys[args.join] ||= @key_generator.generate_key(*args)
37
- end
38
- end
39
-
40
- class LegacyKeyGenerator # :nodoc:
41
- SECRET_MIN_LENGTH = 30 # Characters
42
-
43
- def initialize(secret)
44
- ensure_secret_secure(secret)
45
- @secret = secret
55
+ @cache_keys[args.join("|")] ||= @key_generator.generate_key(*args)
46
56
  end
47
-
48
- def generate_key(salt)
49
- @secret
50
- end
51
-
52
- private
53
-
54
- # To prevent users from using something insecure like "Password" we make sure that the
55
- # secret they've provided is at least 30 characters in length.
56
- def ensure_secret_secure(secret)
57
- if secret.blank?
58
- raise ArgumentError, "A secret is required to generate an integrity hash " \
59
- "for cookie session data. Set a secret_key_base of at least " \
60
- "#{SECRET_MIN_LENGTH} characters in config/secrets.yml."
61
- end
62
-
63
- if secret.length < SECRET_MIN_LENGTH
64
- raise ArgumentError, "Secret should be something secure, " \
65
- "like \"#{SecureRandom.hex(16)}\". The value you " \
66
- "provided, \"#{secret}\", is shorter than the minimum length " \
67
- "of #{SECRET_MIN_LENGTH} characters."
68
- end
69
- end
70
57
  end
71
58
  end
@@ -1,12 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveSupport
2
- # lazy_load_hooks allows Rails to lazily load a lot of components and thus
4
+ # LazyLoadHooks allows Rails to lazily load a lot of components and thus
3
5
  # making the app boot faster. Because of this feature now there is no need to
4
6
  # require <tt>ActiveRecord::Base</tt> at boot time purely to apply
5
7
  # configuration. Instead a hook is registered that applies configuration once
6
8
  # <tt>ActiveRecord::Base</tt> is loaded. Here <tt>ActiveRecord::Base</tt> is
7
9
  # used as example but this feature can be applied elsewhere too.
8
10
  #
9
- # Here is an example where +on_load+ method is called to register a hook.
11
+ # Here is an example where on_load method is called to register a hook.
10
12
  #
11
13
  # initializer 'active_record.initialize_timezone' do
12
14
  # ActiveSupport.on_load(:active_record) do
@@ -16,10 +18,26 @@ module ActiveSupport
16
18
  # end
17
19
  #
18
20
  # When the entirety of +ActiveRecord::Base+ has been
19
- # evaluated then +run_load_hooks+ is invoked. The very last line of
21
+ # evaluated then run_load_hooks is invoked. The very last line of
20
22
  # +ActiveRecord::Base+ is:
21
23
  #
22
24
  # ActiveSupport.run_load_hooks(:active_record, ActiveRecord::Base)
25
+ #
26
+ # run_load_hooks will then execute all the hooks that were registered
27
+ # with the on_load method. In the case of the above example, it will
28
+ # execute the block of code that is in the +initializer+.
29
+ #
30
+ # Registering a hook that has already run results in that hook executing
31
+ # immediately. This allows hooks to be nested for code that relies on
32
+ # multiple lazily loaded components:
33
+ #
34
+ # initializer "action_text.renderer" do
35
+ # ActiveSupport.on_load(:action_controller_base) do
36
+ # ActiveSupport.on_load(:action_text_content) do
37
+ # self.default_renderer = Class.new(ActionController::Base).renderer
38
+ # end
39
+ # end
40
+ # end
23
41
  module LazyLoadHooks
24
42
  def self.extended(base) # :nodoc:
25
43
  base.class_eval do
@@ -30,7 +48,8 @@ module ActiveSupport
30
48
  end
31
49
 
32
50
  # Declares a block that will be executed when a Rails component is fully
33
- # loaded.
51
+ # loaded. If the component has already loaded, the block is executed
52
+ # immediately.
34
53
  #
35
54
  # Options:
36
55
  #
@@ -44,6 +63,13 @@ module ActiveSupport
44
63
  @load_hooks[name] << [block, options]
45
64
  end
46
65
 
66
+ # Executes all blocks registered to +name+ via on_load, using +base+ as the
67
+ # evaluation context.
68
+ #
69
+ # ActiveSupport.run_load_hooks(:active_record, ActiveRecord::Base)
70
+ #
71
+ # In the case of the above example, it will execute all hooks registered
72
+ # for +:active_record+ within the class +ActiveRecord::Base+.
47
73
  def run_load_hooks(name, base = Object)
48
74
  @loaded[name] << base
49
75
  @load_hooks[name].each do |hook, options|
@@ -52,7 +78,6 @@ module ActiveSupport
52
78
  end
53
79
 
54
80
  private
55
-
56
81
  def with_execution_control(name, block, once)
57
82
  unless @run_once[name].include?(block)
58
83
  @run_once[name] << block if once
@@ -66,7 +91,11 @@ module ActiveSupport
66
91
  if options[:yield]
67
92
  block.call(base)
68
93
  else
69
- base.instance_eval(&block)
94
+ if base.is_a?(Module)
95
+ base.class_eval(&block)
96
+ else
97
+ base.instance_eval(&block)
98
+ end
70
99
  end
71
100
  end
72
101
  end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ {
4
+ en: {
5
+ number: {
6
+ nth: {
7
+ ordinals: lambda do |_key, options|
8
+ number = options[:number]
9
+ case number
10
+ when 1; "st"
11
+ when 2; "nd"
12
+ when 3; "rd"
13
+ when 4, 5, 6, 7, 8, 9, 10, 11, 12, 13; "th"
14
+ else
15
+ num_modulo = number.to_i.abs % 100
16
+ num_modulo %= 10 if num_modulo > 13
17
+ case num_modulo
18
+ when 1; "st"
19
+ when 2; "nd"
20
+ when 3; "rd"
21
+ else "th"
22
+ end
23
+ end
24
+ end,
25
+
26
+ ordinalized: lambda do |_key, options|
27
+ number = options[:number]
28
+ "#{number}#{ActiveSupport::Inflector.ordinal(number)}"
29
+ end
30
+ }
31
+ }
32
+ }
33
+ }
@@ -44,22 +44,25 @@ en:
44
44
  delimiter: ","
45
45
  # Number of decimals, behind the separator (the number 1 with a precision of 2 gives: 1.00)
46
46
  precision: 3
47
+ # Determine how rounding is performed (see BigDecimal::mode)
48
+ round_mode: default
47
49
  # If set to true, precision will mean the number of significant digits instead
48
50
  # of the number of decimal digits (1234 with precision 2 becomes 1200, 1.23543 becomes 1.2)
49
51
  significant: false
50
- # If set, the zeros after the decimal separator will always be stripped (eg.: 1.200 will be 1.2)
52
+ # If set, the zeros after the decimal separator will always be stripped (e.g.: 1.200 will be 1.2)
51
53
  strip_insignificant_zeros: false
52
54
 
53
55
  # Used in NumberHelper.number_to_currency()
54
56
  currency:
55
57
  format:
56
- # Where is the currency sign? %u is the currency unit, %n the number (default: $5.00)
58
+ # Where is the currency sign? %u is the currency unit, %n is the number (default: $5.00)
57
59
  format: "%u%n"
58
60
  unit: "$"
59
- # These five are to override number.format and are optional
61
+ # These six are to override number.format and are optional
60
62
  separator: "."
61
63
  delimiter: ","
62
64
  precision: 2
65
+ # round_mode:
63
66
  significant: false
64
67
  strip_insignificant_zeros: false
65
68
 
@@ -87,10 +90,11 @@ en:
87
90
  # Used in NumberHelper.number_to_human_size() and NumberHelper.number_to_human()
88
91
  human:
89
92
  format:
90
- # These five are to override number.format and are optional
93
+ # These six are to override number.format and are optional
91
94
  # separator:
92
95
  delimiter: ""
93
96
  precision: 3
97
+ # round_mode:
94
98
  significant: true
95
99
  strip_insignificant_zeros: true
96
100
  # Used in number_to_human_size()
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/log_subscriber"
2
4
  require "active_support/logger"
3
5
  require "active_support/notifications"
@@ -25,13 +27,13 @@ module ActiveSupport
25
27
  #
26
28
  # All you need to do is to ensure that your log subscriber is added to
27
29
  # Rails::Subscriber, as in the second line of the code above. The test
28
- # helpers are responsible for setting up the queue, subscriptions and
30
+ # helpers are responsible for setting up the queue and subscriptions, and
29
31
  # turning colors in logs off.
30
32
  #
31
33
  # The messages are available in the @logger instance, which is a logger with
32
34
  # limited powers (it actually does not send anything to your output), and
33
35
  # you can collect them doing @logger.logged(level), where level is the level
34
- # used in logging, like info, debug, warn and so on.
36
+ # used in logging, like info, debug, warn, and so on.
35
37
  module TestHelper
36
38
  def setup # :nodoc:
37
39
  @logger = MockLogger.new
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/module/attribute_accessors"
2
4
  require "active_support/core_ext/class/attribute"
3
5
  require "active_support/subscriber"
4
6
 
5
7
  module ActiveSupport
6
- # ActiveSupport::LogSubscriber is an object set to consume
8
+ # <tt>ActiveSupport::LogSubscriber</tt> is an object set to consume
7
9
  # ActiveSupport::Notifications with the sole purpose of logging them.
8
10
  # The log subscriber dispatches notifications to a registered object based
9
11
  # on its given namespace.
@@ -14,7 +16,7 @@ module ActiveSupport
14
16
  # module ActiveRecord
15
17
  # class LogSubscriber < ActiveSupport::LogSubscriber
16
18
  # def sql(event)
17
- # "#{event.payload[:name]} (#{event.duration}) #{event.payload[:sql]}"
19
+ # info "#{event.payload[:name]} (#{event.duration}) #{event.payload[:sql]}"
18
20
  # end
19
21
  # end
20
22
  # end
@@ -27,13 +29,39 @@ module ActiveSupport
27
29
  # subscriber, the line above should be called after your
28
30
  # <tt>ActiveRecord::LogSubscriber</tt> definition.
29
31
  #
30
- # After configured, whenever a "sql.active_record" notification is published,
31
- # it will properly dispatch the event (ActiveSupport::Notifications::Event) to
32
- # the sql method.
32
+ # A logger also needs to be set with <tt>ActiveRecord::LogSubscriber.logger=</tt>.
33
+ # This is assigned automatically in a Rails environment.
34
+ #
35
+ # After configured, whenever a <tt>"sql.active_record"</tt> notification is published,
36
+ # it will properly dispatch the event
37
+ # (<tt>ActiveSupport::Notifications::Event</tt>) to the sql method.
38
+ #
39
+ # Being an ActiveSupport::Notifications consumer,
40
+ # <tt>ActiveSupport::LogSubscriber</tt> exposes a simple interface to check if
41
+ # instrumented code raises an exception. It is common to log a different
42
+ # message in case of an error, and this can be achieved by extending
43
+ # the previous example:
44
+ #
45
+ # module ActiveRecord
46
+ # class LogSubscriber < ActiveSupport::LogSubscriber
47
+ # def sql(event)
48
+ # exception = event.payload[:exception]
49
+ #
50
+ # if exception
51
+ # exception_object = event.payload[:exception_object]
52
+ #
53
+ # error "[ERROR] #{event.payload[:name]}: #{exception.join(', ')} " \
54
+ # "(#{exception_object.backtrace.first})"
55
+ # else
56
+ # # standard logger code
57
+ # end
58
+ # end
59
+ # end
60
+ # end
33
61
  #
34
62
  # Log subscriber also has some helpers to deal with logging and automatically
35
- # flushes all logs when the request finishes (via action_dispatch.callback
36
- # notification) in a Rails environment.
63
+ # flushes all logs when the request finishes
64
+ # (via <tt>action_dispatch.callback</tt> notification) in a Rails environment.
37
65
  class LogSubscriber < Subscriber
38
66
  # Embed in a String to clear all previous ANSI sequences.
39
67
  CLEAR = "\e[0m"
@@ -49,8 +77,7 @@ module ActiveSupport
49
77
  CYAN = "\e[36m"
50
78
  WHITE = "\e[37m"
51
79
 
52
- mattr_accessor :colorize_logging
53
- self.colorize_logging = true
80
+ mattr_accessor :colorize_logging, default: true
54
81
 
55
82
  class << self
56
83
  def logger
@@ -69,6 +96,11 @@ module ActiveSupport
69
96
  def flush_all!
70
97
  logger.flush if logger.respond_to?(:flush)
71
98
  end
99
+
100
+ private
101
+ def fetch_public_methods(subscriber, inherit_all)
102
+ subscriber.public_methods(inherit_all) - LogSubscriber.public_instance_methods(true)
103
+ end
72
104
  end
73
105
 
74
106
  def logger
@@ -82,13 +114,16 @@ module ActiveSupport
82
114
  def finish(name, id, payload)
83
115
  super if logger
84
116
  rescue => e
85
- if logger
86
- logger.error "Could not log #{name.inspect} event. #{e.class}: #{e.message} #{e.backtrace}"
87
- end
117
+ log_exception(name, e)
88
118
  end
89
119
 
90
- private
120
+ def publish_event(event)
121
+ super if logger
122
+ rescue => e
123
+ log_exception(event.name, e)
124
+ end
91
125
 
126
+ private
92
127
  %w(info debug warn error fatal unknown).each do |level|
93
128
  class_eval <<-METHOD, __FILE__, __LINE__ + 1
94
129
  def #{level}(progname = nil, &block)
@@ -107,5 +142,11 @@ module ActiveSupport
107
142
  bold = bold ? BOLD : ""
108
143
  "#{bold}#{color}#{text}#{CLEAR}"
109
144
  end
145
+
146
+ def log_exception(name, e)
147
+ if logger
148
+ logger.error "Could not log #{name.inspect} event. #{e.class}: #{e.message} #{e.backtrace}"
149
+ end
150
+ end
110
151
  end
111
152
  end
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/logger_silence"
2
4
  require "active_support/logger_thread_safe_level"
3
5
  require "logger"
4
6
 
5
7
  module ActiveSupport
6
8
  class Logger < ::Logger
7
- include ActiveSupport::LoggerThreadSafeLevel
8
9
  include LoggerSilence
9
10
 
10
11
  # Returns true if the logger destination matches one of the sources
@@ -13,7 +14,7 @@ module ActiveSupport
13
14
  # ActiveSupport::Logger.logger_outputs_to?(logger, STDOUT)
14
15
  # # => true
15
16
  def self.logger_outputs_to?(logger, *sources)
16
- logdev = logger.instance_variable_get("@logdev")
17
+ logdev = logger.instance_variable_get(:@logdev)
17
18
  logger_source = logdev.dev if logdev.respond_to?(:dev)
18
19
  sources.any? { |source| source == logger_source }
19
20
  end
@@ -76,23 +77,9 @@ module ActiveSupport
76
77
  end
77
78
  end
78
79
 
79
- def initialize(*args)
80
+ def initialize(*args, **kwargs)
80
81
  super
81
82
  @formatter = SimpleFormatter.new
82
- after_initialize if respond_to? :after_initialize
83
- end
84
-
85
- def add(severity, message = nil, progname = nil, &block)
86
- return true if @logdev.nil? || (severity || UNKNOWN) < level
87
- super
88
- end
89
-
90
- Logger::Severity.constants.each do |severity|
91
- class_eval(<<-EOT, __FILE__, __LINE__ + 1)
92
- def #{severity.downcase}? # def debug?
93
- Logger::#{severity} >= level # DEBUG >= level
94
- end # end
95
- EOT
96
83
  end
97
84
 
98
85
  # Simple formatter which only displays the message.
@@ -1,28 +1,21 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/concern"
2
4
  require "active_support/core_ext/module/attribute_accessors"
3
- require "concurrent"
4
-
5
- module LoggerSilence
6
- extend ActiveSupport::Concern
5
+ require "active_support/logger_thread_safe_level"
7
6
 
8
- included do
9
- cattr_accessor :silencer
10
- self.silencer = true
11
- end
7
+ module ActiveSupport
8
+ module LoggerSilence
9
+ extend ActiveSupport::Concern
12
10
 
13
- # Silences the logger for the duration of the block.
14
- def silence(temporary_level = Logger::ERROR)
15
- if silencer
16
- begin
17
- old_local_level = local_level
18
- self.local_level = temporary_level
11
+ included do
12
+ cattr_accessor :silencer, default: true
13
+ include ActiveSupport::LoggerThreadSafeLevel
14
+ end
19
15
 
20
- yield self
21
- ensure
22
- self.local_level = old_local_level
23
- end
24
- else
25
- yield self
16
+ # Silences the logger for the duration of the block.
17
+ def silence(severity = Logger::ERROR)
18
+ silencer ? log_at(severity) { yield self } : yield(self)
26
19
  end
27
20
  end
28
21
  end
@@ -1,31 +1,69 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/concern"
4
+ require "active_support/core_ext/module/attribute_accessors"
5
+ require "concurrent"
6
+ require "fiber"
2
7
 
3
8
  module ActiveSupport
4
9
  module LoggerThreadSafeLevel # :nodoc:
5
10
  extend ActiveSupport::Concern
6
11
 
7
- def after_initialize
8
- @local_levels = Concurrent::Map.new(initial_capacity: 2)
9
- end
10
-
11
- def local_log_id
12
- Thread.current.__id__
12
+ Logger::Severity.constants.each do |severity|
13
+ class_eval(<<-EOT, __FILE__, __LINE__ + 1)
14
+ def #{severity.downcase}? # def debug?
15
+ Logger::#{severity} >= level # DEBUG >= level
16
+ end # end
17
+ EOT
13
18
  end
14
19
 
15
20
  def local_level
16
- @local_levels[local_log_id]
21
+ IsolatedExecutionState[:logger_thread_safe_level]
17
22
  end
18
23
 
19
24
  def local_level=(level)
20
- if level
21
- @local_levels[local_log_id] = level
25
+ case level
26
+ when Integer
27
+ when Symbol
28
+ level = Logger::Severity.const_get(level.to_s.upcase)
29
+ when nil
22
30
  else
23
- @local_levels.delete(local_log_id)
31
+ raise ArgumentError, "Invalid log level: #{level.inspect}"
24
32
  end
33
+ IsolatedExecutionState[:logger_thread_safe_level] = level
25
34
  end
26
35
 
27
36
  def level
28
37
  local_level || super
29
38
  end
39
+
40
+ # Change the thread-local level for the duration of the given block.
41
+ def log_at(level)
42
+ old_local_level, self.local_level = local_level, level
43
+ yield
44
+ ensure
45
+ self.local_level = old_local_level
46
+ end
47
+
48
+ # Redefined to check severity against #level, and thus the thread-local level, rather than +@level+.
49
+ # FIXME: Remove when the minimum Ruby version supports overriding Logger#level.
50
+ def add(severity, message = nil, progname = nil, &block) # :nodoc:
51
+ severity ||= UNKNOWN
52
+ progname ||= @progname
53
+
54
+ return true if @logdev.nil? || severity < level
55
+
56
+ if message.nil?
57
+ if block_given?
58
+ message = yield
59
+ else
60
+ message = progname
61
+ progname = @progname
62
+ end
63
+ end
64
+
65
+ @logdev.write \
66
+ format_message(format_severity(severity), Time.now, progname, message)
67
+ end
30
68
  end
31
69
  end