activesupport 7.1.5.1 → 7.2.0.beta1

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 (88) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +113 -1178
  3. data/lib/active_support/array_inquirer.rb +1 -1
  4. data/lib/active_support/backtrace_cleaner.rb +10 -3
  5. data/lib/active_support/broadcast_logger.rb +18 -19
  6. data/lib/active_support/cache/file_store.rb +15 -10
  7. data/lib/active_support/cache/mem_cache_store.rb +16 -74
  8. data/lib/active_support/cache/memory_store.rb +2 -1
  9. data/lib/active_support/cache/redis_cache_store.rb +16 -13
  10. data/lib/active_support/cache/serializer_with_fallback.rb +0 -23
  11. data/lib/active_support/cache.rb +59 -67
  12. data/lib/active_support/callbacks.rb +74 -113
  13. data/lib/active_support/code_generator.rb +10 -15
  14. data/lib/active_support/core_ext/array/conversions.rb +0 -2
  15. data/lib/active_support/core_ext/class/subclasses.rb +15 -35
  16. data/lib/active_support/core_ext/date/blank.rb +4 -0
  17. data/lib/active_support/core_ext/date/conversions.rb +0 -2
  18. data/lib/active_support/core_ext/date_and_time/compatibility.rb +12 -9
  19. data/lib/active_support/core_ext/date_time/blank.rb +4 -0
  20. data/lib/active_support/core_ext/date_time/compatibility.rb +3 -5
  21. data/lib/active_support/core_ext/date_time/conversions.rb +0 -4
  22. data/lib/active_support/core_ext/erb/util.rb +5 -0
  23. data/lib/active_support/core_ext/hash/keys.rb +4 -4
  24. data/lib/active_support/core_ext/module/attr_internal.rb +17 -6
  25. data/lib/active_support/core_ext/module/delegation.rb +20 -163
  26. data/lib/active_support/core_ext/module/deprecation.rb +1 -4
  27. data/lib/active_support/core_ext/numeric/conversions.rb +3 -3
  28. data/lib/active_support/core_ext/object/blank.rb +45 -1
  29. data/lib/active_support/core_ext/object/instance_variables.rb +11 -19
  30. data/lib/active_support/core_ext/object/json.rb +4 -6
  31. data/lib/active_support/core_ext/object/with.rb +5 -3
  32. data/lib/active_support/core_ext/pathname/blank.rb +4 -0
  33. data/lib/active_support/core_ext/range/overlap.rb +1 -1
  34. data/lib/active_support/core_ext/string/conversions.rb +1 -1
  35. data/lib/active_support/core_ext/string/filters.rb +1 -1
  36. data/lib/active_support/core_ext/string/output_safety.rb +0 -7
  37. data/lib/active_support/core_ext/time/calculations.rb +12 -27
  38. data/lib/active_support/core_ext/time/compatibility.rb +2 -3
  39. data/lib/active_support/core_ext/time/conversions.rb +0 -2
  40. data/lib/active_support/core_ext.rb +0 -1
  41. data/lib/active_support/current_attributes.rb +33 -40
  42. data/lib/active_support/delegation.rb +188 -0
  43. data/lib/active_support/dependencies/autoload.rb +0 -12
  44. data/lib/active_support/deprecation/constant_accessor.rb +1 -3
  45. data/lib/active_support/deprecation/proxy_wrappers.rb +9 -12
  46. data/lib/active_support/deprecation/reporting.rb +9 -4
  47. data/lib/active_support/deprecation.rb +8 -5
  48. data/lib/active_support/descendants_tracker.rb +9 -87
  49. data/lib/active_support/duration/iso8601_parser.rb +2 -2
  50. data/lib/active_support/duration/iso8601_serializer.rb +1 -2
  51. data/lib/active_support/duration.rb +11 -6
  52. data/lib/active_support/error_reporter.rb +41 -3
  53. data/lib/active_support/evented_file_update_checker.rb +0 -1
  54. data/lib/active_support/execution_wrapper.rb +0 -1
  55. data/lib/active_support/file_update_checker.rb +1 -1
  56. data/lib/active_support/fork_tracker.rb +2 -38
  57. data/lib/active_support/gem_version.rb +3 -3
  58. data/lib/active_support/hash_with_indifferent_access.rb +6 -8
  59. data/lib/active_support/html_safe_translation.rb +3 -0
  60. data/lib/active_support/log_subscriber.rb +0 -12
  61. data/lib/active_support/logger.rb +15 -2
  62. data/lib/active_support/message_pack/extensions.rb +15 -2
  63. data/lib/active_support/multibyte/chars.rb +2 -2
  64. data/lib/active_support/notifications/fanout.rb +4 -7
  65. data/lib/active_support/notifications/instrumenter.rb +21 -18
  66. data/lib/active_support/notifications.rb +28 -27
  67. data/lib/active_support/number_helper/number_converter.rb +2 -2
  68. data/lib/active_support/option_merger.rb +2 -2
  69. data/lib/active_support/ordered_options.rb +53 -15
  70. data/lib/active_support/proxy_object.rb +8 -5
  71. data/lib/active_support/railtie.rb +4 -11
  72. data/lib/active_support/string_inquirer.rb +1 -1
  73. data/lib/active_support/syntax_error_proxy.rb +11 -1
  74. data/lib/active_support/test_case.rb +3 -1
  75. data/lib/active_support/testing/assertions.rb +4 -4
  76. data/lib/active_support/testing/constant_stubbing.rb +30 -8
  77. data/lib/active_support/testing/deprecation.rb +5 -12
  78. data/lib/active_support/testing/isolation.rb +18 -8
  79. data/lib/active_support/testing/method_call_assertions.rb +2 -16
  80. data/lib/active_support/testing/strict_warnings.rb +5 -4
  81. data/lib/active_support/testing/tests_without_assertions.rb +19 -0
  82. data/lib/active_support/time_with_zone.rb +9 -10
  83. data/lib/active_support/values/time_zone.rb +1 -1
  84. data/lib/active_support/xml_mini.rb +11 -2
  85. data/lib/active_support.rb +7 -8
  86. metadata +20 -70
  87. data/lib/active_support/deprecation/instance_delegator.rb +0 -65
  88. data/lib/active_support/ruby_features.rb +0 -7
