activesupport 7.0.0 → 7.2.2.1

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 (211) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +156 -255
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +6 -6
  5. data/lib/active_support/actionable_error.rb +3 -1
  6. data/lib/active_support/array_inquirer.rb +3 -1
  7. data/lib/active_support/backtrace_cleaner.rb +41 -9
  8. data/lib/active_support/benchmarkable.rb +1 -0
  9. data/lib/active_support/broadcast_logger.rb +251 -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 +49 -17
  14. data/lib/active_support/cache/mem_cache_store.rb +111 -129
  15. data/lib/active_support/cache/memory_store.rb +81 -26
  16. data/lib/active_support/cache/null_store.rb +6 -0
  17. data/lib/active_support/cache/redis_cache_store.rb +175 -154
  18. data/lib/active_support/cache/serializer_with_fallback.rb +152 -0
  19. data/lib/active_support/cache/strategy/local_cache.rb +31 -13
  20. data/lib/active_support/cache.rb +457 -377
  21. data/lib/active_support/callbacks.rb +123 -139
  22. data/lib/active_support/code_generator.rb +15 -10
  23. data/lib/active_support/concern.rb +4 -2
  24. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +42 -3
  25. data/lib/active_support/concurrency/null_lock.rb +13 -0
  26. data/lib/active_support/configurable.rb +12 -2
  27. data/lib/active_support/core_ext/array/conversions.rb +7 -9
  28. data/lib/active_support/core_ext/array/inquiry.rb +2 -2
  29. data/lib/active_support/core_ext/array.rb +0 -1
  30. data/lib/active_support/core_ext/class/subclasses.rb +4 -15
  31. data/lib/active_support/core_ext/date/blank.rb +4 -0
  32. data/lib/active_support/core_ext/date/calculations.rb +20 -5
  33. data/lib/active_support/core_ext/date/conversions.rb +15 -16
  34. data/lib/active_support/core_ext/date.rb +0 -1
  35. data/lib/active_support/core_ext/date_and_time/calculations.rb +14 -4
  36. data/lib/active_support/core_ext/date_and_time/compatibility.rb +29 -2
  37. data/lib/active_support/core_ext/date_time/blank.rb +4 -0
  38. data/lib/active_support/core_ext/date_time/calculations.rb +4 -0
  39. data/lib/active_support/core_ext/date_time/conversions.rb +15 -15
  40. data/lib/active_support/core_ext/date_time.rb +0 -1
  41. data/lib/active_support/core_ext/digest/uuid.rb +7 -10
  42. data/lib/active_support/core_ext/enumerable.rb +51 -101
  43. data/lib/active_support/core_ext/erb/util.rb +201 -0
  44. data/lib/active_support/core_ext/file/atomic.rb +2 -0
  45. data/lib/active_support/core_ext/hash/conversions.rb +1 -2
  46. data/lib/active_support/core_ext/hash/deep_merge.rb +22 -14
  47. data/lib/active_support/core_ext/hash/deep_transform_values.rb +3 -3
  48. data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -3
  49. data/lib/active_support/core_ext/hash/keys.rb +7 -7
  50. data/lib/active_support/core_ext/integer/inflections.rb +12 -12
  51. data/lib/active_support/core_ext/kernel/singleton_class.rb +1 -1
  52. data/lib/active_support/core_ext/module/attr_internal.rb +17 -6
  53. data/lib/active_support/core_ext/module/attribute_accessors.rb +6 -0
  54. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +38 -20
  55. data/lib/active_support/core_ext/module/concerning.rb +6 -6
  56. data/lib/active_support/core_ext/module/delegation.rb +20 -119
  57. data/lib/active_support/core_ext/module/deprecation.rb +12 -12
  58. data/lib/active_support/core_ext/module/introspection.rb +0 -1
  59. data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
  60. data/lib/active_support/core_ext/numeric/conversions.rb +77 -75
  61. data/lib/active_support/core_ext/numeric.rb +0 -1
  62. data/lib/active_support/core_ext/object/acts_like.rb +29 -5
  63. data/lib/active_support/core_ext/object/blank.rb +45 -1
  64. data/lib/active_support/core_ext/object/deep_dup.rb +16 -0
  65. data/lib/active_support/core_ext/object/duplicable.rb +25 -16
  66. data/lib/active_support/core_ext/object/inclusion.rb +13 -5
  67. data/lib/active_support/core_ext/object/instance_variables.rb +4 -2
  68. data/lib/active_support/core_ext/object/json.rb +17 -7
  69. data/lib/active_support/core_ext/object/to_query.rb +0 -2
  70. data/lib/active_support/core_ext/object/with.rb +46 -0
  71. data/lib/active_support/core_ext/object/with_options.rb +9 -9
  72. data/lib/active_support/core_ext/object.rb +1 -0
  73. data/lib/active_support/core_ext/pathname/blank.rb +20 -0
  74. data/lib/active_support/core_ext/pathname/existence.rb +2 -0
  75. data/lib/active_support/core_ext/pathname.rb +1 -0
  76. data/lib/active_support/core_ext/range/conversions.rb +32 -11
  77. data/lib/active_support/core_ext/range/overlap.rb +40 -0
  78. data/lib/active_support/core_ext/range.rb +1 -2
  79. data/lib/active_support/core_ext/securerandom.rb +2 -6
  80. data/lib/active_support/core_ext/string/conversions.rb +3 -3
  81. data/lib/active_support/core_ext/string/filters.rb +21 -15
  82. data/lib/active_support/core_ext/string/indent.rb +1 -1
  83. data/lib/active_support/core_ext/string/inflections.rb +16 -9
  84. data/lib/active_support/core_ext/string/inquiry.rb +1 -1
  85. data/lib/active_support/core_ext/string/multibyte.rb +1 -1
  86. data/lib/active_support/core_ext/string/output_safety.rb +39 -150
  87. data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
  88. data/lib/active_support/core_ext/time/calculations.rb +42 -32
  89. data/lib/active_support/core_ext/time/compatibility.rb +16 -0
  90. data/lib/active_support/core_ext/time/conversions.rb +13 -15
  91. data/lib/active_support/core_ext/time/zones.rb +8 -9
  92. data/lib/active_support/core_ext/time.rb +0 -1
  93. data/lib/active_support/core_ext.rb +0 -1
  94. data/lib/active_support/current_attributes.rb +53 -46
  95. data/lib/active_support/deep_mergeable.rb +53 -0
  96. data/lib/active_support/delegation.rb +202 -0
  97. data/lib/active_support/dependencies/autoload.rb +9 -16
  98. data/lib/active_support/deprecation/behaviors.rb +65 -42
  99. data/lib/active_support/deprecation/constant_accessor.rb +47 -25
  100. data/lib/active_support/deprecation/deprecators.rb +104 -0
  101. data/lib/active_support/deprecation/disallowed.rb +6 -8
  102. data/lib/active_support/deprecation/method_wrappers.rb +6 -23
  103. data/lib/active_support/deprecation/proxy_wrappers.rb +34 -22
  104. data/lib/active_support/deprecation/reporting.rb +49 -27
  105. data/lib/active_support/deprecation.rb +39 -9
  106. data/lib/active_support/deprecator.rb +7 -0
  107. data/lib/active_support/descendants_tracker.rb +66 -175
  108. data/lib/active_support/duration/iso8601_parser.rb +2 -2
  109. data/lib/active_support/duration/iso8601_serializer.rb +1 -4
  110. data/lib/active_support/duration.rb +13 -7
  111. data/lib/active_support/encrypted_configuration.rb +63 -10
  112. data/lib/active_support/encrypted_file.rb +29 -13
  113. data/lib/active_support/environment_inquirer.rb +22 -2
  114. data/lib/active_support/error_reporter/test_helper.rb +15 -0
  115. data/lib/active_support/error_reporter.rb +160 -36
  116. data/lib/active_support/evented_file_update_checker.rb +19 -7
  117. data/lib/active_support/execution_wrapper.rb +23 -28
  118. data/lib/active_support/file_update_checker.rb +5 -3
  119. data/lib/active_support/fork_tracker.rb +4 -32
  120. data/lib/active_support/gem_version.rb +4 -4
  121. data/lib/active_support/gzip.rb +2 -0
  122. data/lib/active_support/hash_with_indifferent_access.rb +41 -25
  123. data/lib/active_support/html_safe_translation.rb +19 -6
  124. data/lib/active_support/i18n.rb +1 -1
  125. data/lib/active_support/i18n_railtie.rb +20 -13
  126. data/lib/active_support/inflector/inflections.rb +2 -0
  127. data/lib/active_support/inflector/methods.rb +28 -18
  128. data/lib/active_support/inflector/transliterate.rb +4 -2
  129. data/lib/active_support/isolated_execution_state.rb +39 -19
  130. data/lib/active_support/json/decoding.rb +2 -1
  131. data/lib/active_support/json/encoding.rb +25 -43
  132. data/lib/active_support/key_generator.rb +13 -5
  133. data/lib/active_support/lazy_load_hooks.rb +33 -7
  134. data/lib/active_support/locale/en.yml +2 -0
  135. data/lib/active_support/log_subscriber/test_helper.rb +2 -2
  136. data/lib/active_support/log_subscriber.rb +76 -36
  137. data/lib/active_support/logger.rb +22 -60
  138. data/lib/active_support/logger_thread_safe_level.rb +10 -32
  139. data/lib/active_support/message_encryptor.rb +200 -55
  140. data/lib/active_support/message_encryptors.rb +141 -0
  141. data/lib/active_support/message_pack/cache_serializer.rb +23 -0
  142. data/lib/active_support/message_pack/extensions.rb +305 -0
  143. data/lib/active_support/message_pack/serializer.rb +63 -0
  144. data/lib/active_support/message_pack.rb +50 -0
  145. data/lib/active_support/message_verifier.rb +220 -89
  146. data/lib/active_support/message_verifiers.rb +135 -0
  147. data/lib/active_support/messages/codec.rb +65 -0
  148. data/lib/active_support/messages/metadata.rb +111 -45
  149. data/lib/active_support/messages/rotation_coordinator.rb +93 -0
  150. data/lib/active_support/messages/rotator.rb +34 -32
  151. data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
  152. data/lib/active_support/multibyte/chars.rb +4 -2
  153. data/lib/active_support/multibyte/unicode.rb +9 -37
  154. data/lib/active_support/notifications/fanout.rb +248 -87
  155. data/lib/active_support/notifications/instrumenter.rb +93 -25
  156. data/lib/active_support/notifications.rb +38 -31
  157. data/lib/active_support/number_helper/number_converter.rb +16 -7
  158. data/lib/active_support/number_helper/number_to_currency_converter.rb +6 -6
  159. data/lib/active_support/number_helper/number_to_human_size_converter.rb +3 -3
  160. data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -0
  161. data/lib/active_support/number_helper.rb +379 -317
  162. data/lib/active_support/option_merger.rb +4 -4
  163. data/lib/active_support/ordered_hash.rb +3 -3
  164. data/lib/active_support/ordered_options.rb +68 -16
  165. data/lib/active_support/parameter_filter.rb +103 -84
  166. data/lib/active_support/proxy_object.rb +8 -3
  167. data/lib/active_support/railtie.rb +30 -25
  168. data/lib/active_support/reloader.rb +13 -5
  169. data/lib/active_support/rescuable.rb +12 -10
  170. data/lib/active_support/secure_compare_rotator.rb +17 -10
  171. data/lib/active_support/string_inquirer.rb +4 -2
  172. data/lib/active_support/subscriber.rb +10 -27
  173. data/lib/active_support/syntax_error_proxy.rb +60 -0
  174. data/lib/active_support/tagged_logging.rb +64 -25
  175. data/lib/active_support/test_case.rb +160 -7
  176. data/lib/active_support/testing/assertions.rb +29 -13
  177. data/lib/active_support/testing/autorun.rb +0 -2
  178. data/lib/active_support/testing/constant_stubbing.rb +54 -0
  179. data/lib/active_support/testing/deprecation.rb +20 -27
  180. data/lib/active_support/testing/error_reporter_assertions.rb +107 -0
  181. data/lib/active_support/testing/isolation.rb +46 -33
  182. data/lib/active_support/testing/method_call_assertions.rb +7 -8
  183. data/lib/active_support/testing/parallelization/server.rb +3 -0
  184. data/lib/active_support/testing/parallelize_executor.rb +8 -3
  185. data/lib/active_support/testing/setup_and_teardown.rb +2 -0
  186. data/lib/active_support/testing/stream.rb +1 -1
  187. data/lib/active_support/testing/strict_warnings.rb +43 -0
  188. data/lib/active_support/testing/tests_without_assertions.rb +19 -0
  189. data/lib/active_support/testing/time_helpers.rb +38 -16
  190. data/lib/active_support/time_with_zone.rb +28 -54
  191. data/lib/active_support/values/time_zone.rb +26 -15
  192. data/lib/active_support/version.rb +1 -1
  193. data/lib/active_support/xml_mini/jdom.rb +3 -10
  194. data/lib/active_support/xml_mini/nokogiri.rb +1 -1
  195. data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
  196. data/lib/active_support/xml_mini/rexml.rb +1 -1
  197. data/lib/active_support/xml_mini.rb +13 -4
  198. data/lib/active_support.rb +15 -3
  199. metadata +142 -21
  200. data/lib/active_support/core_ext/array/deprecated_conversions.rb +0 -25
  201. data/lib/active_support/core_ext/date/deprecated_conversions.rb +0 -26
  202. data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +0 -22
  203. data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +0 -60
  204. data/lib/active_support/core_ext/range/deprecated_conversions.rb +0 -26
  205. data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -7
  206. data/lib/active_support/core_ext/range/overlaps.rb +0 -10
  207. data/lib/active_support/core_ext/time/deprecated_conversions.rb +0 -22
  208. data/lib/active_support/core_ext/uri.rb +0 -5
  209. data/lib/active_support/deprecation/instance_delegator.rb +0 -38
  210. data/lib/active_support/per_thread_registry.rb +0 -65
  211. data/lib/active_support/ruby_features.rb +0 -7
