activesupport 4.2.11.1 → 6.0.3.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 (263) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +399 -411
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +7 -7
  5. data/lib/active_support/actionable_error.rb +48 -0
  6. data/lib/active_support/all.rb +5 -3
  7. data/lib/active_support/array_inquirer.rb +48 -0
  8. data/lib/active_support/backtrace_cleaner.rb +34 -6
  9. data/lib/active_support/benchmarkable.rb +6 -4
  10. data/lib/active_support/builder.rb +3 -1
  11. data/lib/active_support/cache/file_store.rb +58 -53
  12. data/lib/active_support/cache/mem_cache_store.rb +95 -91
  13. data/lib/active_support/cache/memory_store.rb +39 -36
  14. data/lib/active_support/cache/null_store.rb +11 -7
  15. data/lib/active_support/cache/redis_cache_store.rb +493 -0
  16. data/lib/active_support/cache/strategy/local_cache.rb +75 -42
  17. data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
  18. data/lib/active_support/cache.rb +331 -217
  19. data/lib/active_support/callbacks.rb +650 -592
  20. data/lib/active_support/concern.rb +35 -6
  21. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +35 -0
  22. data/lib/active_support/concurrency/share_lock.rb +226 -0
  23. data/lib/active_support/configurable.rb +13 -14
  24. data/lib/active_support/core_ext/array/access.rb +41 -1
  25. data/lib/active_support/core_ext/array/conversions.rb +24 -20
  26. data/lib/active_support/core_ext/array/extract.rb +21 -0
  27. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  28. data/lib/active_support/core_ext/array/grouping.rb +11 -18
  29. data/lib/active_support/core_ext/array/inquiry.rb +19 -0
  30. data/lib/active_support/core_ext/array/prepend_and_append.rb +4 -6
  31. data/lib/active_support/core_ext/array/wrap.rb +7 -4
  32. data/lib/active_support/core_ext/array.rb +9 -6
  33. data/lib/active_support/core_ext/benchmark.rb +3 -1
  34. data/lib/active_support/core_ext/big_decimal/conversions.rb +10 -12
  35. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  36. data/lib/active_support/core_ext/class/attribute.rb +45 -31
  37. data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
  38. data/lib/active_support/core_ext/class/subclasses.rb +20 -6
  39. data/lib/active_support/core_ext/class.rb +4 -3
  40. data/lib/active_support/core_ext/date/acts_like.rb +3 -1
  41. data/lib/active_support/core_ext/date/blank.rb +14 -0
  42. data/lib/active_support/core_ext/date/calculations.rb +17 -14
  43. data/lib/active_support/core_ext/date/conversions.rb +25 -23
  44. data/lib/active_support/core_ext/date/zones.rb +4 -2
  45. data/lib/active_support/core_ext/date.rb +6 -4
  46. data/lib/active_support/core_ext/date_and_time/calculations.rb +154 -65
  47. data/lib/active_support/core_ext/date_and_time/compatibility.rb +4 -3
  48. data/lib/active_support/core_ext/date_and_time/zones.rb +12 -13
  49. data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
  50. data/lib/active_support/core_ext/date_time/blank.rb +14 -0
  51. data/lib/active_support/core_ext/date_time/calculations.rb +37 -19
  52. data/lib/active_support/core_ext/date_time/compatibility.rb +8 -6
  53. data/lib/active_support/core_ext/date_time/conversions.rb +16 -13
  54. data/lib/active_support/core_ext/date_time.rb +7 -5
  55. data/lib/active_support/core_ext/digest/uuid.rb +7 -5
  56. data/lib/active_support/core_ext/digest.rb +3 -0
  57. data/lib/active_support/core_ext/enumerable.rb +114 -22
  58. data/lib/active_support/core_ext/file/atomic.rb +38 -31
  59. data/lib/active_support/core_ext/file.rb +3 -1
  60. data/lib/active_support/core_ext/hash/compact.rb +4 -23
  61. data/lib/active_support/core_ext/hash/conversions.rb +62 -41
  62. data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
  63. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  64. data/lib/active_support/core_ext/hash/except.rb +12 -9
  65. data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -3
  66. data/lib/active_support/core_ext/hash/keys.rb +19 -42
  67. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  68. data/lib/active_support/core_ext/hash/slice.rb +5 -27
  69. data/lib/active_support/core_ext/hash/transform_values.rb +4 -22
  70. data/lib/active_support/core_ext/hash.rb +10 -9
  71. data/lib/active_support/core_ext/integer/inflections.rb +3 -1
  72. data/lib/active_support/core_ext/integer/multiple.rb +3 -1
  73. data/lib/active_support/core_ext/integer/time.rb +11 -18
  74. data/lib/active_support/core_ext/integer.rb +5 -3
  75. data/lib/active_support/core_ext/kernel/concern.rb +5 -1
  76. data/lib/active_support/core_ext/kernel/reporting.rb +4 -84
  77. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  78. data/lib/active_support/core_ext/kernel.rb +5 -5
  79. data/lib/active_support/core_ext/load_error.rb +3 -22
  80. data/lib/active_support/core_ext/marshal.rb +8 -8
  81. data/lib/active_support/core_ext/module/aliasing.rb +6 -44
  82. data/lib/active_support/core_ext/module/anonymous.rb +12 -1
  83. data/lib/active_support/core_ext/module/attr_internal.rb +8 -9
  84. data/lib/active_support/core_ext/module/attribute_accessors.rb +46 -46
  85. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +144 -0
  86. data/lib/active_support/core_ext/module/concerning.rb +11 -12
  87. data/lib/active_support/core_ext/module/delegation.rb +133 -30
  88. data/lib/active_support/core_ext/module/deprecation.rb +4 -2
  89. data/lib/active_support/core_ext/module/introspection.rb +44 -19
  90. data/lib/active_support/core_ext/module/reachable.rb +5 -7
  91. data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
  92. data/lib/active_support/core_ext/module/remove_method.rb +8 -3
  93. data/lib/active_support/core_ext/module.rb +13 -11
  94. data/lib/active_support/core_ext/name_error.rb +22 -2
  95. data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
  96. data/lib/active_support/core_ext/numeric/conversions.rb +129 -136
  97. data/lib/active_support/core_ext/numeric/inquiry.rb +5 -0
  98. data/lib/active_support/core_ext/numeric/time.rb +35 -23
  99. data/lib/active_support/core_ext/numeric.rb +5 -3
  100. data/lib/active_support/core_ext/object/acts_like.rb +12 -1
  101. data/lib/active_support/core_ext/object/blank.rb +27 -3
  102. data/lib/active_support/core_ext/object/conversions.rb +6 -4
  103. data/lib/active_support/core_ext/object/deep_dup.rb +13 -4
  104. data/lib/active_support/core_ext/object/duplicable.rb +13 -93
  105. data/lib/active_support/core_ext/object/inclusion.rb +5 -3
  106. data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
  107. data/lib/active_support/core_ext/object/json.rb +51 -20
  108. data/lib/active_support/core_ext/object/to_param.rb +3 -1
  109. data/lib/active_support/core_ext/object/to_query.rb +10 -5
  110. data/lib/active_support/core_ext/object/try.rb +81 -23
  111. data/lib/active_support/core_ext/object/with_options.rb +16 -3
  112. data/lib/active_support/core_ext/object.rb +14 -13
  113. data/lib/active_support/core_ext/range/compare_range.rb +76 -0
  114. data/lib/active_support/core_ext/range/conversions.rb +37 -15
  115. data/lib/active_support/core_ext/range/each.rb +18 -17
  116. data/lib/active_support/core_ext/range/include_range.rb +7 -21
  117. data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -0
  118. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  119. data/lib/active_support/core_ext/range.rb +7 -4
  120. data/lib/active_support/core_ext/regexp.rb +2 -0
  121. data/lib/active_support/core_ext/securerandom.rb +45 -0
  122. data/lib/active_support/core_ext/string/access.rb +16 -6
  123. data/lib/active_support/core_ext/string/behavior.rb +3 -1
  124. data/lib/active_support/core_ext/string/conversions.rb +7 -4
  125. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  126. data/lib/active_support/core_ext/string/filters.rb +48 -6
  127. data/lib/active_support/core_ext/string/indent.rb +6 -4
  128. data/lib/active_support/core_ext/string/inflections.rb +66 -24
  129. data/lib/active_support/core_ext/string/inquiry.rb +3 -1
  130. data/lib/active_support/core_ext/string/multibyte.rb +16 -7
  131. data/lib/active_support/core_ext/string/output_safety.rb +93 -40
  132. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
  133. data/lib/active_support/core_ext/string/strip.rb +6 -5
  134. data/lib/active_support/core_ext/string/zones.rb +4 -2
  135. data/lib/active_support/core_ext/string.rb +15 -13
  136. data/lib/active_support/core_ext/time/acts_like.rb +3 -1
  137. data/lib/active_support/core_ext/time/calculations.rb +115 -52
  138. data/lib/active_support/core_ext/time/compatibility.rb +4 -2
  139. data/lib/active_support/core_ext/time/conversions.rb +20 -13
  140. data/lib/active_support/core_ext/time/zones.rb +41 -7
  141. data/lib/active_support/core_ext/time.rb +7 -6
  142. data/lib/active_support/core_ext/uri.rb +6 -7
  143. data/lib/active_support/core_ext.rb +3 -1
  144. data/lib/active_support/current_attributes.rb +203 -0
  145. data/lib/active_support/dependencies/autoload.rb +2 -0
  146. data/lib/active_support/dependencies/interlock.rb +57 -0
  147. data/lib/active_support/dependencies/zeitwerk_integration.rb +117 -0
  148. data/lib/active_support/dependencies.rb +208 -166
  149. data/lib/active_support/deprecation/behaviors.rb +44 -11
  150. data/lib/active_support/deprecation/constant_accessor.rb +52 -0
  151. data/lib/active_support/deprecation/instance_delegator.rb +17 -2
  152. data/lib/active_support/deprecation/method_wrappers.rb +61 -21
  153. data/lib/active_support/deprecation/proxy_wrappers.rb +81 -30
  154. data/lib/active_support/deprecation/reporting.rb +32 -12
  155. data/lib/active_support/deprecation.rb +12 -9
  156. data/lib/active_support/descendants_tracker.rb +57 -9
  157. data/lib/active_support/digest.rb +20 -0
  158. data/lib/active_support/duration/iso8601_parser.rb +123 -0
  159. data/lib/active_support/duration/iso8601_serializer.rb +53 -0
  160. data/lib/active_support/duration.rb +315 -40
  161. data/lib/active_support/encrypted_configuration.rb +45 -0
  162. data/lib/active_support/encrypted_file.rb +100 -0
  163. data/lib/active_support/evented_file_update_checker.rb +234 -0
  164. data/lib/active_support/execution_wrapper.rb +129 -0
  165. data/lib/active_support/executor.rb +8 -0
  166. data/lib/active_support/file_update_checker.rb +62 -37
  167. data/lib/active_support/gem_version.rb +6 -4
  168. data/lib/active_support/gzip.rb +7 -5
  169. data/lib/active_support/hash_with_indifferent_access.rb +129 -30
  170. data/lib/active_support/i18n.rb +9 -6
  171. data/lib/active_support/i18n_railtie.rb +50 -14
  172. data/lib/active_support/inflections.rb +13 -11
  173. data/lib/active_support/inflector/inflections.rb +58 -13
  174. data/lib/active_support/inflector/methods.rb +159 -145
  175. data/lib/active_support/inflector/transliterate.rb +84 -34
  176. data/lib/active_support/inflector.rb +7 -5
  177. data/lib/active_support/json/decoding.rb +32 -30
  178. data/lib/active_support/json/encoding.rb +17 -60
  179. data/lib/active_support/json.rb +4 -2
  180. data/lib/active_support/key_generator.rb +11 -43
  181. data/lib/active_support/lazy_load_hooks.rb +53 -20
  182. data/lib/active_support/locale/en.rb +33 -0
  183. data/lib/active_support/locale/en.yml +2 -0
  184. data/lib/active_support/log_subscriber/test_helper.rb +14 -12
  185. data/lib/active_support/log_subscriber.rb +44 -19
  186. data/lib/active_support/logger.rb +9 -23
  187. data/lib/active_support/logger_silence.rb +32 -14
  188. data/lib/active_support/logger_thread_safe_level.rb +32 -8
  189. data/lib/active_support/message_encryptor.rb +166 -53
  190. data/lib/active_support/message_verifier.rb +149 -16
  191. data/lib/active_support/messages/metadata.rb +72 -0
  192. data/lib/active_support/messages/rotation_configuration.rb +22 -0
  193. data/lib/active_support/messages/rotator.rb +56 -0
  194. data/lib/active_support/multibyte/chars.rb +56 -63
  195. data/lib/active_support/multibyte/unicode.rb +56 -290
  196. data/lib/active_support/multibyte.rb +4 -2
  197. data/lib/active_support/notifications/fanout.rb +109 -22
  198. data/lib/active_support/notifications/instrumenter.rb +107 -16
  199. data/lib/active_support/notifications.rb +51 -10
  200. data/lib/active_support/number_helper/number_converter.rb +16 -15
  201. data/lib/active_support/number_helper/number_to_currency_converter.rb +14 -15
  202. data/lib/active_support/number_helper/number_to_delimited_converter.rb +11 -4
  203. data/lib/active_support/number_helper/number_to_human_converter.rb +13 -10
  204. data/lib/active_support/number_helper/number_to_human_size_converter.rb +11 -9
  205. data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
  206. data/lib/active_support/number_helper/number_to_phone_converter.rb +15 -5
  207. data/lib/active_support/number_helper/number_to_rounded_converter.rb +25 -57
  208. data/lib/active_support/number_helper/rounding_helper.rb +66 -0
  209. data/lib/active_support/number_helper.rb +105 -68
  210. data/lib/active_support/option_merger.rb +24 -4
  211. data/lib/active_support/ordered_hash.rb +7 -5
  212. data/lib/active_support/ordered_options.rb +27 -5
  213. data/lib/active_support/parameter_filter.rb +128 -0
  214. data/lib/active_support/per_thread_registry.rb +9 -4
  215. data/lib/active_support/proxy_object.rb +2 -0
  216. data/lib/active_support/rails.rb +10 -8
  217. data/lib/active_support/railtie.rb +43 -9
  218. data/lib/active_support/reloader.rb +130 -0
  219. data/lib/active_support/rescuable.rb +108 -53
  220. data/lib/active_support/security_utils.rb +15 -11
  221. data/lib/active_support/string_inquirer.rb +11 -4
  222. data/lib/active_support/subscriber.rb +74 -30
  223. data/lib/active_support/tagged_logging.rb +25 -13
  224. data/lib/active_support/test_case.rb +107 -44
  225. data/lib/active_support/testing/assertions.rb +151 -20
  226. data/lib/active_support/testing/autorun.rb +4 -2
  227. data/lib/active_support/testing/constant_lookup.rb +2 -1
  228. data/lib/active_support/testing/declarative.rb +3 -1
  229. data/lib/active_support/testing/deprecation.rb +13 -10
  230. data/lib/active_support/testing/file_fixtures.rb +38 -0
  231. data/lib/active_support/testing/isolation.rb +35 -26
  232. data/lib/active_support/testing/method_call_assertions.rb +70 -0
  233. data/lib/active_support/testing/parallelization.rb +134 -0
  234. data/lib/active_support/testing/setup_and_teardown.rb +13 -8
  235. data/lib/active_support/testing/stream.rb +43 -0
  236. data/lib/active_support/testing/tagged_logging.rb +3 -1
  237. data/lib/active_support/testing/time_helpers.rb +84 -20
  238. data/lib/active_support/time.rb +14 -12
  239. data/lib/active_support/time_with_zone.rb +179 -39
  240. data/lib/active_support/values/time_zone.rb +203 -63
  241. data/lib/active_support/version.rb +3 -1
  242. data/lib/active_support/xml_mini/jdom.rb +116 -115
  243. data/lib/active_support/xml_mini/libxml.rb +16 -13
  244. data/lib/active_support/xml_mini/libxmlsax.rb +15 -14
  245. data/lib/active_support/xml_mini/nokogiri.rb +14 -12
  246. data/lib/active_support/xml_mini/nokogirisax.rb +14 -13
  247. data/lib/active_support/xml_mini/rexml.rb +11 -9
  248. data/lib/active_support/xml_mini.rb +38 -46
  249. data/lib/active_support.rb +13 -11
  250. metadata +84 -26
  251. data/lib/active_support/concurrency/latch.rb +0 -27
  252. data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -16
  253. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
  254. data/lib/active_support/core_ext/date_time/zones.rb +0 -6
  255. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
  256. data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
  257. data/lib/active_support/core_ext/module/method_transplanting.rb +0 -13
  258. data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
  259. data/lib/active_support/core_ext/object/itself.rb +0 -15
  260. data/lib/active_support/core_ext/struct.rb +0 -6
  261. data/lib/active_support/core_ext/thread.rb +0 -86
  262. data/lib/active_support/core_ext/time/marshal.rb +0 -30
  263. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,22 +1,29 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveSupport
