activesupport 6.0.6.1 → 7.1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (245) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +865 -438
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +6 -6
  5. data/lib/active_support/actionable_error.rb +4 -2
  6. data/lib/active_support/array_inquirer.rb +4 -2
  7. data/lib/active_support/backtrace_cleaner.rb +30 -10
  8. data/lib/active_support/benchmarkable.rb +4 -3
  9. data/lib/active_support/broadcast_logger.rb +250 -0
  10. data/lib/active_support/builder.rb +1 -1
  11. data/lib/active_support/cache/coder.rb +153 -0
  12. data/lib/active_support/cache/entry.rb +134 -0
  13. data/lib/active_support/cache/file_store.rb +53 -20
  14. data/lib/active_support/cache/mem_cache_store.rb +208 -63
  15. data/lib/active_support/cache/memory_store.rb +120 -38
  16. data/lib/active_support/cache/null_store.rb +16 -2
  17. data/lib/active_support/cache/redis_cache_store.rb +201 -208
  18. data/lib/active_support/cache/serializer_with_fallback.rb +175 -0
  19. data/lib/active_support/cache/strategy/local_cache.rb +73 -66
  20. data/lib/active_support/cache.rb +539 -261
  21. data/lib/active_support/callbacks.rb +273 -142
  22. data/lib/active_support/code_generator.rb +65 -0
  23. data/lib/active_support/concern.rb +53 -7
  24. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +44 -7
  25. data/lib/active_support/concurrency/null_lock.rb +13 -0
  26. data/lib/active_support/concurrency/share_lock.rb +2 -2
  27. data/lib/active_support/configurable.rb +19 -6
  28. data/lib/active_support/configuration_file.rb +51 -0
  29. data/lib/active_support/core_ext/array/access.rb +1 -5
  30. data/lib/active_support/core_ext/array/conversions.rb +15 -13
  31. data/lib/active_support/core_ext/array/grouping.rb +6 -6
  32. data/lib/active_support/core_ext/array/inquiry.rb +2 -2
  33. data/lib/active_support/core_ext/benchmark.rb +2 -2
  34. data/lib/active_support/core_ext/big_decimal/conversions.rb +1 -1
  35. data/lib/active_support/core_ext/class/attribute.rb +34 -44
  36. data/lib/active_support/core_ext/class/subclasses.rb +19 -29
  37. data/lib/active_support/core_ext/date/blank.rb +1 -1
  38. data/lib/active_support/core_ext/date/calculations.rb +24 -9
  39. data/lib/active_support/core_ext/date/conversions.rb +18 -16
  40. data/lib/active_support/core_ext/date_and_time/calculations.rb +27 -4
  41. data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
  42. data/lib/active_support/core_ext/date_time/blank.rb +1 -1
  43. data/lib/active_support/core_ext/date_time/calculations.rb +4 -0
  44. data/lib/active_support/core_ext/date_time/conversions.rb +19 -15
  45. data/lib/active_support/core_ext/digest/uuid.rb +30 -13
  46. data/lib/active_support/core_ext/enumerable.rb +146 -72
  47. data/lib/active_support/core_ext/erb/util.rb +196 -0
  48. data/lib/active_support/core_ext/file/atomic.rb +3 -1
  49. data/lib/active_support/core_ext/hash/conversions.rb +3 -4
  50. data/lib/active_support/core_ext/hash/deep_merge.rb +22 -14
  51. data/lib/active_support/core_ext/hash/deep_transform_values.rb +4 -4
  52. data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -3
  53. data/lib/active_support/core_ext/hash/keys.rb +5 -5
  54. data/lib/active_support/core_ext/hash/slice.rb +3 -2
  55. data/lib/active_support/core_ext/integer/inflections.rb +12 -12
  56. data/lib/active_support/core_ext/kernel/reporting.rb +4 -4
  57. data/lib/active_support/core_ext/kernel/singleton_class.rb +1 -1
  58. data/lib/active_support/core_ext/load_error.rb +1 -1
  59. data/lib/active_support/core_ext/module/attr_internal.rb +2 -2
  60. data/lib/active_support/core_ext/module/attribute_accessors.rb +31 -29
  61. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +51 -20
  62. data/lib/active_support/core_ext/module/concerning.rb +14 -8
  63. data/lib/active_support/core_ext/module/delegation.rb +75 -42
  64. data/lib/active_support/core_ext/module/deprecation.rb +15 -12
  65. data/lib/active_support/core_ext/module/introspection.rb +1 -26
  66. data/lib/active_support/core_ext/name_error.rb +23 -2
  67. data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
  68. data/lib/active_support/core_ext/numeric/conversions.rb +82 -73
  69. data/lib/active_support/core_ext/object/acts_like.rb +29 -5
  70. data/lib/active_support/core_ext/object/blank.rb +2 -2
  71. data/lib/active_support/core_ext/object/deep_dup.rb +17 -1
  72. data/lib/active_support/core_ext/object/duplicable.rb +15 -4
  73. data/lib/active_support/core_ext/object/inclusion.rb +13 -5
  74. data/lib/active_support/core_ext/object/instance_variables.rb +22 -12
  75. data/lib/active_support/core_ext/object/json.rb +52 -28
  76. data/lib/active_support/core_ext/object/to_query.rb +2 -4
  77. data/lib/active_support/core_ext/object/try.rb +20 -20
  78. data/lib/active_support/core_ext/object/with.rb +44 -0
  79. data/lib/active_support/core_ext/object/with_options.rb +25 -6
  80. data/lib/active_support/core_ext/object.rb +1 -0
  81. data/lib/active_support/core_ext/pathname/blank.rb +16 -0
  82. data/lib/active_support/core_ext/pathname/existence.rb +23 -0
  83. data/lib/active_support/core_ext/pathname.rb +4 -0
  84. data/lib/active_support/core_ext/range/compare_range.rb +6 -25
  85. data/lib/active_support/core_ext/range/conversions.rb +34 -13
  86. data/lib/active_support/core_ext/range/each.rb +1 -1
  87. data/lib/active_support/core_ext/range/overlap.rb +40 -0
  88. data/lib/active_support/core_ext/range.rb +1 -2
  89. data/lib/active_support/core_ext/regexp.rb +8 -1
  90. data/lib/active_support/core_ext/securerandom.rb +25 -13
  91. data/lib/active_support/core_ext/string/access.rb +5 -24
  92. data/lib/active_support/core_ext/string/conversions.rb +3 -2
  93. data/lib/active_support/core_ext/string/filters.rb +21 -15
  94. data/lib/active_support/core_ext/string/indent.rb +1 -1
  95. data/lib/active_support/core_ext/string/inflections.rb +51 -10
  96. data/lib/active_support/core_ext/string/inquiry.rb +2 -1
  97. data/lib/active_support/core_ext/string/multibyte.rb +2 -2
  98. data/lib/active_support/core_ext/string/output_safety.rb +85 -194
  99. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -2
  100. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +6 -0
  101. data/lib/active_support/core_ext/symbol.rb +3 -0
  102. data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
  103. data/lib/active_support/core_ext/time/calculations.rb +46 -8
  104. data/lib/active_support/core_ext/time/conversions.rb +16 -13
  105. data/lib/active_support/core_ext/time/zones.rb +12 -28
  106. data/lib/active_support/core_ext.rb +2 -1
  107. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  108. data/lib/active_support/current_attributes.rb +54 -22
  109. data/lib/active_support/deep_mergeable.rb +53 -0
  110. data/lib/active_support/dependencies/autoload.rb +17 -12
  111. data/lib/active_support/dependencies/interlock.rb +10 -18
  112. data/lib/active_support/dependencies/require_dependency.rb +28 -0
  113. data/lib/active_support/dependencies.rb +58 -769
  114. data/lib/active_support/deprecation/behaviors.rb +77 -38
  115. data/lib/active_support/deprecation/constant_accessor.rb +5 -4
  116. data/lib/active_support/deprecation/deprecators.rb +104 -0
  117. data/lib/active_support/deprecation/disallowed.rb +54 -0
  118. data/lib/active_support/deprecation/instance_delegator.rb +31 -5
  119. data/lib/active_support/deprecation/method_wrappers.rb +12 -28
  120. data/lib/active_support/deprecation/proxy_wrappers.rb +40 -25
  121. data/lib/active_support/deprecation/reporting.rb +76 -16
  122. data/lib/active_support/deprecation.rb +36 -4
  123. data/lib/active_support/deprecator.rb +7 -0
  124. data/lib/active_support/descendants_tracker.rb +150 -68
  125. data/lib/active_support/digest.rb +5 -3
  126. data/lib/active_support/duration/iso8601_parser.rb +3 -3
  127. data/lib/active_support/duration/iso8601_serializer.rb +24 -12
  128. data/lib/active_support/duration.rb +136 -56
  129. data/lib/active_support/encrypted_configuration.rb +72 -9
  130. data/lib/active_support/encrypted_file.rb +46 -13
  131. data/lib/active_support/environment_inquirer.rb +40 -0
  132. data/lib/active_support/error_reporter/test_helper.rb +15 -0
  133. data/lib/active_support/error_reporter.rb +203 -0
  134. data/lib/active_support/evented_file_update_checker.rb +86 -137
  135. data/lib/active_support/execution_context/test_helper.rb +13 -0
  136. data/lib/active_support/execution_context.rb +53 -0
  137. data/lib/active_support/execution_wrapper.rb +31 -12
  138. data/lib/active_support/executor/test_helper.rb +7 -0
  139. data/lib/active_support/file_update_checker.rb +4 -2
  140. data/lib/active_support/fork_tracker.rb +79 -0
  141. data/lib/active_support/gem_version.rb +5 -5
  142. data/lib/active_support/gzip.rb +2 -0
  143. data/lib/active_support/hash_with_indifferent_access.rb +86 -42
  144. data/lib/active_support/html_safe_translation.rb +53 -0
  145. data/lib/active_support/i18n.rb +2 -1
  146. data/lib/active_support/i18n_railtie.rb +29 -27
  147. data/lib/active_support/inflector/inflections.rb +26 -9
  148. data/lib/active_support/inflector/methods.rb +54 -64
  149. data/lib/active_support/inflector/transliterate.rb +7 -5
  150. data/lib/active_support/isolated_execution_state.rb +76 -0
  151. data/lib/active_support/json/decoding.rb +6 -5
  152. data/lib/active_support/json/encoding.rb +31 -45
  153. data/lib/active_support/key_generator.rb +32 -7
  154. data/lib/active_support/lazy_load_hooks.rb +33 -7
  155. data/lib/active_support/locale/en.yml +10 -4
  156. data/lib/active_support/log_subscriber/test_helper.rb +2 -2
  157. data/lib/active_support/log_subscriber.rb +101 -32
  158. data/lib/active_support/logger.rb +9 -60
  159. data/lib/active_support/logger_silence.rb +2 -26
  160. data/lib/active_support/logger_thread_safe_level.rb +24 -25
  161. data/lib/active_support/message_encryptor.rb +205 -58
  162. data/lib/active_support/message_encryptors.rb +141 -0
  163. data/lib/active_support/message_pack/cache_serializer.rb +23 -0
  164. data/lib/active_support/message_pack/extensions.rb +292 -0
  165. data/lib/active_support/message_pack/serializer.rb +63 -0
  166. data/lib/active_support/message_pack.rb +50 -0
  167. data/lib/active_support/message_verifier.rb +237 -86
  168. data/lib/active_support/message_verifiers.rb +135 -0
  169. data/lib/active_support/messages/codec.rb +65 -0
  170. data/lib/active_support/messages/metadata.rb +112 -46
  171. data/lib/active_support/messages/rotation_configuration.rb +2 -1
  172. data/lib/active_support/messages/rotation_coordinator.rb +93 -0
  173. data/lib/active_support/messages/rotator.rb +35 -32
  174. data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
  175. data/lib/active_support/multibyte/chars.rb +15 -52
  176. data/lib/active_support/multibyte/unicode.rb +8 -122
  177. data/lib/active_support/multibyte.rb +1 -1
  178. data/lib/active_support/notifications/fanout.rb +310 -105
  179. data/lib/active_support/notifications/instrumenter.rb +113 -48
  180. data/lib/active_support/notifications.rb +56 -29
  181. data/lib/active_support/number_helper/number_converter.rb +15 -8
  182. data/lib/active_support/number_helper/number_to_currency_converter.rb +11 -6
  183. data/lib/active_support/number_helper/number_to_delimited_converter.rb +1 -1
  184. data/lib/active_support/number_helper/number_to_human_converter.rb +1 -1
  185. data/lib/active_support/number_helper/number_to_human_size_converter.rb +5 -5
  186. data/lib/active_support/number_helper/number_to_phone_converter.rb +2 -1
  187. data/lib/active_support/number_helper/number_to_rounded_converter.rb +9 -5
  188. data/lib/active_support/number_helper/rounding_helper.rb +12 -32
  189. data/lib/active_support/number_helper.rb +379 -304
  190. data/lib/active_support/option_merger.rb +11 -18
  191. data/lib/active_support/ordered_hash.rb +4 -4
  192. data/lib/active_support/ordered_options.rb +23 -3
  193. data/lib/active_support/parameter_filter.rb +104 -75
  194. data/lib/active_support/proxy_object.rb +2 -0
  195. data/lib/active_support/rails.rb +1 -4
  196. data/lib/active_support/railtie.rb +90 -6
  197. data/lib/active_support/reloader.rb +12 -4
  198. data/lib/active_support/rescuable.rb +18 -16
  199. data/lib/active_support/ruby_features.rb +7 -0
  200. data/lib/active_support/secure_compare_rotator.rb +58 -0
  201. data/lib/active_support/security_utils.rb +19 -12
  202. data/lib/active_support/string_inquirer.rb +5 -3
  203. data/lib/active_support/subscriber.rb +23 -47
  204. data/lib/active_support/syntax_error_proxy.rb +70 -0
  205. data/lib/active_support/tagged_logging.rb +84 -23
  206. data/lib/active_support/test_case.rb +166 -27
  207. data/lib/active_support/testing/assertions.rb +73 -20
  208. data/lib/active_support/testing/autorun.rb +0 -2
  209. data/lib/active_support/testing/constant_stubbing.rb +32 -0
  210. data/lib/active_support/testing/deprecation.rb +53 -2
  211. data/lib/active_support/testing/error_reporter_assertions.rb +107 -0
  212. data/lib/active_support/testing/isolation.rb +30 -29
  213. data/lib/active_support/testing/method_call_assertions.rb +24 -11
  214. data/lib/active_support/testing/parallelization/server.rb +82 -0
  215. data/lib/active_support/testing/parallelization/worker.rb +103 -0
  216. data/lib/active_support/testing/parallelization.rb +16 -95
  217. data/lib/active_support/testing/parallelize_executor.rb +81 -0
  218. data/lib/active_support/testing/stream.rb +4 -6
  219. data/lib/active_support/testing/strict_warnings.rb +39 -0
  220. data/lib/active_support/testing/tagged_logging.rb +1 -1
  221. data/lib/active_support/testing/time_helpers.rb +89 -19
  222. data/lib/active_support/time_with_zone.rb +105 -70
  223. data/lib/active_support/values/time_zone.rb +59 -26
  224. data/lib/active_support/version.rb +1 -1
  225. data/lib/active_support/xml_mini/jdom.rb +4 -11
  226. data/lib/active_support/xml_mini/libxml.rb +5 -5
  227. data/lib/active_support/xml_mini/libxmlsax.rb +1 -1
  228. data/lib/active_support/xml_mini/nokogiri.rb +5 -5
  229. data/lib/active_support/xml_mini/nokogirisax.rb +2 -2
  230. data/lib/active_support/xml_mini/rexml.rb +9 -2
  231. data/lib/active_support/xml_mini.rb +7 -6
  232. data/lib/active_support.rb +40 -1
  233. metadata +127 -40
  234. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -5
  235. data/lib/active_support/core_ext/hash/compact.rb +0 -5
  236. data/lib/active_support/core_ext/hash/transform_values.rb +0 -5
  237. data/lib/active_support/core_ext/marshal.rb +0 -24
  238. data/lib/active_support/core_ext/module/reachable.rb +0 -6
  239. data/lib/active_support/core_ext/numeric/inquiry.rb +0 -5
  240. data/lib/active_support/core_ext/range/include_range.rb +0 -9
  241. data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -23
  242. data/lib/active_support/core_ext/range/overlaps.rb +0 -10
  243. data/lib/active_support/core_ext/uri.rb +0 -25
  244. data/lib/active_support/dependencies/zeitwerk_integration.rb +0 -117
  245. data/lib/active_support/per_thread_registry.rb +0 -60
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2005-2019 David Heinemeier Hansson
1
+ Copyright (c) David Heinemeier Hansson
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.rdoc CHANGED
@@ -1,11 +1,11 @@
1
- = Active Support -- Utility classes and Ruby extensions from Rails
1
+ = Active Support -- Utility classes and Ruby extensions from \Rails
2
2
 