@@ -4,7 +4,9 @@ require "active_support/security_utils"
4
4
  require "active_support/messages/rotator"
5
5
 
6
6
  module ActiveSupport
7
- # The ActiveSupport::SecureCompareRotator is a wrapper around +ActiveSupport::SecurityUtils.secure_compare+
7
+ # = Secure Compare Rotator
8
+ #
9
+ # The ActiveSupport::SecureCompareRotator is a wrapper around ActiveSupport::SecurityUtils.secure_compare
8
10
  # and allows you to rotate a previously defined value to a new one.
9
11
  #
10
12
  # It can be used as follow:
@@ -29,23 +31,28 @@ module ActiveSupport
29
31
  # end
30
32
  class SecureCompareRotator
31
33
  include SecurityUtils
32
- prepend Messages::Rotator
33
34
 
34
35
  InvalidMatch = Class.new(StandardError)
35
36
 
36
- def initialize(value, **_options)
37
+ def initialize(value, on_rotation: nil)
37
38
  @value = value
39
+ @rotate_values = []
40
+ @on_rotation = on_rotation
38
41
  end
39
42
 
40
- def secure_compare!(other_value, on_rotation: @on_rotation)
41
- secure_compare(@value, other_value) ||
42
- run_rotations(on_rotation) { |wrapper| wrapper.secure_compare!(other_value) } ||
43
- raise(InvalidMatch)
43
+ def rotate(previous_value)
44
+ @rotate_values << previous_value
44
45
  end