2
4
  # Wrapping a string in this class gives you a prettier way to test
3
5
  # for equality. The value returned by <tt>Rails.env</tt> is wrapped
4
- # in a StringInquirer object so instead of calling this:
6
+ # in a StringInquirer object, so instead of calling this:
5
7
  #
6
8
  # Rails.env == 'production'
7
9
  #
8
10
  # you can call this:
9
11
  #
10
12
  # Rails.env.production?
13
+ #
14
+ # == Instantiating a new StringInquirer
15
+ #
16
+ # vehicle = ActiveSupport::StringInquirer.new('car')
17
+ # vehicle.car? # => true
18
+ # vehicle.bike? # => false
11
19
  class StringInquirer < String
12
20
  private
13
-
14
21
  def respond_to_missing?(method_name, include_private = false)
15
- method_name[-1] == '?'
22
+ (method_name[-1] == "?") || super
16
23
  end
17
24
 
18
25
  def method_missing(method_name, *arguments)
19
- if method_name[-1] == '?'
26
+ if method_name[-1] == "?"
20
27
  self == method_name[0..-2]
21
28
  else
22
29
  super
@@ -1,36 +1,37 @@
1
- require 'active_support/per_thread_registry'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/per_thread_registry"
4
+ require "active_support/notifications"
2
5
 