3
3
  Active Support is a collection of utility classes and standard library
4
- extensions that were found useful for the Rails framework. These additions
4
+ extensions that were found useful for the \Rails framework. These additions
5
5
  reside in this package so they can be loaded as needed in Ruby projects
6
- outside of Rails.
6
+ outside of \Rails.
7
7
 
8
- You can read more about the extensions in the {Active Support Core Extensions}[https://edgeguides.rubyonrails.org/active_support_core_extensions.html] guide.
8
+ You can read more about the extensions in the {Active Support Core Extensions}[https://guides.rubyonrails.org/active_support_core_extensions.html] guide.
9
9
 
10
10
  == Download and installation
11
11
 
@@ -13,7 +13,7 @@ The latest version of Active Support can be installed with RubyGems:
13
13
 
14
14
  $ gem install activesupport
15
15
 
16
- Source code can be downloaded as part of the Rails project on GitHub:
16
+ Source code can be downloaded as part of the \Rails project on GitHub:
17
17
 
18
18
  * https://github.com/rails/rails/tree/main/activesupport
19
19
 
@@ -31,7 +31,7 @@ API documentation is at:
31
31
 
32
32
  * https://api.rubyonrails.org
33
33
 
34
- Bug reports for the Ruby on Rails project can be filed here:
34
+ Bug reports for the Ruby on \Rails project can be filed here:
35
35
 
36
36
  * https://github.com/rails/rails/issues
37
37
 
@@ -1,9 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveSupport
4
- # Actionable errors let's you define actions to resolve an error.
4
+ # = Actionable Errors
5
5
  #
6
- # To make an error actionable, include the <tt>ActiveSupport::ActionableError</tt>
6
+ # Actionable errors lets you define actions to resolve an error.
7
+ #
8
+ # To make an error actionable, include the +ActiveSupport::ActionableError+
7
9
  # module and invoke the +action+ class macro to define the action. An action
8
10
  # needs a name and a block to execute.
9
11
  module ActionableError
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveSupport
4
+ # = \Array Inquirer
5
+ #
4
6
  # Wrapping an array in an +ArrayInquirer+ gives a friendlier way to check
5
7
  # its string-like contents:
6
8
  #
@@ -34,11 +36,11 @@ module ActiveSupport
34
36
 
35
37
  private
36
38
  def respond_to_missing?(name, include_private = false)
37
- (name[-1] == "?") || super
39
+ name.end_with?("?") || super
38
40
  end
39
41
 
40
42
  def method_missing(name, *args)
41
- if name[-1] == "?"
43
+ if name.end_with?("?")
42
44
  any?(name[0..-2])
43
45
  else
44
46
  super
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveSupport
4
+ # = Backtrace Cleaner
5
+ #
4
6
  # Backtraces often include many lines that are not relevant for the context
5
7
  # under review. This makes it hard to find the signal amongst the backtrace
6
8
  # noise, and adds debugging time. With a BacktraceCleaner, filters and
@@ -16,15 +18,15 @@ module ActiveSupport
16
18
  #
17
19
  # bc = ActiveSupport::BacktraceCleaner.new
18
20
  # bc.add_filter { |line| line.gsub(Rails.root.to_s, '') } # strip the Rails.root prefix
19
- # bc.add_silencer { |line| line =~ /puma|rubygems/ } # skip any lines from puma or rubygems
21
+ # bc.add_silencer { |line| /puma|rubygems/.match?(line) } # skip any lines from puma or rubygems
20
22
  # bc.clean(exception.backtrace) # perform the cleanup
21
23
  #
22
- # To reconfigure an existing BacktraceCleaner (like the default one in Rails)
24
+ # To reconfigure an existing BacktraceCleaner (like the default one in \Rails)
23
25
  # and show as much data as possible, you can always call
24
- # <tt>BacktraceCleaner#remove_silencers!</tt>, which will restore the
26
+ # BacktraceCleaner#remove_silencers!, which will restore the
25
27
  # backtrace to a pristine state. If you need to reconfigure an existing
26
28
  # BacktraceCleaner so that it does not filter or modify the paths of any lines
27
- # of the backtrace, you can call <tt>BacktraceCleaner#remove_filters!</tt>
29
+ # of the backtrace, you can call BacktraceCleaner#remove_filters!
28
30
  # These two methods will give you a completely untouched backtrace.
29
31
  #
30
32
  # Inspired by the Quiet Backtrace gem by thoughtbot.
@@ -52,11 +54,29 @@ module ActiveSupport
52
54
  end
53
55
  alias :filter :clean
54
56
 
57
+ # Returns the frame with all filters applied.
58
+ # returns +nil+ if the frame was silenced.
59
+ def clean_frame(frame, kind = :silent)
60
+ frame = frame.to_s
61
+ @filters.each do |f|
62
+ frame = f.call(frame.to_s)
63
+ end
64
+
65
+ case kind
66
+ when :silent
67
+ frame unless @silencers.any? { |s| s.call(frame) }
68
+ when :noise
69
+ frame if @silencers.any? { |s| s.call(frame) }
70
+ else
71
+ frame
72
+ end
73
+ end
74
+
55
75
  # Adds a filter from the block provided. Each line in the backtrace will be
56
76
  # mapped against this filter.
57
77
  #
58
78
  # # Will turn "/my/rails/root/app/models/person.rb" into "/app/models/person.rb"
59
- # backtrace_cleaner.add_filter { |line| line.gsub(Rails.root, '') }
79
+ # backtrace_cleaner.add_filter { |line| line.gsub(Rails.root.to_s, '') }
60
80
  def add_filter(&block)
61
81
  @filters << block
62
82
  end
@@ -65,7 +85,7 @@ module ActiveSupport
65
85
  # for a given line, it will be excluded from the clean backtrace.
66
86
  #
67
87
  # # Will reject all lines that include the word "puma", like "/gems/puma/server.rb" or "/app/my_puma_server/rb"
68
- # backtrace_cleaner.add_silencer { |line| line =~ /puma/ }
88
+ # backtrace_cleaner.add_silencer { |line| /puma/.match?(line) }
69
89
  def add_silencer(&block)
70
90
  @silencers << block
71
91
  end
@@ -91,7 +111,7 @@ module ActiveSupport
91
111
  gems_paths = (Gem.path | [Gem.default_dir]).map { |p| Regexp.escape(p) }
92
112
  return if gems_paths.empty?
93
113
 
94
- gems_regexp = %r{(#{gems_paths.join('|')})/(bundler/)?gems/([^/]+)-([\w.]+)/(.*)}
114
+ gems_regexp = %r{\A(#{gems_paths.join('|')})/(bundler/)?gems/([^/]+)-([\w.]+)/(.*)}
95
115
  gems_result = '\3 (\4) \5'
96
116
  add_filter { |line| line.sub(gems_regexp, gems_result) }
97
117
  end
@@ -106,7 +126,7 @@ module ActiveSupport
106
126
 
107
127
  def filter_backtrace(backtrace)
108
128
  @filters.each do |f|
109
- backtrace = backtrace.map { |line| f.call(line) }
129
+ backtrace = backtrace.map { |line| f.call(line.to_s) }
110
130
  end
111
131
 
112
132
  backtrace
@@ -114,7 +134,7 @@ module ActiveSupport
114
134
 
115
135
  def silence(backtrace)
116
136
  @silencers.each do |s|
117
- backtrace = backtrace.reject { |line| s.call(line) }
137
+ backtrace = backtrace.reject { |line| s.call(line.to_s) }
118
138
  end
119
139
 
120
140
  backtrace
@@ -123,7 +143,7 @@ module ActiveSupport
123
143
  def noise(backtrace)
124
144
  backtrace.select do |line|
125
145
  @silencers.any? do |s|
126
- s.call(line)
146
+ s.call(line.to_s)
127
147
  end
128
148
  end
129
149
  end
@@ -4,6 +4,7 @@ require "active_support/core_ext/benchmark"
4
4
  require "active_support/core_ext/hash/keys"
5
5
 
6
6
  module ActiveSupport
7
+ # = \Benchmarkable
7
8
  module Benchmarkable
8
9
  # Allows you to measure the execution time of a block in a template and
9
10
  # records the result to the log. Wrap this block around expensive operations
@@ -34,14 +35,14 @@ module ActiveSupport
34
35
  # <% benchmark 'Process data files', level: :info, silence: true do %>
35
36
  # <%= expensive_and_chatty_files_operation %>
36
37
  # <% end %>
37
- def benchmark(message = "Benchmarking", options = {})
38
+ def benchmark(message = "Benchmarking", options = {}, &block)
38
39
  if logger
39
40
  options.assert_valid_keys(:level, :silence)
40
41
  options[:level] ||= :info
41
42
 
42
43
  result = nil
43
- ms = Benchmark.ms { result = options[:silence] ? logger.silence { yield } : yield }
44
- logger.send(options[:level], "%s (%.1fms)" % [ message, ms ])
44
+ ms = Benchmark.ms { result = options[:silence] ? logger.silence(&block) : yield }
45
+ logger.public_send(options[:level], "%s (%.1fms)" % [ message, ms ])
45
46
  result
46
47
  else
47
48
  yield
@@ -0,0 +1,250 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ # = Active Support Broadcast Logger
5
+ #
6
+ # The Broadcast logger is a logger used to write messages to multiple IO. It is commonly used
7
+ # in development to display messages on STDOUT and also write them to a file (development.log).
8
+ # With the Broadcast logger, you can broadcast your logs to a unlimited number of sinks.
9
+ #
10
+ # The BroadcastLogger acts as a standard logger and all methods you are used to are available.
11
+ # However, all the methods on this logger will propagate and be delegated to the other loggers
12
+ # that are part of the broadcast.
13
+ #
14
+ # Broadcasting your logs.
15
+ #
16
+ # stdout_logger = Logger.new(STDOUT)
17
+ # file_logger = Logger.new("development.log")
18
+ # broadcast = BroadcastLogger.new(stdout_logger, file_logger)
19
+ #
20
+ # broadcast.info("Hello world!") # Writes the log to STDOUT and the development.log file.
21
+ #
22
+ # Add a logger to the broadcast.
23
+ #
24
+ # stdout_logger = Logger.new(STDOUT)
25
+ # broadcast = BroadcastLogger.new(stdout_logger)
26
+ # file_logger = Logger.new("development.log")
27
+ # broadcast.broadcast_to(file_logger)
28
+ #
29
+ # broadcast.info("Hello world!") # Writes the log to STDOUT and the development.log file.
30
+ #
31
+ # Modifying the log level for all broadcasted loggers.
32
+ #
33
+ # stdout_logger = Logger.new(STDOUT)
34
+ # file_logger = Logger.new("development.log")
35
+ # broadcast = BroadcastLogger.new(stdout_logger, file_logger)
36
+ #
37
+ # broadcast.level = Logger::FATAL # Modify the log level for the whole broadcast.
38
+ #
39
+ # Stop broadcasting log to a sink.
40
+ #
41
+ # stdout_logger = Logger.new(STDOUT)
42
+ # file_logger = Logger.new("development.log")
43
+ # broadcast = BroadcastLogger.new(stdout_logger, file_logger)
44
+ # broadcast.info("Hello world!") # Writes the log to STDOUT and the development.log file.
45
+ #
46
+ # broadcast.stop_broadcasting_to(file_logger)
47
+ # broadcast.info("Hello world!") # Writes the log *only* to STDOUT.
48
+ #
49
+ # At least one sink has to be part of the broadcast. Otherwise, your logs will not
50
+ # be written anywhere. For instance:
51
+ #
52
+ # broadcast = BroadcastLogger.new
53
+ # broadcast.info("Hello world") # The log message will appear nowhere.
54
+ #
55
+ # If you are adding a custom logger with custom methods to the broadcast,
56
+ # the `BroadcastLogger` will proxy them and return the raw value, or an array
57
+ # of raw values, depending on how many loggers in the broadcasts responded to
58
+ # the method:
59
+ #
60
+ # class MyLogger < ::Logger
61
+ # def loggable?
62
+ # true
63
+ # end
64
+ # end
65
+ #
66
+ # logger = BroadcastLogger.new
67
+ # logger.loggable? # => A NoMethodError exception is raised because no loggers in the broadcasts could respond.
68
+ #
69
+ # logger.broadcast_to(MyLogger.new(STDOUT))
70
+ # logger.loggable? # => true
71
+ # logger.broadcast_to(MyLogger.new(STDOUT))
72
+ # puts logger.broadcasts # => [MyLogger, MyLogger]
73
+ # logger.loggable? # [true, true]
74
+ class BroadcastLogger
75
+ include ActiveSupport::LoggerSilence
76
+
77
+ # Returns all the logger that are part of this broadcast.
78
+ attr_reader :broadcasts
79
+ attr_reader :formatter
80
+ attr_accessor :progname
81
+
82
+ def initialize(*loggers)
83
+ @broadcasts = []
84
+ @progname = "Broadcast"
85
+
86
+ broadcast_to(*loggers)
87
+ end
88
+
89
+ # Add logger(s) to the broadcast.
90
+ #
91
+ # broadcast_logger = ActiveSupport::BroadcastLogger.new
92
+ # broadcast_logger.broadcast_to(Logger.new(STDOUT), Logger.new(STDERR))
93
+ def broadcast_to(*loggers)
94
+ @broadcasts.concat(loggers)
95
+ end
96
+
97
+ # Remove a logger from the broadcast. When a logger is removed, messages sent to
98
+ # the broadcast will no longer be written to its sink.
99
+ #
100
+ # sink = Logger.new(STDOUT)
101
+ # broadcast_logger = ActiveSupport::BroadcastLogger.new
102
+ #
103
+ # broadcast_logger.stop_broadcasting_to(sink)
104
+ def stop_broadcasting_to(logger)
105
+ @broadcasts.delete(logger)
106
+ end
107
+
108
+ def level
109
+ @broadcasts.map(&:level).min
110
+ end
111
+
112
+ def <<(message)
113
+ dispatch { |logger| logger.<<(message) }
114
+ end
115
+
116
+ def add(*args, &block)
117
+ dispatch { |logger| logger.add(*args, &block) }
118
+ end
119
+ alias_method :log, :add
120
+
121
+ def debug(*args, &block)
122
+ dispatch { |logger| logger.debug(*args, &block) }
123
+ end
124
+
125
+ def info(*args, &block)
126
+ dispatch { |logger| logger.info(*args, &block) }
127
+ end
128
+
129
+ def warn(*args, &block)
130
+ dispatch { |logger| logger.warn(*args, &block) }
131
+ end
132
+
133
+ def error(*args, &block)
134
+ dispatch { |logger| logger.error(*args, &block) }
135
+ end
136
+
137
+ def fatal(*args, &block)
138
+ dispatch { |logger| logger.fatal(*args, &block) }
139
+ end
140
+
141
+ def unknown(*args, &block)
142
+ dispatch { |logger| logger.unknown(*args, &block) }
143
+ end
144
+
145
+ def formatter=(formatter)
146
+ dispatch { |logger| logger.formatter = formatter }
147
+
148
+ @formatter = formatter
149
+ end
150
+
151
+ def level=(level)
152
+ dispatch { |logger| logger.level = level }
153
+ end
154
+ alias_method :sev_threshold=, :level=
155
+
156
+ def local_level=(level)
157
+ dispatch do |logger|
158
+ logger.local_level = level if logger.respond_to?(:local_level=)
159
+ end
160
+ end
161
+
162
+ def close
163
+ dispatch { |logger| logger.close }
164
+ end
165
+
166
+ # +True+ if the log level allows entries with severity Logger::DEBUG to be written
167
+ # to at least one broadcast. +False+ otherwise.
168
+ def debug?
169
+ @broadcasts.any? { |logger| logger.debug? }
170
+ end
171
+
172
+ # Sets the log level to Logger::DEBUG for the whole broadcast.
173
+ def debug!
174
+ dispatch { |logger| logger.debug! }
175
+ end
176
+
177
+ # +True+ if the log level allows entries with severity Logger::INFO to be written
178
+ # to at least one broadcast. +False+ otherwise.
179
+ def info?
180
+ @broadcasts.any? { |logger| logger.info? }
181
+ end
182
+
183
+ # Sets the log level to Logger::INFO for the whole broadcast.
184
+ def info!
185
+ dispatch { |logger| logger.info! }
186
+ end
187
+
188
+ # +True+ if the log level allows entries with severity Logger::WARN to be written
189
+ # to at least one broadcast. +False+ otherwise.
190
+ def warn?
191
+ @broadcasts.any? { |logger| logger.warn? }
192
+ end
193
+
194
+ # Sets the log level to Logger::WARN for the whole broadcast.
195
+ def warn!
196
+ dispatch { |logger| logger.warn! }
197
+ end
198
+
199
+ # +True+ if the log level allows entries with severity Logger::ERROR to be written
200
+ # to at least one broadcast. +False+ otherwise.
201
+ def error?
202
+ @broadcasts.any? { |logger| logger.error? }
203
+ end
204
+
205
+ # Sets the log level to Logger::ERROR for the whole broadcast.
206
+ def error!
207
+ dispatch { |logger| logger.error! }
208
+ end
209
+
210
+ # +True+ if the log level allows entries with severity Logger::FATAL to be written
211
+ # to at least one broadcast. +False+ otherwise.
212
+ def fatal?
213
+ @broadcasts.any? { |logger| logger.fatal? }
214
+ end
215
+
216
+ # Sets the log level to Logger::FATAL for the whole broadcast.
217
+ def fatal!
218
+ dispatch { |logger| logger.fatal! }
219
+ end
220
+
221
+ def initialize_copy(other)
222
+ @broadcasts = []
223
+ @progname = other.progname.dup
224
+ @formatter = other.formatter.dup
225
+
226
+ broadcast_to(*other.broadcasts.map(&:dup))
227
+ end
228
+
229
+ private
230
+ def dispatch(&block)
231
+ @broadcasts.each { |logger| block.call(logger) }
232
+ end
233
+
234
+ def method_missing(name, *args, **kwargs, &block)
235
+ loggers = @broadcasts.select { |logger| logger.respond_to?(name) }
236
+
237
+ if loggers.none?
238
+ super(name, *args, **kwargs, &block)
239
+ elsif loggers.one?
240
+ loggers.first.send(name, *args, **kwargs, &block)
241
+ else
242
+ loggers.map { |logger| logger.send(name, *args, **kwargs, &block) }
243
+ end
244
+ end
245
+
246
+ def respond_to_missing?(method, include_all)
247
+ @broadcasts.any? { |logger| logger.respond_to?(method, include_all) }
248
+ end
249
+ end
250
+ end
@@ -3,6 +3,6 @@
3
3
  begin
4
4
  require "builder"
5
5
  rescue LoadError => e
6
- $stderr.puts "You don't have builder installed in your application. Please add it to your Gemfile and run bundle install"
6
+ warn "You don't have builder installed in your application. Please add it to your Gemfile and run bundle install"
7
7
  raise e
8
8
  end
@@ -0,0 +1,153 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "entry"
4
+
5
+ module ActiveSupport
6
+ module Cache
7
+ class Coder # :nodoc:
8
+ def initialize(serializer, compressor, legacy_serializer: false)
9
+ @serializer = serializer
10
+ @compressor = compressor
11
+ @legacy_serializer = legacy_serializer
12
+ end
13
+
14
+ def dump(entry)
15
+ return @serializer.dump(entry) if @legacy_serializer
16
+
17
+ dump_compressed(entry, Float::INFINITY)
18
+ end
19
+
20
+ def dump_compressed(entry, threshold)
21
+ return @serializer.dump_compressed(entry, threshold) if @legacy_serializer
22
+
23
+ # If value is a string with a supported encoding, use it as the payload
24
+ # instead of passing it through the serializer.
25
+ if type = type_for_string(entry.value)
26
+ payload = entry.value.b
27
+ else
28
+ type = OBJECT_DUMP_TYPE
29
+ payload = @serializer.dump(entry.value)
30
+ end
31
+
32
+ if compressed = try_compress(payload, threshold)
33
+ payload = compressed
34
+ type = type | COMPRESSED_FLAG
35
+ end
36
+
37
+ expires_at = entry.expires_at || -1.0
38
+
39
+ version = dump_version(entry.version) if entry.version
40
+ version_length = version&.bytesize || -1
41
+
42
+ packed = SIGNATURE.b
43
+ packed << [type, expires_at, version_length].pack(PACKED_TEMPLATE)
44
+ packed << version if version
45
+ packed << payload
46
+ end
47
+
48
+ def load(dumped)
49
+ return @serializer.load(dumped) if !signature?(dumped)
50
+
51
+ type = dumped.unpack1(PACKED_TYPE_TEMPLATE)
52
+ expires_at = dumped.unpack1(PACKED_EXPIRES_AT_TEMPLATE)
53
+ version_length = dumped.unpack1(PACKED_VERSION_LENGTH_TEMPLATE)
54
+
55
+ expires_at = nil if expires_at < 0
56
+ version = load_version(dumped.byteslice(PACKED_VERSION_INDEX, version_length)) if version_length >= 0
57
+ payload = dumped.byteslice((PACKED_VERSION_INDEX + [version_length, 0].max)..)
58
+
59
+ compressor = @compressor if type & COMPRESSED_FLAG > 0
60
+ serializer = STRING_DESERIALIZERS[type & ~COMPRESSED_FLAG] || @serializer
61
+
62
+ LazyEntry.new(serializer, compressor, payload, version: version, expires_at: expires_at)
63
+ end
64
+
65
+ private
66
+ SIGNATURE = "\x00\x11".b.freeze
67
+
68
+ OBJECT_DUMP_TYPE = 0x01
69
+
70
+ STRING_ENCODINGS = {
71
+ 0x02 => Encoding::UTF_8,
72
+ 0x03 => Encoding::BINARY,
73
+ 0x04 => Encoding::US_ASCII,
74
+ }
75
+
76
+ COMPRESSED_FLAG = 0x80
77
+
78
+ PACKED_TEMPLATE = "CEl<"
79
+ PACKED_TYPE_TEMPLATE = "@#{SIGNATURE.bytesize}C"
80
+ PACKED_EXPIRES_AT_TEMPLATE = "@#{[0].pack(PACKED_TYPE_TEMPLATE).bytesize}E"
81
+ PACKED_VERSION_LENGTH_TEMPLATE = "@#{[0].pack(PACKED_EXPIRES_AT_TEMPLATE).bytesize}l<"
82
+ PACKED_VERSION_INDEX = [0].pack(PACKED_VERSION_LENGTH_TEMPLATE).bytesize
83
+
84
+ MARSHAL_SIGNATURE = "\x04\x08".b.freeze
85
+
86
+ class StringDeserializer
87
+ def initialize(encoding)
88
+ @encoding = encoding
89
+ end
90
+
91
+ def load(payload)
92
+ payload.force_encoding(@encoding)
93
+ end
94
+ end
95
+
96
+ STRING_DESERIALIZERS = STRING_ENCODINGS.transform_values { |encoding| StringDeserializer.new(encoding) }
97
+
98
+ class LazyEntry < Cache::Entry
99
+ def initialize(serializer, compressor, payload, **options)
100
+ super(payload, **options)
101
+ @serializer = serializer
102
+ @compressor = compressor
103
+ @resolved = false
104
+ end
105
+
106
+ def value
107
+ if !@resolved
108
+ @value = @serializer.load(@compressor ? @compressor.inflate(@value) : @value)
109
+ @resolved = true
110
+ end
111
+ @value
112
+ end
113
+
114
+ def mismatched?(version)
115
+ super.tap { |mismatched| value if !mismatched }
116
+ rescue Cache::DeserializationError
117
+ true
118
+ end
119
+ end
120
+
121
+ def signature?(dumped)
122
+ dumped.is_a?(String) && dumped.start_with?(SIGNATURE)
123
+ end
124
+
125
+ def type_for_string(value)
126
+ STRING_ENCODINGS.key(value.encoding) if value.instance_of?(String)
127
+ end
128
+
129
+ def try_compress(string, threshold)
130
+ if @compressor && string.bytesize >= threshold
131
+ compressed = @compressor.deflate(string)
132
+ compressed if compressed.bytesize < string.bytesize
133
+ end
134
+ end
135
+
136
+ def dump_version(version)
137
+ if version.encoding != Encoding::UTF_8 || version.start_with?(MARSHAL_SIGNATURE)
138
+ Marshal.dump(version)
139
+ else
140
+ version.b
141
+ end
142
+ end
143
+
144
+ def load_version(dumped_version)
145
+ if dumped_version.start_with?(MARSHAL_SIGNATURE)
146
+ Marshal.load(dumped_version)
147
+ else
148
+ dumped_version.force_encoding(Encoding::UTF_8)
149
+ end
150
+ end
151
+ end
152
+ end
153
+ end