45
46
 
46
- private
47
- def build_rotation(previous_value, _options)
48
- self.class.new(previous_value)
47
+ def secure_compare!(other_value, on_rotation: @on_rotation)
48
+ if secure_compare(@value, other_value)
49
+ true
50
+ elsif @rotate_values.any? { |value| secure_compare(value, other_value) }
51
+ on_rotation&.call
52
+ true
53
+ else
54
+ raise InvalidMatch
49
55
  end
56
+ end
50
57
  end
51
58
  end
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveSupport
4
+ # = \String Inquirer
5
+ #
4
6
  # Wrapping a string in this class gives you a prettier way to test
5
7
  # for equality. The value returned by <tt>Rails.env</tt> is wrapped
6
8
  # in a StringInquirer object, so instead of calling this:
@@ -11,7 +13,7 @@ module ActiveSupport
11
13
  #
12
14
  # Rails.env.production?
13
15
  #
14
- # == Instantiating a new StringInquirer
16
+ # == Instantiating a new \StringInquirer
15
17
  #
16
18
  # vehicle = ActiveSupport::StringInquirer.new('car')
17
19
  # vehicle.car? # => true
@@ -22,7 +24,7 @@ module ActiveSupport
22
24
  method_name.end_with?("?") || super
23
25
  end