3
6
  module ActiveSupport
4
7
  # ActiveSupport::Subscriber is an object set to consume
5
8
  # ActiveSupport::Notifications. The subscriber dispatches notifications to
6
9
  # a registered object based on its given namespace.
7
10
  #
8
- # An example would be Active Record subscriber responsible for collecting
11
+ # An example would be an Active Record subscriber responsible for collecting
9
12
  # statistics about queries:
10
13
  #
11
14
  # module ActiveRecord
12
15
  # class StatsSubscriber < ActiveSupport::Subscriber
16
+ # attach_to :active_record
17
+ #
13
18
  # def sql(event)
14
19
  # Statsd.timing("sql.#{event.payload[:name]}", event.duration)
15
20
  # end
16
21
  # end
17
22
  # end
18
23
  #
19
- # And it's finally registered as:
20
- #
21
- # ActiveRecord::StatsSubscriber.attach_to :active_record
22
- #
23
- # Since we need to know all instance methods before attaching the log
24
- # subscriber, the line above should be called after your subscriber definition.
25
- #
26
24
  # After configured, whenever a "sql.active_record" notification is published,
27
25
  # it will properly dispatch the event (ActiveSupport::Notifications::Event) to
28
26
  # the +sql+ method.
27
+ #
28
+ # We can detach a subscriber as well:
29
+ #
30
+ # ActiveRecord::StatsSubscriber.detach_from(:active_record)
29
31
  class Subscriber