@@ -26,12 +26,16 @@ module ActiveSupport
26
26
  class ErrorReporter
27
27
  SEVERITIES = %i(error warning info)
28
28
  DEFAULT_SOURCE = "application"
29
+ DEFAULT_RESCUE = [StandardError].freeze
29
30
 
30
- attr_accessor :logger
31
+ attr_accessor :logger, :debug_mode
32
+
33
+ UnexpectedError = Class.new(Exception)
31
34
 
32
35
  def initialize(*subscribers, logger: nil)
33
36
  @subscribers = subscribers.flatten
34
37
  @logger = logger
38
+ @debug_mode = false
35
39
  end
36
40
 
37
41
  # Evaluates the given block, reporting and swallowing any unhandled error.
@@ -72,7 +76,7 @@ module ActiveSupport
72
76
  # source of the error. Subscribers can use this value to ignore certain
73
77
  # errors. Defaults to <tt>"application"</tt>.
74
78
  def handle(*error_classes, severity: :warning, context: {}, fallback: nil, source: DEFAULT_SOURCE)
75
- error_classes = [StandardError] if error_classes.blank?
79
+ error_classes = DEFAULT_RESCUE if error_classes.empty?
76
80
  yield
77
81
  rescue *error_classes => error
78
82
  report(error, handled: true, severity: severity, context: context, source: source)
@@ -108,13 +112,47 @@ module ActiveSupport
108
112
  # source of the error. Subscribers can use this value to ignore certain
109
113
  # errors. Defaults to <tt>"application"</tt>.
110
114
  def record(*error_classes, severity: :error, context: {}, source: DEFAULT_SOURCE)
111
- error_classes = [StandardError] if error_classes.blank?
115
+ error_classes = DEFAULT_RESCUE if error_classes.empty?
112
116
  yield
113
117
  rescue *error_classes => error
114
118
  report(error, handled: false, severity: severity, context: context, source: source)
115
119
  raise
116
120
  end
117
121
 