24
26
 
25
- def method_missing(method_name, *arguments)
27
+ def method_missing(method_name, ...)
26
28
  if method_name.end_with?("?")
27
29
  self == method_name[0..-2]
28
30
  else
@@ -3,7 +3,9 @@
3
3
  require "active_support/notifications"
4
4
 
5
5
  module ActiveSupport
6
- # ActiveSupport::Subscriber is an object set to consume
6
+ # = Active Support \Subscriber
7
+ #
8
+ # +ActiveSupport::Subscriber+ is an object set to consume
7
9
  # ActiveSupport::Notifications. The subscriber dispatches notifications to
8
10
  # a registered object based on its given namespace.
9
11
  #
@@ -20,9 +22,9 @@ module ActiveSupport
20
22
  # end
21
23
  # end
22
24
  #
23
- # After configured, whenever a "sql.active_record" notification is published,
24
- # it will properly dispatch the event (ActiveSupport::Notifications::Event) to
25
- # the +sql+ method.
25
+ # After configured, whenever a <tt>"sql.active_record"</tt> notification is
26
+ # published, it will properly dispatch the event
27
+ # (ActiveSupport::Notifications::Event) to the +sql+ method.
26
28
  #
27
29
  # We can detach a subscriber as well:
28
30
  #
@@ -65,6 +67,7 @@ module ActiveSupport
65
67
 