30
32
  class << self
31
-
32
33
  # Attach the subscriber to a namespace.
33
- def attach_to(namespace, subscriber=new, notifier=ActiveSupport::Notifications)
34
+ def attach_to(namespace, subscriber = new, notifier = ActiveSupport::Notifications)
34
35
  @namespace = namespace
35
36
  @subscriber = subscriber
36
37
  @notifier = notifier
@@ -43,6 +44,25 @@ module ActiveSupport
43
44
  end
44
45
  end
45
46
 
47
+ # Detach the subscriber from a namespace.
48
+ def detach_from(namespace, notifier = ActiveSupport::Notifications)
49
+ @namespace = namespace
50
+ @subscriber = find_attached_subscriber
51
+ @notifier = notifier
52
+
53
+ return unless subscriber
54
+
55
+ subscribers.delete(subscriber)
56
+
57
+ # Remove event subscribers of all existing methods on the class.
58
+ subscriber.public_methods(false).each do |event|
59
+ remove_event_subscriber(event)
60
+ end
61
+
62
+ # Reset notifier so that event subscribers will not add for new methods added to the class.
63
+ @notifier = nil
64
+ end
65
+
46
66
  # Adds event subscribers for all new methods added to the class.
47
67
  def method_added(event)
48
68
  # Only public methods are added as subscribers, and only if a notifier
@@ -57,51 +77,75 @@ module ActiveSupport
57
77
  @@subscribers ||= []
58
78
  end
59
79
 
60
- protected
80
+ private
81
+ attr_reader :subscriber, :notifier, :namespace
82
+
83
+ def add_event_subscriber(event) # :doc:
84
+ return if invalid_event?(event.to_s)
61
85
 
