activesupport 7.1.5.2 → 8.0.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +64 -1234
- data/lib/active_support/array_inquirer.rb +1 -1
- data/lib/active_support/backtrace_cleaner.rb +10 -3
- data/lib/active_support/benchmark.rb +21 -0
- data/lib/active_support/benchmarkable.rb +3 -2
- data/lib/active_support/broadcast_logger.rb +4 -4
- data/lib/active_support/cache/file_store.rb +27 -12
- data/lib/active_support/cache/mem_cache_store.rb +16 -74
- data/lib/active_support/cache/memory_store.rb +8 -3
- data/lib/active_support/cache/redis_cache_store.rb +21 -15
- data/lib/active_support/cache/serializer_with_fallback.rb +0 -23
- data/lib/active_support/cache.rb +74 -77
- data/lib/active_support/callbacks.rb +75 -115
- data/lib/active_support/class_attribute.rb +26 -0
- data/lib/active_support/code_generator.rb +9 -0
- data/lib/active_support/concurrency/share_lock.rb +0 -1
- data/lib/active_support/configuration_file.rb +15 -6
- data/lib/active_support/core_ext/array/conversions.rb +0 -2
- data/lib/active_support/core_ext/benchmark.rb +6 -9
- data/lib/active_support/core_ext/class/attribute.rb +10 -19
- data/lib/active_support/core_ext/class/subclasses.rb +15 -35
- data/lib/active_support/core_ext/date/blank.rb +4 -0
- data/lib/active_support/core_ext/date/conversions.rb +2 -2
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +28 -1
- data/lib/active_support/core_ext/date_time/blank.rb +4 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +0 -4
- data/lib/active_support/core_ext/digest/uuid.rb +6 -0
- data/lib/active_support/core_ext/enumerable.rb +8 -3
- data/lib/active_support/core_ext/erb/util.rb +5 -0
- data/lib/active_support/core_ext/hash/except.rb +0 -12
- data/lib/active_support/core_ext/hash/keys.rb +4 -4
- data/lib/active_support/core_ext/module/attr_internal.rb +16 -6
- data/lib/active_support/core_ext/module/delegation.rb +20 -163
- data/lib/active_support/core_ext/module/deprecation.rb +1 -4
- data/lib/active_support/core_ext/numeric/conversions.rb +3 -3
- data/lib/active_support/core_ext/object/blank.rb +45 -1
- data/lib/active_support/core_ext/object/instance_variables.rb +11 -19
- data/lib/active_support/core_ext/object/json.rb +16 -10
- data/lib/active_support/core_ext/object/with.rb +5 -3
- data/lib/active_support/core_ext/pathname/blank.rb +4 -0
- data/lib/active_support/core_ext/range/overlap.rb +1 -1
- data/lib/active_support/core_ext/securerandom.rb +8 -24
- data/lib/active_support/core_ext/string/conversions.rb +1 -1
- data/lib/active_support/core_ext/string/filters.rb +1 -1
- data/lib/active_support/core_ext/string/multibyte.rb +1 -1
- data/lib/active_support/core_ext/string/output_safety.rb +0 -7
- data/lib/active_support/core_ext/thread/backtrace/location.rb +2 -7
- data/lib/active_support/core_ext/time/calculations.rb +32 -30
- data/lib/active_support/core_ext/time/compatibility.rb +24 -0
- data/lib/active_support/core_ext/time/conversions.rb +2 -2
- data/lib/active_support/core_ext/time/zones.rb +1 -1
- data/lib/active_support/core_ext.rb +0 -1
- data/lib/active_support/current_attributes.rb +38 -40
- data/lib/active_support/delegation.rb +200 -0
- data/lib/active_support/dependencies/autoload.rb +0 -12
- data/lib/active_support/dependencies.rb +0 -1
- data/lib/active_support/deprecation/constant_accessor.rb +47 -26
- data/lib/active_support/deprecation/proxy_wrappers.rb +9 -12
- data/lib/active_support/deprecation/reporting.rb +1 -15
- data/lib/active_support/deprecation.rb +8 -5
- data/lib/active_support/descendants_tracker.rb +9 -87
- data/lib/active_support/duration/iso8601_parser.rb +2 -2
- data/lib/active_support/duration/iso8601_serializer.rb +1 -2
- data/lib/active_support/duration.rb +25 -16
- data/lib/active_support/encrypted_configuration.rb +20 -2
- data/lib/active_support/encrypted_file.rb +1 -1
- data/lib/active_support/error_reporter.rb +65 -3
- data/lib/active_support/evented_file_update_checker.rb +0 -2
- data/lib/active_support/execution_wrapper.rb +0 -1
- data/lib/active_support/file_update_checker.rb +1 -1
- data/lib/active_support/fork_tracker.rb +2 -38
- data/lib/active_support/gem_version.rb +4 -4
- data/lib/active_support/hash_with_indifferent_access.rb +21 -23
- data/lib/active_support/html_safe_translation.rb +3 -0
- data/lib/active_support/i18n_railtie.rb +19 -11
- data/lib/active_support/isolated_execution_state.rb +0 -2
- data/lib/active_support/json/encoding.rb +2 -2
- data/lib/active_support/log_subscriber.rb +0 -12
- data/lib/active_support/logger.rb +15 -2
- data/lib/active_support/logger_thread_safe_level.rb +0 -8
- data/lib/active_support/message_pack/extensions.rb +15 -2
- data/lib/active_support/message_verifier.rb +12 -0
- data/lib/active_support/multibyte/chars.rb +2 -2
- data/lib/active_support/notifications/fanout.rb +4 -8
- data/lib/active_support/notifications/instrumenter.rb +21 -18
- data/lib/active_support/notifications.rb +28 -27
- data/lib/active_support/number_helper/number_converter.rb +2 -2
- data/lib/active_support/number_helper.rb +22 -0
- data/lib/active_support/option_merger.rb +2 -2
- data/lib/active_support/ordered_options.rb +53 -15
- data/lib/active_support/railtie.rb +8 -11
- data/lib/active_support/string_inquirer.rb +1 -1
- data/lib/active_support/subscriber.rb +1 -0
- data/lib/active_support/tagged_logging.rb +5 -1
- data/lib/active_support/test_case.rb +3 -1
- data/lib/active_support/testing/assertions.rb +79 -21
- data/lib/active_support/testing/constant_stubbing.rb +30 -8
- data/lib/active_support/testing/deprecation.rb +5 -12
- data/lib/active_support/testing/isolation.rb +19 -9
- data/lib/active_support/testing/method_call_assertions.rb +2 -16
- data/lib/active_support/testing/parallelization/server.rb +3 -0
- data/lib/active_support/testing/strict_warnings.rb +8 -4
- data/lib/active_support/testing/tests_without_assertions.rb +19 -0
- data/lib/active_support/testing/time_helpers.rb +4 -3
- data/lib/active_support/time_with_zone.rb +29 -16
- data/lib/active_support/values/time_zone.rb +18 -16
- data/lib/active_support/xml_mini.rb +11 -2
- data/lib/active_support.rb +11 -3
- metadata +32 -22
- data/lib/active_support/deprecation/instance_delegator.rb +0 -65
- data/lib/active_support/proxy_object.rb +0 -17
- data/lib/active_support/ruby_features.rb +0 -7
|
@@ -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,
|
|
63
|
-
result = @wrapped_string.__send__(method,
|
|
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,8 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "mutex_m"
|
|
4
3
|
require "concurrent/map"
|
|
5
|
-
require "set"
|
|
6
4
|
require "active_support/core_ext/object/try"
|
|
7
5
|
|
|
8
6
|
module ActiveSupport
|
|
@@ -49,15 +47,13 @@ module ActiveSupport
|
|
|
49
47
|
#
|
|
50
48
|
# This class is thread safe. All methods are reentrant.
|
|
51
49
|
class Fanout
|
|
52
|
-
include Mutex_m
|
|
53
|
-
|
|
54
50
|
def initialize
|
|
51
|
+
@mutex = Mutex.new
|
|
55
52
|
@string_subscribers = Concurrent::Map.new { |h, k| h.compute_if_absent(k) { [] } }
|
|
56
53
|
@other_subscribers = []
|
|
57
54
|
@all_listeners_for = Concurrent::Map.new
|
|
58
55
|
@groups_for = Concurrent::Map.new
|
|
59
56
|
@silenceable_groups_for = Concurrent::Map.new
|
|
60
|
-
super
|
|
61
57
|
end
|
|
62
58
|
|
|
63
59
|
def inspect # :nodoc:
|
|
@@ -67,7 +63,7 @@ module ActiveSupport
|
|
|
67
63
|
|
|
68
64
|
def subscribe(pattern = nil, callable = nil, monotonic: false, &block)
|
|
69
65
|
subscriber = Subscribers.new(pattern, callable || block, monotonic)
|
|
70
|
-
synchronize do
|
|
66
|
+
@mutex.synchronize do
|
|
71
67
|
case pattern
|
|
72
68
|
when String
|
|
73
69
|
@string_subscribers[pattern] << subscriber
|
|
@@ -83,7 +79,7 @@ module ActiveSupport
|
|
|
83
79
|
end
|
|
84
80
|
|
|
85
81
|
def unsubscribe(subscriber_or_name)
|
|
86
|
-
synchronize do
|
|
82
|
+
@mutex.synchronize do
|
|
87
83
|
case subscriber_or_name
|
|
88
84
|
when String
|
|
89
85
|
@string_subscribers[subscriber_or_name].clear
|
|
@@ -300,7 +296,7 @@ module ActiveSupport
|
|
|
300
296
|
|
|
301
297
|
def all_listeners_for(name)
|
|
302
298
|
# this is correctly done double-checked locking (Concurrent::Map's lookups have volatile semantics)
|
|
303
|
-
@all_listeners_for[name] || synchronize do
|
|
299
|
+
@all_listeners_for[name] || @mutex.synchronize do
|
|
304
300
|
# use synchronisation when accessing @subscribers
|
|
305
301
|
@all_listeners_for[name] ||=
|
|
306
302
|
@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
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
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
|
|
197
|
-
# @event =
|
|
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
|
|
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 # =>
|
|
46
|
-
# finish # =>
|
|
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
|
|
58
|
-
# events <<
|
|
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
|
|
70
|
-
# event.duration
|
|
71
|
-
# event.payload
|
|
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 {
|
|
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
|
|
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
|
-
#
|
|
218
|
-
#
|
|
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
|
-
#
|
|
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) {
|
|
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,
|
|
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,
|
|
171
|
+
translate_number_value_with_default(key, locale: options[:locale], **i18n_options)
|
|
172
172
|
end
|
|
173
173
|
|
|
174
174
|
def default_value(key)
|
|
@@ -1,6 +1,28 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module ActiveSupport
|
|
4
|
+
# = Number Helper
|
|
5
|
+
#
|
|
6
|
+
# Provides methods for formatting numbers into currencies, percentages,
|
|
7
|
+
# phone numbers, and more.
|
|
8
|
+
#
|
|
9
|
+
# Example usage in a class:
|
|
10
|
+
# class Topic
|
|
11
|
+
# include ActiveSupport::NumberHelper
|
|
12
|
+
#
|
|
13
|
+
# def price
|
|
14
|
+
# number_to_currency(@price)
|
|
15
|
+
# end
|
|
16
|
+
# end
|
|
17
|
+
#
|
|
18
|
+
# Example usage in a module:
|
|
19
|
+
# require "active_support/number_helper"
|
|
20
|
+
#
|
|
21
|
+
# module NumberFormatting
|
|
22
|
+
# def format_price(price)
|
|
23
|
+
# ActiveSupport::NumberHelper.number_to_currency(price)
|
|
24
|
+
# end
|
|
25
|
+
# end
|
|
4
26
|
module NumberHelper
|
|
5
27
|
extend ActiveSupport::Autoload
|
|
6
28
|
|
|
@@ -46,18 +46,14 @@ module ActiveSupport
|
|
|
46
46
|
super(key.to_sym, *identifiers)
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
-
def method_missing(
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
def method_missing(method, *args)
|
|
50
|
+
if method.end_with?("=")
|
|
51
|
+
self[method.name.chomp("=")] = args.first
|
|
52
|
+
elsif method.end_with?("!")
|
|
53
|
+
name_string = method.name.chomp("!")
|
|
54
|
+
self[name_string].presence || raise(KeyError.new(":#{name_string} is blank"))
|
|
53
55
|
else
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if bangs
|
|
57
|
-
self[name_string].presence || raise(KeyError.new(":#{name_string} is blank"))
|
|
58
|
-
else
|
|
59
|
-
self[name_string]
|
|
60
|
-
end
|
|
56
|
+
self[method.name]
|
|
61
57
|
end
|
|
62
58
|
end
|
|
63
59
|
|
|
@@ -92,18 +88,60 @@ module ActiveSupport
|
|
|
92
88
|
# h.boy # => 'John'
|
|
93
89
|
class InheritableOptions < OrderedOptions
|
|
94
90
|
def initialize(parent = nil)
|
|
95
|
-
|
|
91
|
+
@parent = parent
|
|
92
|
+
if @parent.kind_of?(OrderedOptions)
|
|
96
93
|
# use the faster _get when dealing with OrderedOptions
|
|
97
|
-
super() { |h, k| parent._get(k) }
|
|
98
|
-
elsif parent
|
|
99
|
-
super() { |h, k| parent[k] }
|
|
94
|
+
super() { |h, k| @parent._get(k) }
|
|
95
|
+
elsif @parent
|
|
96
|
+
super() { |h, k| @parent[k] }
|
|
100
97
|
else
|
|
101
98
|
super()
|
|
99
|
+
@parent = {}
|
|
102
100
|
end
|
|
103
101
|
end
|
|
104
102
|
|
|
103
|
+
def to_h
|
|
104
|
+
@parent.merge(self)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def ==(other)
|
|
108
|
+
to_h == other.to_h
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def inspect
|
|
112
|
+
"#<#{self.class.name} #{to_h.inspect}>"
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def to_s
|
|
116
|
+
to_h.to_s
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def pretty_print(pp)
|
|
120
|
+
pp.pp_hash(to_h)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
alias_method :own_key?, :key?
|
|
124
|
+
private :own_key?
|
|
125
|
+
|
|
126
|
+
def key?(key)
|
|
127
|
+
super || @parent.key?(key)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def overridden?(key)
|
|
131
|
+
!!(@parent && @parent.key?(key) && own_key?(key.to_sym))
|
|
132
|
+
end
|
|
133
|
+
|
|
105
134
|
def inheritable_copy
|
|
106
135
|
self.class.new(self)
|
|
107
136
|
end
|
|
137
|
+
|
|
138
|
+
def to_a
|
|
139
|
+
entries
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def each(&block)
|
|
143
|
+
to_h.each(&block)
|
|
144
|
+
self
|
|
145
|
+
end
|
|
108
146
|
end
|
|
109
147
|
end
|
|
@@ -89,10 +89,15 @@ module ActiveSupport
|
|
|
89
89
|
begin
|
|
90
90
|
TZInfo::DataSource.get
|
|
91
91
|
rescue TZInfo::DataSourceNotFound => e
|
|
92
|
-
raise e.exception
|
|
92
|
+
raise e.exception('tzinfo-data is not present. Please add gem "tzinfo-data" to your Gemfile and run bundle install')
|
|
93
93
|
end
|
|
94
94
|
require "active_support/core_ext/time/zones"
|
|
95
95
|
Time.zone_default = Time.find_zone!(app.config.time_zone)
|
|
96
|
+
config.eager_load_namespaces << TZInfo
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
initializer "active_support.to_time_preserves_timezone" do |app|
|
|
100
|
+
ActiveSupport.to_time_preserves_timezone = app.config.active_support.to_time_preserves_timezone
|
|
96
101
|
end
|
|
97
102
|
|
|
98
103
|
# Sets the default week start
|
|
@@ -117,16 +122,8 @@ module ActiveSupport
|
|
|
117
122
|
|
|
118
123
|
initializer "active_support.set_configs" do |app|
|
|
119
124
|
app.config.active_support.each do |k, v|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
elsif k == :remove_deprecated_time_with_zone_name
|
|
123
|
-
ActiveSupport.deprecator.warn("config.active_support.remove_deprecated_time_with_zone_name is deprecated and will be removed in Rails 7.2.")
|
|
124
|
-
elsif k == :use_rfc4122_namespaced_uuids
|
|
125
|
-
ActiveSupport.deprecator.warn("config.active_support.use_rfc4122_namespaced_uuids is deprecated and will be removed in Rails 7.2.")
|
|
126
|
-
else
|
|
127
|
-
k = "#{k}="
|
|
128
|
-
ActiveSupport.public_send(k, v) if ActiveSupport.respond_to? k
|
|
129
|
-
end
|
|
125
|
+
k = "#{k}="
|
|
126
|
+
ActiveSupport.public_send(k, v) if ActiveSupport.respond_to? k
|
|
130
127
|
end
|
|
131
128
|
end
|
|
132
129
|
|
|
@@ -67,6 +67,7 @@ module ActiveSupport
|
|
|
67
67
|
|
|
68
68
|
# Adds event subscribers for all new methods added to the class.
|
|
69
69
|
def method_added(event)
|
|
70
|
+
super
|
|
70
71
|
# Only public methods are added as subscribers, and only if a notifier
|
|
71
72
|
# has been set up. This means that subscribers will only be set up for
|
|
72
73
|
# classes that call #attach_to.
|
|
@@ -2,7 +2,6 @@
|
|
|
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
|
|
@@ -114,6 +113,11 @@ module ActiveSupport
|
|
|
114
113
|
end
|
|
115
114
|
end
|
|
116
115
|
|
|
116
|
+
# Returns an `ActiveSupport::Logger` that has already been wrapped with tagged logging concern.
|
|
117
|
+
def self.logger(*args, **kwargs)
|
|
118
|
+
new ActiveSupport::Logger.new(*args, **kwargs)
|
|
119
|
+
end
|
|
120
|
+
|
|
117
121
|
def self.new(logger)
|
|
118
122
|
logger = logger.clone
|
|
119
123
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require "minitest"
|
|
4
4
|
require "active_support/testing/tagged_logging"
|
|
5
5
|
require "active_support/testing/setup_and_teardown"
|
|
6
|
+
require "active_support/testing/tests_without_assertions"
|
|
6
7
|
require "active_support/testing/assertions"
|
|
7
8
|
require "active_support/testing/error_reporter_assertions"
|
|
8
9
|
require "active_support/testing/deprecation"
|
|
@@ -78,7 +79,7 @@ module ActiveSupport
|
|
|
78
79
|
# number of tests to run is above the +threshold+ param. The default value is
|
|
79
80
|
# 50, and it's configurable via +config.active_support.test_parallelization_threshold+.
|
|
80
81
|
def parallelize(workers: :number_of_processors, with: :processes, threshold: ActiveSupport.test_parallelization_threshold)
|
|
81
|
-
workers = Concurrent.
|
|
82
|
+
workers = Concurrent.processor_count if workers == :number_of_processors
|
|
82
83
|
workers = ENV["PARALLEL_WORKERS"].to_i if ENV["PARALLEL_WORKERS"]
|
|
83
84
|
|
|
84
85
|
Minitest.parallel_executor = ActiveSupport::Testing::ParallelizeExecutor.new(size: workers, with: with, threshold: threshold)
|
|
@@ -142,6 +143,7 @@ module ActiveSupport
|
|
|
142
143
|
|
|
143
144
|
include ActiveSupport::Testing::TaggedLogging
|
|
144
145
|
prepend ActiveSupport::Testing::SetupAndTeardown
|
|
146
|
+
prepend ActiveSupport::Testing::TestsWithoutAssertions
|
|
145
147
|
include ActiveSupport::Testing::Assertions
|
|
146
148
|
include ActiveSupport::Testing::ErrorReporterAssertions
|
|
147
149
|
include ActiveSupport::Testing::Deprecation
|
|
@@ -19,7 +19,7 @@ module ActiveSupport
|
|
|
19
19
|
#
|
|
20
20
|
# assert_not foo, 'foo should be false'
|
|
21
21
|
def assert_not(object, message = nil)
|
|
22
|
-
message ||= "Expected #{mu_pp(object)} to be nil or false"
|
|
22
|
+
message ||= -> { "Expected #{mu_pp(object)} to be nil or false" }
|
|
23
23
|
assert !object, message
|
|
24
24
|
end
|
|
25
25
|
|
|
@@ -118,9 +118,13 @@ module ActiveSupport
|
|
|
118
118
|
|
|
119
119
|
expressions.zip(exps, before) do |(code, diff), exp, before_value|
|
|
120
120
|
actual = exp.call
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
121
|
+
rich_message = -> do
|
|
122
|
+
code_string = code.respond_to?(:call) ? _callable_to_source_string(code) : code
|
|
123
|
+
error = "`#{code_string}` didn't change by #{diff}, but by #{actual - before_value}"
|
|
124
|
+
error = "#{message}.\n#{error}" if message
|
|
125
|
+
error
|
|
126
|
+
end
|
|
127
|
+
assert_equal(before_value + diff, actual, rich_message)
|
|
124
128
|
end
|
|
125
129
|
|
|
126
130
|
retval
|
|
@@ -195,22 +199,32 @@ module ActiveSupport
|
|
|
195
199
|
retval = _assert_nothing_raised_or_warn("assert_changes", &block)
|
|
196
200
|
|
|
197
201
|
unless from == UNTRACKED
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
202
|
+
rich_message = -> do
|
|
203
|
+
error = "Expected change from #{from.inspect}, got #{before.inspect}"
|
|
204
|
+
error = "#{message}.\n#{error}" if message
|
|
205
|
+
error
|
|
206
|
+
end
|
|
207
|
+
assert from === before, rich_message
|
|
201
208
|
end
|
|
202
209
|
|
|
203
210
|
after = exp.call
|
|
204
211
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
212
|
+
rich_message = -> do
|
|
213
|
+
code_string = expression.respond_to?(:call) ? _callable_to_source_string(expression) : expression
|
|
214
|
+
error = "`#{code_string}` didn't change"
|
|
215
|
+
error = "#{error}. It was already #{to.inspect}" if before == to
|
|
216
|
+
error = "#{message}.\n#{error}" if message
|
|
217
|
+
error
|
|
218
|
+
end
|
|
219
|
+
refute_equal before, after, rich_message
|
|
209
220
|
|
|
210
221
|
unless to == UNTRACKED
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
222
|
+
rich_message = -> do
|
|
223
|
+
error = "Expected change to #{to.inspect}, got #{after.inspect}\n"
|
|
224
|
+
error = "#{message}.\n#{error}" if message
|
|
225
|
+
error
|
|
226
|
+
end
|
|
227
|
+
assert to === after, rich_message
|
|
214
228
|
end
|
|
215
229
|
|
|
216
230
|
retval
|
|
@@ -242,20 +256,27 @@ module ActiveSupport
|
|
|
242
256
|
retval = _assert_nothing_raised_or_warn("assert_no_changes", &block)
|
|
243
257
|
|
|
244
258
|
unless from == UNTRACKED
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
259
|
+
rich_message = -> do
|
|
260
|
+
error = "Expected initial value of #{from.inspect}, got #{before.inspect}"
|
|
261
|
+
error = "#{message}.\n#{error}" if message
|
|
262
|
+
error
|
|
263
|
+
end
|
|
264
|
+
assert from === before, rich_message
|
|
248
265
|
end
|
|
249
266
|
|
|
250
267
|
after = exp.call
|
|
251
268
|
|
|
252
|
-
|
|
253
|
-
|
|
269
|
+
rich_message = -> do
|
|
270
|
+
code_string = expression.respond_to?(:call) ? _callable_to_source_string(expression) : expression
|
|
271
|
+
error = "`#{code_string}` changed"
|
|
272
|
+
error = "#{message}.\n#{error}" if message
|
|
273
|
+
error
|
|
274
|
+
end
|
|
254
275
|
|
|
255
276
|
if before.nil?
|
|
256
|
-
assert_nil after,
|
|
277
|
+
assert_nil after, rich_message
|
|
257
278
|
else
|
|
258
|
-
assert_equal before, after,
|
|
279
|
+
assert_equal before, after, rich_message
|
|
259
280
|
end
|
|
260
281
|
|
|
261
282
|
retval
|
|
@@ -276,6 +297,43 @@ module ActiveSupport
|
|
|
276
297
|
|
|
277
298
|
raise
|
|
278
299
|
end
|
|
300
|
+
|
|
301
|
+
def _callable_to_source_string(callable)
|
|
302
|
+
if defined?(RubyVM::InstructionSequence) && callable.is_a?(Proc)
|
|
303
|
+
iseq = RubyVM::InstructionSequence.of(callable)
|
|
304
|
+
source =
|
|
305
|
+
if iseq.script_lines
|
|
306
|
+
iseq.script_lines.join("\n")
|
|
307
|
+
elsif File.readable?(iseq.absolute_path)
|
|
308
|
+
File.read(iseq.absolute_path)
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
return callable unless source
|
|
312
|
+
|
|
313
|
+
location = iseq.to_a[4][:code_location]
|
|
314
|
+
return callable unless location
|
|
315
|
+
|
|
316
|
+
lines = source.lines[(location[0] - 1)..(location[2] - 1)]
|
|
317
|
+
lines[-1] = lines[-1].byteslice(...location[3])
|
|
318
|
+
lines[0] = lines[0].byteslice(location[1]...)
|
|
319
|
+
source = lines.join.strip
|
|
320
|
+
|
|
321
|
+
# We ignore procs defined with do/end as they are likely multi-line anyway.
|
|
322
|
+
if source.start_with?("{")
|
|
323
|
+
source.delete_suffix!("}")
|
|
324
|
+
source.delete_prefix!("{")
|
|
325
|
+
source.strip!
|
|
326
|
+
# It won't read nice if the callable contains multiple
|
|
327
|
+
# lines, and it should be a rare occurrence anyway.
|
|
328
|
+
# Same if it takes arguments.
|
|
329
|
+
if !source.include?("\n") && !source.start_with?("|")
|
|
330
|
+
return source
|
|
331
|
+
end
|
|
332
|
+
end
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
callable
|
|
336
|
+
end
|
|
279
337
|
end
|
|
280
338
|
end
|
|
281
339
|
end
|