66
68
  # Adds event subscribers for all new methods added to the class.
67
69
  def method_added(event)
70
+ super
68
71
  # Only public methods are added as subscribers, and only if a notifier
69
72
  # has been set up. This means that subscribers will only be set up for
70
73
  # classes that call #attach_to.
@@ -126,38 +129,18 @@ module ActiveSupport
126
129
  attr_reader :patterns # :nodoc:
127
130
 
128
131
  def initialize
129
- @queue_key = [self.class.name, object_id].join "-"
130
132
  @patterns = {}
131
133
  super
132
134
  end
133
135
 
134
- def start(name, id, payload)
135
- event = ActiveSupport::Notifications::Event.new(name, nil, nil, id, payload)
136
- event.start!
137
- parent = event_stack.last
138
- parent << event if parent
139
-
140
- event_stack.push event
141
- end
142
-
143
- def finish(name, id, payload)
144
- event = event_stack.pop
145
- event.finish!
146
- event.payload.merge!(payload)
147
-
148
- method = name.split(".").first
136
+ def call(event)
137
+ method = event.name[0, event.name.index(".")]
149
138
  send(method, event)
150
139
  end
151
140
 
152
141
  def publish_event(event) # :nodoc:
153
- method = event.name.split(".").first
142
+ method = event.name[0, event.name.index(".")]
154
143
  send(method, event)
155
144
  end
156
-
157
- private
158
- def event_stack
159
- registry = ActiveSupport::IsolatedExecutionState[:active_support_subscriber_queue_registry] ||= {}
160
- registry[@queue_key] ||= []
161
- end
162
145
  end
163
146
  end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "delegate"
4
+
5
+ module ActiveSupport
6
+ # This is a class for wrapping syntax errors. The purpose of this class
7
+ # is to enhance the backtraces on SyntaxError exceptions to include the
8
+ # source location of the syntax error. That way we can display the error
9
+ # source on error pages in development.
10
+ class SyntaxErrorProxy < DelegateClass(SyntaxError) # :nodoc:
11
+ def backtrace
12
+ parse_message_for_trace + super
13
+ end
14
+
15
+ class BacktraceLocation < Struct.new(:path, :lineno, :to_s) # :nodoc:
16
+ def spot(_)
17
+ end
18
+
19
+ def label
20
+ end
21
+ end
22
+
23
+ class BacktraceLocationProxy < DelegateClass(Thread::Backtrace::Location) # :nodoc:
24
+ def initialize(loc, ex)
25
+ super(loc)
26
+ @ex = ex
27
+ end
28
+
29
+ def spot(_)
30
+ super(@ex.__getobj__)
31
+ end
32
+ end
33
+
34
+ def backtrace_locations
35
+ return nil if super.nil?
36
+
37
+ parse_message_for_trace.map { |trace|
38
+ file, line = trace.match(/^(.+?):(\d+).*$/, &:captures) || trace
39
+ BacktraceLocation.new(file, line.to_i, trace)
40
+ # We have to wrap these backtrace locations because we need the
41
+ # spot information to come from the originating exception, not the
42
+ # proxy object that's generating these
43
+ } + super.map { |loc| BacktraceLocationProxy.new(loc, self) }
44
+ end
45
+
46
+ private
47
+ def parse_message_for_trace
48
+ if __getobj__.to_s.start_with?("(eval")
49
+ # If the exception is coming from a call to eval, we need to keep
50
+ # the path of the file in which eval was called to ensure we can
51
+ # return the right source fragment to show the location of the
52
+ # error
53
+ location = __getobj__.backtrace_locations[0]
54
+ ["#{location.path}:#{location.lineno}: #{__getobj__}"]
55
+ else
56
+ __getobj__.to_s.split("\n")
57
+ end
58
+ end
59
+ end
60
+ end
@@ -2,18 +2,19 @@
2
2
 
3
3
  require "active_support/core_ext/module/delegation"
4
4
  require "active_support/core_ext/object/blank"
5
- require "logger"
6
5
  require "active_support/logger"
7
6
 
8
7
  module ActiveSupport
8
+ # = Active Support Tagged Logging
9
+ #
9
10
  # Wraps any standard Logger object to provide tagging capabilities.
10
11
  #
11
12
  # May be called with a block:
12
13
  #
13
14
  # logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