62
- attr_reader :subscriber, :notifier, :namespace
86
+ pattern = prepare_pattern(event)
63
87
 
64
- def add_event_subscriber(event)
65
- return if %w{ start finish }.include?(event.to_s)
88
+ # Don't add multiple subscribers (eg. if methods are redefined).
89
+ return if pattern_subscribed?(pattern)
66
90
 
67
- pattern = "#{event}.#{namespace}"
91
+ subscriber.patterns[pattern] = notifier.subscribe(pattern, subscriber)
92
+ end
68
93
 
69
- # don't add multiple subscribers (eg. if methods are redefined)
70
- return if subscriber.patterns.include?(pattern)
94
+ def remove_event_subscriber(event) # :doc:
95
+ return if invalid_event?(event.to_s)
71
96
 
72
- subscriber.patterns << pattern
73
- notifier.subscribe(pattern, subscriber)
74
- end
97
+ pattern = prepare_pattern(event)
98
+
99
+ return unless pattern_subscribed?(pattern)
100
+
101
+ notifier.unsubscribe(subscriber.patterns[pattern])
102
+ subscriber.patterns.delete(pattern)
103
+ end
104
+
105
+ def find_attached_subscriber
106
+ subscribers.find { |attached_subscriber| attached_subscriber.instance_of?(self) }
107
+ end
108
+
109
+ def invalid_event?(event)
110
+ %w{ start finish }.include?(event.to_s)
111
+ end
112
+
113
+ def prepare_pattern(event)
114
+ "#{event}.#{namespace}"
115
+ end
116
+
117
+ def pattern_subscribed?(pattern)
118
+ subscriber.patterns.key?(pattern)
119
+ end
75
120
  end
76
121
 
77
122
  attr_reader :patterns # :nodoc:
78
123
 
79
124
  def initialize
80
125
  @queue_key = [self.class.name, object_id].join "-"
81
- @patterns = []
126
+ @patterns = {}
82
127
  super
83
128
  end
84
129
 
85
130
  def start(name, id, payload)
86
- e = ActiveSupport::Notifications::Event.new(name, Time.now, nil, id, payload)
131
+ event = ActiveSupport::Notifications::Event.new(name, nil, nil, id, payload)
132
+ event.start!
87
133
  parent = event_stack.last
88
- parent << e if parent
134
+ parent << event if parent
89
135
 
90
- event_stack.push e
136
+ event_stack.push event
91
137
  end
92
138
 
93
139
  def finish(name, id, payload)
94
- finished = Time.now
95
- event = event_stack.pop
96
- event.end = finished
140
+ event = event_stack.pop
141
+ event.finish!
97
142
  event.payload.merge!(payload)
98
143
 
99
- method = name.split('.').first
144
+ method = name.split(".").first
100
145
  send(method, event)
101
146
  end
102
147
 
103
148
  private
104
-
105
149
  def event_stack
106
150
  SubscriberQueueRegistry.instance.get_queue(@queue_key)
107
151
  end
@@ -1,7 +1,9 @@
1
- require 'active_support/core_ext/module/delegation'
2
- require 'active_support/core_ext/object/blank'
3
- require 'logger'
4
- require 'active_support/logger'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/module/delegation"
4
+ require "active_support/core_ext/object/blank"
5
+ require "logger"
6
+ require "active_support/logger"
5
7
 
6
8
  module ActiveSupport
7
9
  # Wraps any standard Logger object to provide tagging capabilities.
@@ -43,21 +45,31 @@ module ActiveSupport
43
45
  end
44
46
 
45
47
  def current_tags
46
- Thread.current[:activesupport_tagged_logging_tags] ||= []
48
+ # We use our object ID here to avoid conflicting with other instances
49
+ thread_key = @thread_key ||= "activesupport_tagged_logging_tags:#{object_id}"
50
+ Thread.current[thread_key] ||= []
47
51
  end
48
52
 
49
- private
50
- def tags_text
51
- tags = current_tags
52
- if tags.any?
53
- tags.collect { |tag| "[#{tag}] " }.join
54
- end
53
+ def tags_text
54
+ tags = current_tags
55
+ if tags.one?
56
+ "[#{tags[0]}] "
57
+ elsif tags.any?
58
+ tags.collect { |tag| "[#{tag}] " }.join
55
59
  end
60
+ end
56
61
  end
57
62
 
58
63
  def self.new(logger)
59
- # Ensure we set a default formatter so we aren't extending nil!
60
- logger.formatter ||= ActiveSupport::Logger::SimpleFormatter.new
64
+ logger = logger.dup
65
+
66
+ if logger.formatter
67
+ logger.formatter = logger.formatter.dup
68
+ else
69
+ # Ensure we set a default formatter so we aren't extending nil!
70
+ logger.formatter = ActiveSupport::Logger::SimpleFormatter.new
71
+ end
72
+
61
73
  logger.formatter.extend Formatter
62
74
  logger.extend(self)
63
75
  end