122
+ # Either report the given error when in production, or raise it when in development or test.
123
+ #
124
+ # When called in production, after the error is reported, this method will return
125
+ # nil and execution will continue.
126
+ #
127
+ # When called in development, the original error is wrapped in a different error class to ensure
128
+ # it's not being rescued higher in the stack and will be surfaced to the developer.
129
+ #
130
+ # This method is intended for reporting violated assertions about preconditions, or similar
131
+ # cases that can and should be gracefully handled in production, but that aren't supposed to happen.
132
+ #
133
+ # The error can be either an exception instance or a String.
134
+ #
135
+ # example:
136
+ #
137
+ # def edit
138
+ # if published?
139
+ # Rails.error.unexpected("[BUG] Attempting to edit a published article, that shouldn't be possible")
140
+ # return false
141
+ # end
142
+ # # ...
143
+ # end
144
+ #
145
+ def unexpected(error, severity: :warning, context: {}, source: DEFAULT_SOURCE)
146
+ error = RuntimeError.new(error) if error.is_a?(String)
147
+ error.set_backtrace(caller(1)) if error.backtrace.nil?
148
+
149
+ if @debug_mode
150
+ raise UnexpectedError, "#{error.class.name}: #{error.message}", error.backtrace, cause: error
151
+ else
152
+ report(error, handled: true, severity: severity, context: context, source: source)
153
+ end
154
+ end
155
+
118
156
  # Register a new error subscriber. The subscriber must respond to
119
157
  #
120
158
  # report(Exception, handled: Boolean, severity: (:error OR :warning OR :info), context: Hash, source: String)
@@ -6,7 +6,6 @@ require "listen"
6
6
  require "set"
7
7
  require "pathname"
8
8
  require "concurrent/atomic/atomic_boolean"
9
- require "active_support/fork_tracker"
10
9
 
11
10
  module ActiveSupport
12
11
  # Allows you to "listen" to changes in a file system.
@@ -2,7 +2,6 @@
2
2
 
3
3
  require "active_support/error_reporter"
4
4
  require "active_support/callbacks"
5
- require "concurrent/hash"
6
5
 
7
6
  module ActiveSupport
8
7
  class ExecutionWrapper
@@ -104,7 +104,7 @@ module ActiveSupport
104
104
  @watched || begin
105
105
  all = @files.select { |f| File.exist?(f) }
106
106
  all.concat(Dir[@glob]) if @glob
107
- all
107
+ all.tap(&:uniq!)
108
108
  end
109
109
  end
110
110
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  module ActiveSupport
4
4
  module ForkTracker # :nodoc:
5
- module ModernCoreExt
5
+ module CoreExt
6
6
  def _fork
7
7
  pid = super
8
8
  if pid == 0
@@ -12,27 +12,6 @@ module ActiveSupport
12
12
  end
13
13
  end
14
14
 
15
- module CoreExt
16
- def fork(...)
17
- if block_given?
18
- super do
19
- ForkTracker.check!
20
- yield
21
- end
22
- else
23
- unless pid = super
24
- ForkTracker.check!
25
- end
26
- pid
27
- end
28
- end
29
- end
30
-
31
- module CoreExtPrivate
32
- include CoreExt
33
- private :fork
34
- end
35
-
36
15
  @pid = Process.pid
37
16
  @callbacks = []
38
17
 
@@ -45,23 +24,8 @@ module ActiveSupport
45
24
  end
46
25
  end
47
26
 
48
- if Process.respond_to?(:_fork) # Ruby 3.1+
49
- def check!
50
- # We trust the `_fork` callback
51
- end
52
- else
53
- alias_method :check!, :after_fork_callback
54
- end
55
-
56
27
  def hook!
57
- if Process.respond_to?(:_fork) # Ruby 3.1+
58
- ::Process.singleton_class.prepend(ModernCoreExt)
59
- elsif Process.respond_to?(:fork)
60
- ::Object.prepend(CoreExtPrivate) if RUBY_VERSION < "3.0"
61
- ::Kernel.prepend(CoreExtPrivate)
62
- ::Kernel.singleton_class.prepend(CoreExt)
63
- ::Process.singleton_class.prepend(CoreExt)
64
- end
28
+ ::Process.singleton_class.prepend(CoreExt)
65
29
  end
66
30
 
67
31
  def after_fork(&block)
@@ -8,9 +8,9 @@ module ActiveSupport
8
8
 
9
9
  module VERSION
10
10
  MAJOR = 7
11
- MINOR = 1
12
- TINY = 5
13
- PRE = "1"
11
+ MINOR = 2
12
+ TINY = 0
13
+ PRE = "beta1"
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -387,15 +387,13 @@ module ActiveSupport
387
387
  _new_hash
388
388
  end
389
389
 
390
+ def to_proc
391
+ proc { |key| self[key] }
392
+ end
393
+
390
394
  private