14
- # logger.tagged('BCX') { logger.info 'Stuff' } # Logs "[BCX] Stuff"
15
- # logger.tagged('BCX', "Jason") { logger.info 'Stuff' } # Logs "[BCX] [Jason] Stuff"
16
- # logger.tagged('BCX') { logger.tagged('Jason') { logger.info 'Stuff' } } # Logs "[BCX] [Jason] Stuff"
15
+ # logger.tagged('BCX') { logger.info 'Stuff' } # Logs "[BCX] Stuff"
16
+ # logger.tagged('BCX', "Jason") { |tagged_logger| tagged_logger.info 'Stuff' } # Logs "[BCX] [Jason] Stuff"
17
+ # logger.tagged('BCX') { logger.tagged('Jason') { logger.info 'Stuff' } } # Logs "[BCX] [Jason] Stuff"
17
18
  #
18
19
  # If called without a block, a new logger will be returned with applied tags:
19
20
  #
@@ -29,52 +30,86 @@ module ActiveSupport
29
30
  module Formatter # :nodoc:
30
31
  # This method is invoked when a log event occurs.
31
32
  def call(severity, timestamp, progname, msg)
32
- super(severity, timestamp, progname, "#{tags_text}#{msg}")
33
+ super(severity, timestamp, progname, tag_stack.format_message(msg))
33
34
  end
34
35
 
35
36
  def tagged(*tags)
36
- new_tags = push_tags(*tags)
37
+ pushed_count = tag_stack.push_tags(tags).size
37
38
  yield self
38
39
  ensure
39
- pop_tags(new_tags.size)
40
+ pop_tags(pushed_count)
40
41
  end
41
42
 
42
43
  def push_tags(*tags)
43
- tags.flatten!
44
- tags.reject!(&:blank?)
45
- current_tags.concat tags
46
- tags
44
+ tag_stack.push_tags(tags)
47
45
  end
48
46
 
49
- def pop_tags(size = 1)
50
- current_tags.pop size
47
+ def pop_tags(count = 1)
48
+ tag_stack.pop_tags(count)
51
49
  end
52
50
 
53
51
  def clear_tags!
54
- current_tags.clear
52
+ tag_stack.clear
55
53
  end
56
54
 
57
- def current_tags
55
+ def tag_stack
58
56
  # We use our object ID here to avoid conflicting with other instances
59
- thread_key = @thread_key ||= "activesupport_tagged_logging_tags:#{object_id}"
60
- IsolatedExecutionState[thread_key] ||= []
57
+ @thread_key ||= "activesupport_tagged_logging_tags:#{object_id}"
58
+ IsolatedExecutionState[@thread_key] ||= TagStack.new
59
+ end
60
+
61
+ def current_tags
62
+ tag_stack.tags
61
63
  end
62
64
 
63
65
  def tags_text