@@ -1,15 +1,18 @@
1
- gem 'minitest' # make sure we get the gem, not stdlib
2
- require 'minitest'
3
- require 'active_support/testing/tagged_logging'
4
- require 'active_support/testing/setup_and_teardown'
5
- require 'active_support/testing/assertions'
6
- require 'active_support/testing/deprecation'
7
- require 'active_support/testing/declarative'
8
- require 'active_support/testing/isolation'
9
- require 'active_support/testing/constant_lookup'
10
- require 'active_support/testing/time_helpers'
11
- require 'active_support/core_ext/kernel/reporting'
12
- require 'active_support/deprecation'
1
+ # frozen_string_literal: true
2
+
3
+ gem "minitest" # make sure we get the gem, not stdlib
4
+ require "minitest"
5
+ require "active_support/testing/tagged_logging"
6
+ require "active_support/testing/setup_and_teardown"
7
+ require "active_support/testing/assertions"
8
+ require "active_support/testing/deprecation"
9
+ require "active_support/testing/declarative"
10
+ require "active_support/testing/isolation"
11
+ require "active_support/testing/constant_lookup"
12
+ require "active_support/testing/time_helpers"
13
+ require "active_support/testing/file_fixtures"
14
+ require "active_support/testing/parallelization"
15
+ require "concurrent/utility/processor_counter"
13
16
 
14
17
  module ActiveSupport
15
18
  class TestCase < ::Minitest::Test
@@ -31,45 +34,112 @@ module ActiveSupport
31
34
 
32
35
  # Returns the order in which test cases are run.
33
36
  #
34
- # ActiveSupport::TestCase.test_order # => :sorted
37
+ # ActiveSupport::TestCase.test_order # => :random
35
38
  #
36
39
  # Possible values are +:random+, +:parallel+, +:alpha+, +:sorted+.
37
- # Defaults to +:sorted+.
40
+ # Defaults to +:random+.
38
41
  def test_order
39
- test_order = ActiveSupport.test_order
40
-
41
- if test_order.nil?
42
- ActiveSupport::Deprecation.warn "You did not specify a value for the " \
43
- "configuration option `active_support.test_order`. In Rails 5, " \
44
- "the default value of this option will change from `:sorted` to " \
45
- "`:random`.\n" \
46
- "To disable this warning and keep the current behavior, you can add " \
47
- "the following line to your `config/environments/test.rb`:\n" \
48
- "\n" \
49
- " Rails.application.configure do\n" \
50
- " config.active_support.test_order = :sorted\n" \
51
- " end\n" \
52
- "\n" \
53
- "Alternatively, you can opt into the future behavior by setting this " \
54
- "option to `:random`."
55
-
56
- test_order = :sorted
57
- self.test_order = test_order
42
+ ActiveSupport.test_order ||= :random
43
+ end
44
+
45
+ # Parallelizes the test suite.
46
+ #
47
+ # Takes a +workers+ argument that controls how many times the process
48
+ # is forked. For each process a new database will be created suffixed
49
+ # with the worker number.
50
+ #
51
+ # test-database-0
52
+ # test-database-1
53
+ #
54
+ # If <tt>ENV["PARALLEL_WORKERS"]</tt> is set the workers argument will be ignored
55
+ # and the environment variable will be used instead. This is useful for CI
56
+ # environments, or other environments where you may need more workers than
57
+ # you do for local testing.
58
+ #
59
+ # If the number of workers is set to +1+ or fewer, the tests will not be
60
+ # parallelized.
61
+ #
62
+ # If +workers+ is set to +:number_of_processors+, the number of workers will be
63
+ # set to the actual core count on the machine you are on.
64
+ #
65
+ # The default parallelization method is to fork processes. If you'd like to
66
+ # use threads instead you can pass <tt>with: :threads</tt> to the +parallelize+
67
+ # method. Note the threaded parallelization does not create multiple
68
+ # database and will not work with system tests at this time.
69
+ #
70
+ # parallelize(workers: :number_of_processors, with: :threads)
71
+ #
72
+ # The threaded parallelization uses minitest's parallel executor directly.
73
+ # The processes parallelization uses a Ruby DRb server.
74
+ def parallelize(workers: :number_of_processors, with: :processes)
75
+ workers = Concurrent.physical_processor_count if workers == :number_of_processors
76
+ workers = ENV["PARALLEL_WORKERS"].to_i if ENV["PARALLEL_WORKERS"]
77
+
78
+ return if workers <= 1
79
+
80
+ executor = case with
81
+ when :processes
82
+ Testing::Parallelization.new(workers)
83
+ when :threads
84
+ Minitest::Parallel::Executor.new(workers)
85
+ else
86
+ raise ArgumentError, "#{with} is not a supported parallelization executor."
58
87
  end
59
88
 
60
- test_order
89
+ self.lock_threads = false if defined?(self.lock_threads) && with == :threads
90
+
91
+ Minitest.parallel_executor = executor
92
+
93
+ parallelize_me!
94
+ end
95
+
96
+ # Set up hook for parallel testing. This can be used if you have multiple
97
+ # databases or any behavior that needs to be run after the process is forked
98
+ # but before the tests run.
99
+ #
100
+ # Note: this feature is not available with the threaded parallelization.
101
+ #
102
+ # In your +test_helper.rb+ add the following:
103
+ #
104
+ # class ActiveSupport::TestCase
105
+ # parallelize_setup do
106
+ # # create databases
107
+ # end
108
+ # end
109
+ def parallelize_setup(&block)
110
+ ActiveSupport::Testing::Parallelization.after_fork_hook do |worker|
111
+ yield worker
112
+ end
61
113
  end
62
114
 