391
- if Symbol.method_defined?(:name)
392
- def convert_key(key)
393
- key.kind_of?(Symbol) ? key.name : key
394
- end
395
- else
396
- def convert_key(key)
397
- key.kind_of?(Symbol) ? key.to_s : key
398
- end
395
+ def convert_key(key)
396
+ Symbol === key ? key.name : key
399
397
  end
400
398
 
401
399
  def convert_value(value, conversion: nil)
@@ -9,11 +9,14 @@ module ActiveSupport
9
9
  html_safe_options = html_escape_translation_options(options)
10
10
 
11
11
  exception = false
12
+
12
13
  exception_handler = ->(*args) do
13
14
  exception = true
14
15
  I18n.exception_handler.call(*args)
15
16
  end
17
+
16
18
  translation = I18n.translate(key, **html_safe_options, exception_handler: exception_handler)
19
+
17
20
  if exception
18
21
  translation
19
22
  else
@@ -62,10 +62,6 @@ module ActiveSupport
62
62
  # that all logs are flushed, and it is called in Rails::Rack::Logger after a
63
63
  # request finishes.
64
64
  class LogSubscriber < Subscriber
65
- # Embed in a String to clear all previous ANSI sequences.
66
- CLEAR = ActiveSupport::Deprecation::DeprecatedObjectProxy.new("\e[0m", "CLEAR is deprecated! Use MODES[:clear] instead.", ActiveSupport.deprecator)
67
- BOLD = ActiveSupport::Deprecation::DeprecatedObjectProxy.new("\e[1m", "BOLD is deprecated! Use MODES[:bold] instead.", ActiveSupport.deprecator)
68
-
69
65
  # ANSI sequence modes