64
- tags = current_tags
65
- if tags.one?
66
- "[#{tags[0]}] "
67
- elsif tags.any?
68
- tags.collect { |tag| "[#{tag}] " }.join
66
+ tag_stack.format_message("")
67
+ end
68
+ end
69
+
70
+ class TagStack # :nodoc:
71
+ attr_reader :tags
72
+
73
+ def initialize
74
+ @tags = []
75
+ @tags_string = nil
76
+ end
77
+
78
+ def push_tags(tags)
79
+ @tags_string = nil
80
+ tags.flatten!
81
+ tags.reject!(&:blank?)
82
+ @tags.concat(tags)
83
+ tags
84
+ end
85
+
86
+ def pop_tags(count)
87
+ @tags_string = nil
88
+ @tags.pop(count)
89
+ end
90
+
91
+ def clear
92
+ @tags_string = nil
93
+ @tags.clear
94
+ end
95
+
96
+ def format_message(message)
97
+ if @tags.empty?
98
+ message
99
+ elsif @tags.size == 1
100
+ "[#{@tags[0]}] #{message}"
101
+ else
102
+ @tags_string ||= "[#{@tags.join("] [")}] "
103
+ "#{@tags_string}#{message}"
69
104
  end
70
105
  end
71
106
  end
72
107
 
73
108
  module LocalTagStorage # :nodoc:
74
- attr_accessor :current_tags
109
+ attr_accessor :tag_stack
75
110
 
76
111
  def self.extended(base)
77
- base.current_tags = []
112
+ base.tag_stack = TagStack.new
78
113
  end
79
114
  end
80
115
 
@@ -82,7 +117,11 @@ module ActiveSupport
82
117
  logger = logger.clone
83
118
 
84
119
  if logger.formatter
85
- logger.formatter = logger.formatter.dup
120
+ logger.formatter = logger.formatter.clone
121
+
122
+ # Workaround for https://bugs.ruby-lang.org/issues/20250
123
+ # Can be removed when Ruby 3.4 is the least supported version.
124
+ logger.formatter.object_id if logger.formatter.is_a?(Proc)
86
125
  else
87
126
  # Ensure we set a default formatter so we aren't extending nil!
88
127
  logger.formatter = ActiveSupport::Logger::SimpleFormatter.new
@@ -1,15 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- gem "minitest" # make sure we get the gem, not stdlib
4
3
  require "minitest"
5
4
  require "active_support/testing/tagged_logging"
6
5
  require "active_support/testing/setup_and_teardown"
6
+ require "active_support/testing/tests_without_assertions"
7
7
  require "active_support/testing/assertions"
8
+ require "active_support/testing/error_reporter_assertions"
8
9
  require "active_support/testing/deprecation"
9
10
  require "active_support/testing/declarative"
10
11
  require "active_support/testing/isolation"
11
12
  require "active_support/testing/constant_lookup"
12
13
  require "active_support/testing/time_helpers"
14
+ require "active_support/testing/constant_stubbing"
13
15
  require "active_support/testing/file_fixtures"
14
16
  require "active_support/testing/parallelization"
15
17
  require "active_support/testing/parallelize_executor"
@@ -66,7 +68,7 @@ module ActiveSupport
66
68
  # The default parallelization method is to fork processes. If you'd like to
67
69
  # use threads instead you can pass <tt>with: :threads</tt> to the +parallelize+
68
70
  # method. Note the threaded parallelization does not create multiple
69
- # database and will not work with system tests at this time.
71
+ # databases and will not work with system tests.
70
72
  #
71
73
  # parallelize(workers: :number_of_processors, with: :threads)
72
74
  #
@@ -77,11 +79,9 @@ module ActiveSupport
77
79
  # number of tests to run is above the +threshold+ param. The default value is
78
80
  # 50, and it's configurable via +config.active_support.test_parallelization_threshold+.
79
81
  def parallelize(workers: :number_of_processors, with: :processes, threshold: ActiveSupport.test_parallelization_threshold)
80
- workers = Concurrent.physical_processor_count if workers == :number_of_processors
82
+ workers = Concurrent.processor_count if workers == :number_of_processors
81
83
  workers = ENV["PARALLEL_WORKERS"].to_i if ENV["PARALLEL_WORKERS"]
82
84
 
83
- return if workers <= 1
84
-
85
85
  Minitest.parallel_executor = ActiveSupport::Testing::ParallelizeExecutor.new(size: workers, with: with, threshold: threshold)
86
86
  end
87
87
 
@@ -118,34 +118,187 @@ module ActiveSupport
118
118
  def parallelize_teardown(&block)
119
119
  ActiveSupport::Testing::Parallelization.run_cleanup_hook(&block)
120
120
  end
121
+
122
+ # :singleton-method: fixture_paths
123
+ #
124
+ # Returns the ActiveRecord::FixtureSet collection.
125
+ #
126
+ # In your +test_helper.rb+ you must have <tt>require "rails/test_help"</tt>.
127
+
128
+ # :singleton-method: fixture_paths=
129
+ #
130
+ # :call-seq:
131
+ # fixture_paths=(fixture_paths)
132
+ #
133
+ # Sets the given path to the fixture set.
134
+ #
135
+ # Can also append multiple paths.
136
+ #
137
+ # ActiveSupport::TestCase.fixture_paths << "component1/test/fixtures"
138
+ #
139
+ # In your +test_helper.rb+ you must have <tt>require "rails/test_help"</tt>.
121
140
  end
122
141
 
123
142
  alias_method :method_name, :name
124
143
 
125
144
  include ActiveSupport::Testing::TaggedLogging
126
145
  prepend ActiveSupport::Testing::SetupAndTeardown
146
+ prepend ActiveSupport::Testing::TestsWithoutAssertions
127
147
  include ActiveSupport::Testing::Assertions
148
+ include ActiveSupport::Testing::ErrorReporterAssertions
128
149
  include ActiveSupport::Testing::Deprecation
150
+ include ActiveSupport::Testing::ConstantStubbing
129
151
  include ActiveSupport::Testing::TimeHelpers
130
152
  include ActiveSupport::Testing::FileFixtures
131
153
  extend ActiveSupport::Testing::Declarative
132
154
 
133
- # test/unit backwards compatibility methods
134
- alias :assert_raise :assert_raises
155
+ ##
156
+ # :method: assert_not_empty
157
+ #
158
+ # :call-seq:
159
+ # assert_not_empty(obj, msg = nil)
160
+ #
161
+ # Alias for: refute_empty[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_empty]
162
+
163
+ #
135
164
  alias :assert_not_empty :refute_empty
165
+
166
+ ##
167
+ # :method: assert_not_equal
168
+ #
169
+ # :call-seq:
170
+ # assert_not_equal(exp, act, msg = nil)
171
+ #
172
+ # Alias for: refute_equal[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_equal]
173
+
174
+ #
136
175
  alias :assert_not_equal :refute_equal
176
+
177
+ ##
178
+ # :method: assert_not_in_delta
179
+ #
180
+ # :call-seq:
181
+ # assert_not_in_delta(exp, act, delta = 0.001, msg = nil)
182
+ #
183
+ # Alias for: refute_in_delta[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_in_delta]
184
+
185
+ #
137
186
  alias :assert_not_in_delta :refute_in_delta
187
+
188
+ ##
189
+ # :method: assert_not_in_epsilon
190
+ #
191
+ # :call-seq:
192
+ # assert_not_in_epsilon(a, b, epsilon = 0.001, msg = nil)
193
+ #
194
+ # Alias for: refute_in_epsilon[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_in_epsilon]
195
+
196
+ #
138
197
  alias :assert_not_in_epsilon :refute_in_epsilon
198
+
199
+ ##
200
+ # :method: assert_not_includes
201
+ #
202
+ # :call-seq:
203
+ # assert_not_includes(collection, obj, msg = nil)
204
+ #
205
+ # Alias for: refute_includes[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_includes]
206
+
207
+ #
139
208
  alias :assert_not_includes :refute_includes
209
+
210
+ ##
211
+ # :method: assert_not_instance_of
212
+ #
213
+ # :call-seq:
214
+ # assert_not_instance_of(cls, obj, msg = nil)
215
+ #
216
+ # Alias for: refute_instance_of[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_instance_of]
217
+
218
+ #
140
219
  alias :assert_not_instance_of :refute_instance_of
220
+
221
+ ##
222
+ # :method: assert_not_kind_of
223
+ #
224
+ # :call-seq:
225
+ # assert_not_kind_of(cls, obj, msg = nil)
226
+ #
227
+ # Alias for: refute_kind_of[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_kind_of]
228
+
229
+ #
141
230
  alias :assert_not_kind_of :refute_kind_of
231
+
232
+ ##
233
+ # :method: assert_no_match
234
+ #
235
+ # :call-seq:
236
+ # assert_no_match(matcher, obj, msg = nil)
237
+ #
238
+ # Alias for: refute_match[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_match]
239
+
240
+ #
142
241
  alias :assert_no_match :refute_match
242
+
243
+ ##
244
+ # :method: assert_not_nil
245
+ #
246
+ # :call-seq:
247
+ # assert_not_nil(obj, msg = nil)
248
+ #
249
+ # Alias for: refute_nil[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_nil]
250
+
251
+ #
143
252
  alias :assert_not_nil :refute_nil
253
+
254
+ ##
255
+ # :method: assert_not_operator
256
+ #
257
+ # :call-seq:
258
+ # assert_not_operator(o1, op, o2 = UNDEFINED, msg = nil)
259
+ #
260
+ # Alias for: refute_operator[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_operator]
261
+
262
+ #
144
263
  alias :assert_not_operator :refute_operator
264
+
265
+ ##
266
+ # :method: assert_not_predicate
267
+ #
268
+ # :call-seq:
269
+ # assert_not_predicate(o1, op, msg = nil)
270
+ #
271
+ # Alias for: refute_predicate[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_predicate]
272
+
273
+ #
145
274
  alias :assert_not_predicate :refute_predicate
275
+
276
+ ##
277
+ # :method: assert_not_respond_to
278
+ #
279
+ # :call-seq:
280
+ # assert_not_respond_to(obj, meth, msg = nil)
281
+ #
282
+ # Alias for: refute_respond_to[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_respond_to]
283
+
284
+ #
146
285
  alias :assert_not_respond_to :refute_respond_to
286
+
287
+ ##
288
+ # :method: assert_not_same
289
+ #
290
+ # :call-seq:
291
+ # assert_not_same(exp, act, msg = nil)
292
+ #
293
+ # Alias for: refute_same[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_same]
294
+
295
+ #
147
296
  alias :assert_not_same :refute_same
148
297
 
149
298
  ActiveSupport.run_load_hooks(:active_support_test_case, self)
299
+
300
+ def inspect # :nodoc:
301
+ Object.instance_method(:to_s).bind_call(self)
302
+ end
150
303
  end
151
304
  end