63
- alias :my_tests_are_order_dependent! :i_suck_and_my_tests_are_order_dependent!
115
+ # Clean up hook for parallel testing. This can be used to drop databases
116
+ # if your app uses multiple write/read databases or other clean up before
117
+ # the tests finish. This runs before the forked process is closed.
118
+ #
119
+ # Note: this feature is not available with the threaded parallelization.
120
+ #
121
+ # In your +test_helper.rb+ add the following:
122
+ #
123
+ # class ActiveSupport::TestCase
124
+ # parallelize_teardown do
125
+ # # drop databases
126
+ # end
127
+ # end
128
+ def parallelize_teardown(&block)
129
+ ActiveSupport::Testing::Parallelization.run_cleanup_hook do |worker|
130
+ yield worker
131
+ end
132
+ end
64
133
  end
65
134
 
66
135
  alias_method :method_name, :name
67
136
 
68
137
  include ActiveSupport::Testing::TaggedLogging
69
- include ActiveSupport::Testing::SetupAndTeardown
138
+ prepend ActiveSupport::Testing::SetupAndTeardown
70
139
  include ActiveSupport::Testing::Assertions
71
140
  include ActiveSupport::Testing::Deprecation
72
141
  include ActiveSupport::Testing::TimeHelpers
142
+ include ActiveSupport::Testing::FileFixtures
73
143
  extend ActiveSupport::Testing::Declarative
74
144
 
75
145
  # test/unit backwards compatibility methods
@@ -88,13 +158,6 @@ module ActiveSupport
88
158
  alias :assert_not_respond_to :refute_respond_to
89
159
  alias :assert_not_same :refute_same
90
160
 
91
- # Fails if the block raises an exception.
92
- #
93
- # assert_nothing_raised do
94
- # ...
95
- # end
96
- def assert_nothing_raised(*args)
97
- yield
98
- end
161
+ ActiveSupport.run_load_hooks(:active_support_test_case, self)
99
162
  end
100
163
  end
@@ -1,9 +1,11 @@
1
- require 'active_support/core_ext/object/blank'
1
+ # frozen_string_literal: true
2
2
 
3
3
  module ActiveSupport
4
4
  module Testing
5
5
  module Assertions
6
- # Assert that an expression is not truthy. Passes if <tt>object</tt> is
6
+ UNTRACKED = Object.new # :nodoc:
7
+
8
+ # Asserts that an expression is not truthy. Passes if <tt>object</tt> is
7
9
  # +nil+ or +false+. "Truthy" means "considered true in a conditional"
8
10
  # like <tt>if foo</tt>.
9
11
  #
@@ -19,79 +21,208 @@ module ActiveSupport
19
21
  assert !object, message
20
22
  end
21
23
 
24
+ # Assertion that the block should not raise an exception.
25
+ #
26
+ # Passes if evaluated code in the yielded block raises no exception.
27
+ #
28
+ # assert_nothing_raised do
29
+ # perform_service(param: 'no_exception')
30
+ # end
31
+ def assert_nothing_raised
32
+ yield
33
+ end
34
+
22
35
  # Test numeric difference between the return value of an expression as a
23
36
  # result of what is evaluated in the yielded block.
24
37
  #
25
38
  # assert_difference 'Article.count' do
26
- # post :create, article: {...}
39
+ # post :create, params: { article: {...} }
27
40
  # end
28
41
  #
29
42
  # An arbitrary expression is passed in and evaluated.
30
43
  #
31
- # assert_difference 'assigns(:article).comments(:reload).size' do
32
- # post :create, comment: {...}
44
+ # assert_difference 'Article.last.comments(:reload).size' do
45
+ # post :create, params: { comment: {...} }
33
46
  # end
34
47
  #
35
48
  # An arbitrary positive or negative difference can be specified.
36
49
  # The default is <tt>1</tt>.
37
50
  #
38
51
  # assert_difference 'Article.count', -1 do
39
- # post :delete, id: ...
52
+ # post :delete, params: { id: ... }
40
53
  # end
41
54
  #
42
55
  # An array of expressions can also be passed in and evaluated.
43
56
  #
44
57
  # assert_difference [ 'Article.count', 'Post.count' ], 2 do
45
- # post :create, article: {...}
58
+ # post :create, params: { article: {...} }
59
+ # end
60
+ #
61
+ # A hash of expressions/numeric differences can also be passed in and evaluated.
62
+ #
63
+ # assert_difference ->{ Article.count } => 1, ->{ Notification.count } => 2 do
64
+ # post :create, params: { article: {...} }
46
65
  # end
47
66
  #
48
67
  # A lambda or a list of lambdas can be passed in and evaluated:
49
68
  #
50
69
  # assert_difference ->{ Article.count }, 2 do
51
- # post :create, article: {...}
70
+ # post :create, params: { article: {...} }
52
71
  # end
53
72
  #
54
73
  # assert_difference [->{ Article.count }, ->{ Post.count }], 2 do
55
- # post :create, article: {...}
74
+ # post :create, params: { article: {...} }
56
75
  # end
57
76
  #
58
77
  # An error message can be specified.
59
78
  #
60
79
  # assert_difference 'Article.count', -1, 'An Article should be destroyed' do
61
- # post :delete, id: ...
80
+ # post :delete, params: { id: ... }
62
81
  # end
63
- def assert_difference(expression, difference = 1, message = nil, &block)
64
- expressions = Array(expression)
82
+ def assert_difference(expression, *args, &block)
83
+ expressions =
84
+ if expression.is_a?(Hash)
85
+ message = args[0]
86
+ expression
87
+ else
88
+ difference = args[0] || 1
89
+ message = args[1]
90
+ Hash[Array(expression).map { |e| [e, difference] }]
91
+ end
65
92
 