70
66
  MODES = {
71
67
  clear: 0,
@@ -182,14 +178,6 @@ module ActiveSupport
182
178
  end
183
179
 
184
180
  def mode_from(options)
185
- if options.is_a?(TrueClass) || options.is_a?(FalseClass)
186
- ActiveSupport.deprecator.warn(<<~MSG.squish)
187
- Bolding log text with a positional boolean is deprecated and will be removed
188
- in Rails 7.2. Use an option hash instead (eg. `color("my text", :red, bold: true)`).
189
- MSG
190
- options = { bold: options }
191
- end
192
-
193
181
  modes = MODES.values_at(*options.compact_blank.keys)
194
182
 
195
183
  "\e[#{modes.join(";")}m" if modes.any?
@@ -13,6 +13,10 @@ module ActiveSupport
13
13
  # logger = Logger.new(STDOUT)
14
14
  # ActiveSupport::Logger.logger_outputs_to?(logger, STDOUT)
15
15
  # # => true
16
+ #
17
+ # logger = Logger.new('/var/log/rails.log')
18
+ # ActiveSupport::Logger.logger_outputs_to?(logger, '/var/log/rails.log')
19
+ # # => true
16
20
  def self.logger_outputs_to?(logger, *sources)
17
21
  loggers = if logger.is_a?(BroadcastLogger)
18
22
  logger.broadcasts
@@ -21,9 +25,9 @@ module ActiveSupport
21
25
  end
22
26
 
23
27
  logdevs = loggers.map { |logger| logger.instance_variable_get(:@logdev) }
24
- logger_sources = logdevs.filter_map { |logdev| logdev.dev if logdev.respond_to?(:dev) }
28
+ logger_sources = logdevs.filter_map { |logdev| logdev.try(:filename) || logdev.try(:dev) }
25
29
 
26
- (sources & logger_sources).any?
30
+ normalize_sources(sources).intersect?(normalize_sources(logger_sources))
27
31
  end
28
32
 
29
33
  def initialize(*args, **kwargs)
@@ -38,5 +42,14 @@ module ActiveSupport
38
42
  "#{String === msg ? msg : msg.inspect}\n"
39
43
  end
40
44
  end
45
+
46
+ private
47
+ def self.normalize_sources(sources)
48
+ sources.map do |source|
49
+ source = source.path if source.respond_to?(:path)
50
+ source = File.realpath(source) if source.is_a?(String) && File.exist?(source)
51
+ source
52
+ end
53
+ end
41
54
  end
42
55
  end
@@ -86,8 +86,9 @@ module ActiveSupport
86
86
  unpacker: URI.method(:parse)
87
87
 
88
88
  registry.register_type 14, IPAddr,
89
- packer: :to_s,
90
- unpacker: :new
89
+ packer: method(:write_ipaddr),
90
+ unpacker: method(:read_ipaddr),
91
+ recursive: true
91
92
 
92
93
  registry.register_type 15, Pathname,
93
94
  packer: :to_s,
@@ -221,6 +222,18 @@ module ActiveSupport
221
222
  Set.new(unpacker.read)
222
223
  end
223
224
 
225
+ def write_ipaddr(ipaddr, packer)
226
+ if ipaddr.prefix < 32 || (ipaddr.ipv6? && ipaddr.prefix < 128)
227
+ packer.write("#{ipaddr}/#{ipaddr.prefix}")
228
+ else
229
+ packer.write(ipaddr.to_s)
230
+ end
231
+ end
232
+
233
+ def read_ipaddr(unpacker)
234
+ IPAddr.new(unpacker.read)
235
+ end
236
+
224
237
  def write_hash_with_indifferent_access(hwia, packer)
225
238
  packer.write(hwia.to_h)
226
239
  end
@@ -59,8 +59,8 @@ module ActiveSupport # :nodoc:
59
59
  end
60
60
 
61
61
  # Forward all undefined methods to the wrapped string.
62
- def method_missing(method, *args, &block)
63
- result = @wrapped_string.__send__(method, *args, &block)
62
+ def method_missing(method, ...)
63
+ result = @wrapped_string.__send__(method, ...)
64
64
  if method.end_with?("!")
65
65
  self if result
66
66
  else
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "mutex_m"
4
3
  require "concurrent/map"
5
4
  require "set"
6
5
  require "active_support/core_ext/object/try"
@@ -49,15 +48,13 @@ module ActiveSupport
49
48
  #
50
49
  # This class is thread safe. All methods are reentrant.
51
50
  class Fanout
52
- include Mutex_m
53
-
54
51
  def initialize
52
+ @mutex = Mutex.new
55
53
  @string_subscribers = Concurrent::Map.new { |h, k| h.compute_if_absent(k) { [] } }
56
54
  @other_subscribers = []
57
55
  @all_listeners_for = Concurrent::Map.new
58
56
  @groups_for = Concurrent::Map.new
59
57
  @silenceable_groups_for = Concurrent::Map.new
60
- super
61
58
  end
62
59
 
63
60
  def inspect # :nodoc:
@@ -67,7 +64,7 @@ module ActiveSupport
67
64
 
68
65
  def subscribe(pattern = nil, callable = nil, monotonic: false, &block)
69
66
  subscriber = Subscribers.new(pattern, callable || block, monotonic)
70
- synchronize do
67
+ @mutex.synchronize do
71
68
  case pattern
72
69
  when String
73
70
  @string_subscribers[pattern] << subscriber
@@ -83,7 +80,7 @@ module ActiveSupport
83
80
  end
84
81
 
85
82
  def unsubscribe(subscriber_or_name)
86
- synchronize do
83
+ @mutex.synchronize do
87
84
  case subscriber_or_name
88
85
  when String
89
86
  @string_subscribers[subscriber_or_name].clear
@@ -300,7 +297,7 @@ module ActiveSupport
300
297
 
301
298
  def all_listeners_for(name)
302
299
  # this is correctly done double-checked locking (Concurrent::Map's lookups have volatile semantics)
303
- @all_listeners_for[name] || synchronize do
300
+ @all_listeners_for[name] || @mutex.synchronize do
304
301
  # use synchronisation when accessing @subscribers
305
302
  @all_listeners_for[name] ||=
306
303
  @string_subscribers[name] + @other_subscribers.select { |s| s.subscribed_to?(name) }
@@ -117,6 +117,8 @@ module ActiveSupport
117
117
  @cpu_time_finish = 0.0
118
118
  @allocation_count_start = 0
119
119
  @allocation_count_finish = 0
120
+ @gc_time_start = 0
121
+ @gc_time_finish = 0
120
122
  end
121
123
 
122
124
  def time
@@ -144,12 +146,14 @@ module ActiveSupport
144
146
  def start!
145
147
  @time = now
146
148
  @cpu_time_start = now_cpu
149
+ @gc_time_start = now_gc
147
150
  @allocation_count_start = now_allocations
148
151
  end
149
152
 
150
153
  # Record information at the time this event finishes
151
154
  def finish!
152
155
  @cpu_time_finish = now_cpu
156
+ @gc_time_finish = now_gc
153
157
  @end = now
154
158
  @allocation_count_finish = now_allocations
155
159
  end
@@ -173,28 +177,17 @@ module ActiveSupport
173
177
  @allocation_count_finish - @allocation_count_start
174
178
  end
175
179
 
176
- def children # :nodoc:
177
- ActiveSupport.deprecator.warn <<~EOM
178
- ActiveSupport::Notifications::Event#children is deprecated and will
179
- be removed in Rails 7.2.
180
- EOM
181
- []
182
- end
183
-
184
- def parent_of?(event) # :nodoc:
185
- ActiveSupport.deprecator.warn <<~EOM
186
- ActiveSupport::Notifications::Event#parent_of? is deprecated and will
187
- be removed in Rails 7.2.
188
- EOM
189
- start = (time - event.time) * 1000
190
- start <= 0 && (start + duration >= event.duration)
180
+ # Returns the time spent in GC (in milliseconds) between the call to #start!
181
+ # and the call to #finish!
182
+ def gc_time
183
+ (@gc_time_finish - @gc_time_start) / 1_000_000.0
191
184
  end
192
185
 
193
186
  # Returns the difference in milliseconds between when the execution of the
194
187
  # event started and when it ended.
195
188
  #
196
- # ActiveSupport::Notifications.subscribe('wait') do |*args|
197
- # @event = ActiveSupport::Notifications::Event.new(*args)
189
+ # ActiveSupport::Notifications.subscribe('wait') do |event|
190
+ # @event = event
198
191
  # end
199
192
  #
200
193
  # ActiveSupport::Notifications.instrument('wait') do
@@ -218,11 +211,21 @@ module ActiveSupport
218
211
  Process.clock_gettime(Process::CLOCK_THREAD_CPUTIME_ID, :float_millisecond)
219
212
  end
220
213
  rescue
221
- def now_cpu # rubocop:disable Lint/DuplicateMethods
214
+ def now_cpu
222
215
  0.0
223
216
  end
224
217
  end
225
218
 
219
+ if GC.respond_to?(:total_time)
220
+ def now_gc
221
+ GC.total_time
222
+ end
223
+ else
224
+ def now_gc
225
+ 0
226
+ end
227
+ end
228
+
226
229
  if GC.stat.key?(:total_allocated_objects)
227
230
  def now_allocations
228
231
  GC.stat(:total_allocated_objects)
@@ -29,6 +29,16 @@ module ActiveSupport
29
29
  # You can consume those events and the information they provide by registering
30
30
  # a subscriber.
31
31
  #
32
+ # ActiveSupport::Notifications.subscribe('render') do |event|
33
+ # event.name # => "render"
34
+ # event.duration # => 10 (in milliseconds)
35
+ # event.payload # => { extra: :information }
36
+ # event.allocations # => 1826 (objects)
37
+ # end
38
+ #
39
+ # +Event+ objects record CPU time and allocations. If you don't need this
40
+ # it's also possible to pass a block that accepts five arguments:
41
+ #
32
42
  # ActiveSupport::Notifications.subscribe('render') do |name, start, finish, id, payload|
33
43
  # name # => String, name of the event (such as 'render' from above)
34
44
  # start # => Time, when the instrumented block started execution
@@ -42,20 +52,18 @@ module ActiveSupport
42
52
  #
43
53
  # ActiveSupport::Notifications.monotonic_subscribe('render') do |name, start, finish, id, payload|
44
54
  # name # => String, name of the event (such as 'render' from above)
45
- # start # => Monotonic time, when the instrumented block started execution
46
- # finish # => Monotonic time, when the instrumented block ended execution
55
+ # start # => Float, monotonic time when the instrumented block started execution
56
+ # finish # => Float, monotonic time when the instrumented block ended execution
47
57
  # id # => String, unique ID for the instrumenter that fired the event
48
58
  # payload # => Hash, the payload
49
59
  # end
50
60
  #
51
- # The +start+ and +finish+ values above represent monotonic time.
52
- #
53
61
  # For instance, let's store all "render" events in an array:
54
62
  #
55
63
  # events = []
56
64
  #
57
- # ActiveSupport::Notifications.subscribe('render') do |*args|
58
- # events << ActiveSupport::Notifications::Event.new(*args)
65
+ # ActiveSupport::Notifications.subscribe('render') do |event|
66
+ # events << event
59
67
  # end
60
68
  #
61
69
  # That code returns right away, you are just subscribing to "render" events.
@@ -66,14 +74,10 @@ module ActiveSupport
66
74
  # end
67
75
  #
68
76
  # event = events.first
69
- # event.name # => "render"
70
- # event.duration # => 10 (in milliseconds)
71
- # event.payload # => { extra: :information }
72
- #
73
- # The block in the <tt>subscribe</tt> call gets the name of the event, start
74
- # timestamp, end timestamp, a string with a unique identifier for that event's instrumenter
75
- # (something like "535801666f04d0298cd6"), and a hash with the payload, in
76
- # that order.
77
+ # event.name # => "render"
78
+ # event.duration # => 10 (in milliseconds)
79
+ # event.payload # => { extra: :information }
80
+ # event.allocations # => 1826 (objects)
77
81
  #
78
82
  # If an exception happens during that particular instrumentation the payload will
79
83
  # have a key <tt>:exception</tt> with an array of two elements as value: a string with
@@ -138,7 +142,7 @@ module ActiveSupport
138
142
  # You can subscribe to some event temporarily while some block runs. For
139
143
  # example, in
140
144
  #
141
- # callback = lambda {|*args| ... }
145
+ # callback = lambda {|event| ... }
142
146
  # ActiveSupport::Notifications.subscribed(callback, "sql.active_record") do
143
147
  # ...
144
148
  # end
@@ -161,7 +165,7 @@ module ActiveSupport
161
165
  #
162
166
  # The +subscribe+ method returns a subscriber object:
163
167
  #
164
- # subscriber = ActiveSupport::Notifications.subscribe("render") do |*args|
168
+ # subscriber = ActiveSupport::Notifications.subscribe("render") do |event|
165
169
  # ...
166
170
  # end
167
171
  #
@@ -214,11 +218,15 @@ module ActiveSupport
214
218
  # You can subscribe to events by passing a String to match exact event
215
219
  # names, or by passing a Regexp to match all events that match a pattern.
216
220
  #
217
- # ActiveSupport::Notifications.subscribe(/render/) do |*args|
218
- # @event = ActiveSupport::Notifications::Event.new(*args)
221
+ # If the block passed to the method only takes one argument,
222
+ # it will yield an +Event+ object to the block:
223
+ #
224
+ # ActiveSupport::Notifications.subscribe(/render/) do |event|
225
+ # @event = event
219
226
  # end
220
227
  #
221
- # The +block+ will receive five parameters with information about the event:
228
+ # Otherwise the +block+ will receive five arguments with information
229
+ # about the event:
222
230
  #
223
231
  # ActiveSupport::Notifications.subscribe('render') do |name, start, finish, id, payload|
224
232
  # name # => String, name of the event (such as 'render' from above)
@@ -228,16 +236,9 @@ module ActiveSupport
228
236
  # payload # => Hash, the payload
229
237
  # end
230
238
  #
231
- # If the block passed to the method only takes one parameter,
232
- # it will yield an event object to the block:
233
- #
234
- # ActiveSupport::Notifications.subscribe(/render/) do |event|
235
- # @event = event
236
- # end
237
- #
238
239
  # Raises an error if invalid event name type is passed:
239
240
  #
240
- # ActiveSupport::Notifications.subscribe(:render) {|*args| ...}
241
+ # ActiveSupport::Notifications.subscribe(:render) {|event| ...}
241
242
  # #=> ArgumentError (pattern must be specified as a String, Regexp or empty)
242
243
  #
243
244
  def subscribe(pattern = nil, callback = nil, &block)
@@ -164,11 +164,11 @@ module ActiveSupport
164
164
  end
165
165
 
166
166
  def translate_number_value_with_default(key, **i18n_options)
167
- I18n.translate(key, **{ default: default_value(key), scope: :number }.merge!(i18n_options))
167
+ I18n.translate(key, default: default_value(key), scope: :number, **i18n_options)
168
168
  end
169
169
 
170
170
  def translate_in_locale(key, **i18n_options)
171
- translate_number_value_with_default(key, **{ locale: options[:locale] }.merge(i18n_options))
171
+ translate_number_value_with_default(key, locale: options[:locale], **i18n_options)
172
172
  end
173
173
 
174
174
  def default_value(key)
@@ -31,8 +31,8 @@ module ActiveSupport
31
31
  end
32
32
  end
33
33
 
34
- def respond_to_missing?(*arguments)
35
- @context.respond_to?(*arguments)
34
+ def respond_to_missing?(...)
35
+ @context.respond_to?(...)
36
36
  end
37
37
  end
38
38
  end