66
- exps = expressions.map { |e|
93
+ exps = expressions.keys.map { |e|
67
94
  e.respond_to?(:call) ? e : lambda { eval(e, block.binding) }
68
95
  }
69
- before = exps.map { |e| e.call }
96
+ before = exps.map(&:call)
70
97
 
71
- yield
98
+ retval = yield
72
99
 
73
- expressions.zip(exps).each_with_index do |(code, e), i|
74
- error = "#{code.inspect} didn't change by #{difference}"
100
+ expressions.zip(exps, before) do |(code, diff), exp, before_value|
101
+ error = "#{code.inspect} didn't change by #{diff}"
75
102
  error = "#{message}.\n#{error}" if message
76
- assert_equal(before[i] + difference, e.call, error)
103
+ assert_equal(before_value + diff, exp.call, error)
77
104
  end
105
+
106
+ retval
78
107
  end
79
108
 
80
109
  # Assertion that the numeric result of evaluating an expression is not
81
110
  # changed before and after invoking the passed in block.
82
111
  #
83
112
  # assert_no_difference 'Article.count' do
84
- # post :create, article: invalid_attributes
113
+ # post :create, params: { article: invalid_attributes }
114
+ # end
115
+ #
116
+ # A lambda can be passed in and evaluated.
117
+ #
118
+ # assert_no_difference -> { Article.count } do
119
+ # post :create, params: { article: invalid_attributes }
85
120
  # end
86
121
  #
87
122
  # An error message can be specified.
88
123
  #
89
124
  # assert_no_difference 'Article.count', 'An Article should not be created' do
90
- # post :create, article: invalid_attributes
125
+ # post :create, params: { article: invalid_attributes }
126
+ # end
127
+ #
128
+ # An array of expressions can also be passed in and evaluated.
129
+ #
130
+ # assert_no_difference [ 'Article.count', -> { Post.count } ] do
131
+ # post :create, params: { article: invalid_attributes }
91
132
  # end
92
133
  def assert_no_difference(expression, message = nil, &block)
93
134
  assert_difference expression, 0, message, &block
94
135
  end
136
+
137
+ # Assertion that the result of evaluating an expression is changed before
138
+ # and after invoking the passed in block.
139
+ #
140
+ # assert_changes 'Status.all_good?' do
141
+ # post :create, params: { status: { ok: false } }
142
+ # end
143
+ #
144
+ # You can pass the block as a string to be evaluated in the context of
145
+ # the block. A lambda can be passed for the block as well.
146
+ #
147
+ # assert_changes -> { Status.all_good? } do
148
+ # post :create, params: { status: { ok: false } }
149
+ # end
150
+ #
151
+ # The assertion is useful to test side effects. The passed block can be
152
+ # anything that can be converted to string with #to_s.
153
+ #
154
+ # assert_changes :@object do
155
+ # @object = 42
156
+ # end
157
+ #
158
+ # The keyword arguments :from and :to can be given to specify the
159
+ # expected initial value and the expected value after the block was
160
+ # executed.
161
+ #
162
+ # assert_changes :@object, from: nil, to: :foo do
163
+ # @object = :foo
164
+ # end
165
+ #
166
+ # An error message can be specified.
167
+ #
168
+ # assert_changes -> { Status.all_good? }, 'Expected the status to be bad' do
169
+ # post :create, params: { status: { incident: true } }
170
+ # end
171
+ def assert_changes(expression, message = nil, from: UNTRACKED, to: UNTRACKED, &block)
172
+ exp = expression.respond_to?(:call) ? expression : -> { eval(expression.to_s, block.binding) }
173
+
174
+ before = exp.call
175
+ retval = yield
176
+
177
+ unless from == UNTRACKED
178
+ error = "#{expression.inspect} isn't #{from.inspect}"
179
+ error = "#{message}.\n#{error}" if message
180
+ assert from === before, error
181
+ end
182
+
183
+ after = exp.call
184
+
185
+ error = "#{expression.inspect} didn't change"
186
+ error = "#{error}. It was already #{to}" if before == to
187
+ error = "#{message}.\n#{error}" if message
188
+ assert before != after, error
189
+
190
+ unless to == UNTRACKED
191
+ error = "#{expression.inspect} didn't change to as expected\n"
192
+ error = "#{error}Expected: #{to.inspect}\n"
193
+ error = "#{error} Actual: #{after.inspect}"
194
+ error = "#{message}.\n#{error}" if message
195
+ assert to === after, error
196
+ end
197
+
198
+ retval
199
+ end
200
+
201
+ # Assertion that the result of evaluating an expression is not changed before
202
+ # and after invoking the passed in block.
203
+ #
204
+ # assert_no_changes 'Status.all_good?' do
205
+ # post :create, params: { status: { ok: true } }
206
+ # end
207
+ #
208
+ # An error message can be specified.
209
+ #
210
+ # assert_no_changes -> { Status.all_good? }, 'Expected the status to be good' do
211
+ # post :create, params: { status: { ok: false } }
212
+ # end
213
+ def assert_no_changes(expression, message = nil, &block)
214
+ exp = expression.respond_to?(:call) ? expression : -> { eval(expression.to_s, block.binding) }
215
+
216
+ before = exp.call
217
+ retval = yield
218
+ after = exp.call
219
+
220
+ error = "#{expression.inspect} did change to #{after}"
221
+ error = "#{message}.\n#{error}" if message
222
+ assert before == after, error
223
+
224
+ retval
225
+ end
95
226
  end
96
227
  end
97
228
  end