activesupport 7.2.3 → 8.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +72 -347
- data/README.rdoc +1 -1
- data/lib/active_support/backtrace_cleaner.rb +2 -2
- data/lib/active_support/benchmark.rb +21 -0
- data/lib/active_support/benchmarkable.rb +3 -2
- data/lib/active_support/broadcast_logger.rb +74 -61
- data/lib/active_support/cache/file_store.rb +14 -4
- data/lib/active_support/cache/mem_cache_store.rb +15 -13
- data/lib/active_support/cache/memory_store.rb +9 -5
- data/lib/active_support/cache/null_store.rb +2 -2
- data/lib/active_support/cache/redis_cache_store.rb +6 -3
- data/lib/active_support/cache/strategy/local_cache.rb +20 -56
- data/lib/active_support/cache.rb +19 -14
- data/lib/active_support/callbacks.rb +7 -6
- data/lib/active_support/class_attribute.rb +33 -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 +3 -3
- data/lib/active_support/core_ext/benchmark.rb +6 -10
- data/lib/active_support/core_ext/class/attribute.rb +22 -18
- data/lib/active_support/core_ext/date/conversions.rb +2 -0
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +2 -2
- data/lib/active_support/core_ext/date_time/conversions.rb +2 -4
- data/lib/active_support/core_ext/enumerable.rb +13 -20
- data/lib/active_support/core_ext/hash/except.rb +0 -12
- data/lib/active_support/core_ext/module/attr_internal.rb +3 -4
- data/lib/active_support/core_ext/module/introspection.rb +0 -3
- data/lib/active_support/core_ext/object/json.rb +15 -9
- data/lib/active_support/core_ext/object/try.rb +2 -2
- data/lib/active_support/core_ext/range.rb +0 -1
- data/lib/active_support/core_ext/string/filters.rb +3 -3
- data/lib/active_support/core_ext/string/multibyte.rb +2 -2
- data/lib/active_support/core_ext/thread/backtrace/location.rb +2 -7
- data/lib/active_support/core_ext/time/calculations.rb +14 -2
- data/lib/active_support/core_ext/time/conversions.rb +2 -0
- data/lib/active_support/current_attributes.rb +7 -14
- data/lib/active_support/delegation.rb +0 -2
- data/lib/active_support/dependencies.rb +0 -1
- data/lib/active_support/deprecation/reporting.rb +0 -19
- data/lib/active_support/deprecation.rb +1 -1
- data/lib/active_support/duration.rb +14 -10
- data/lib/active_support/encrypted_configuration.rb +20 -2
- data/lib/active_support/error_reporter.rb +27 -6
- data/lib/active_support/evented_file_update_checker.rb +0 -1
- data/lib/active_support/execution_wrapper.rb +1 -1
- data/lib/active_support/file_update_checker.rb +1 -1
- data/lib/active_support/gem_version.rb +3 -3
- data/lib/active_support/hash_with_indifferent_access.rb +31 -35
- data/lib/active_support/i18n_railtie.rb +19 -11
- data/lib/active_support/isolated_execution_state.rb +0 -2
- data/lib/active_support/json/decoding.rb +1 -1
- data/lib/active_support/json/encoding.rb +7 -25
- data/lib/active_support/lazy_load_hooks.rb +1 -1
- data/lib/active_support/message_encryptors.rb +2 -2
- data/lib/active_support/message_verifier.rb +0 -9
- data/lib/active_support/message_verifiers.rb +3 -5
- data/lib/active_support/messages/rotator.rb +0 -5
- data/lib/active_support/multibyte/chars.rb +1 -4
- data/lib/active_support/notifications/fanout.rb +0 -1
- data/lib/active_support/number_helper.rb +22 -0
- data/lib/active_support/railtie.rb +4 -0
- data/lib/active_support/tagged_logging.rb +5 -0
- data/lib/active_support/testing/assertions.rb +79 -21
- data/lib/active_support/testing/isolation.rb +0 -2
- data/lib/active_support/testing/parallelization/server.rb +2 -15
- data/lib/active_support/testing/parallelization/worker.rb +2 -2
- data/lib/active_support/testing/parallelization.rb +1 -12
- data/lib/active_support/testing/strict_warnings.rb +43 -0
- data/lib/active_support/testing/time_helpers.rb +2 -1
- data/lib/active_support/time_with_zone.rb +22 -13
- data/lib/active_support/values/time_zone.rb +11 -9
- data/lib/active_support/xml_mini.rb +0 -2
- data/lib/active_support.rb +10 -3
- metadata +27 -9
- data/lib/active_support/core_ext/range/sole.rb +0 -17
- data/lib/active_support/proxy_object.rb +0 -20
|
@@ -19,11 +19,20 @@ module ActiveSupport
|
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def parse(context: nil, **options)
|
|
22
|
-
source = render(context)
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
source = @content.include?("<%") ? render(context) : @content
|
|
23
|
+
|
|
24
|
+
if source == @content
|
|
25
|
+
if YAML.respond_to?(:unsafe_load)
|
|
26
|
+
YAML.unsafe_load_file(@content_path, **options) || {}
|
|
27
|
+
else
|
|
28
|
+
YAML.load_file(@content_path, **options) || {}
|
|
29
|
+
end
|
|
25
30
|
else
|
|
26
|
-
YAML.
|
|
31
|
+
if YAML.respond_to?(:unsafe_load)
|
|
32
|
+
YAML.unsafe_load(source, **options) || {}
|
|
33
|
+
else
|
|
34
|
+
YAML.load(source, **options) || {}
|
|
35
|
+
end
|
|
27
36
|
end
|
|
28
37
|
rescue Psych::SyntaxError => error
|
|
29
38
|
raise "YAML syntax error occurred while parsing #{@content_path}. " \
|
|
@@ -33,8 +42,7 @@ module ActiveSupport
|
|
|
33
42
|
|
|
34
43
|
private
|
|
35
44
|
def read(content_path)
|
|
36
|
-
require "yaml"
|
|
37
|
-
require "erb"
|
|
45
|
+
require "yaml" unless defined?(YAML)
|
|
38
46
|
|
|
39
47
|
File.read(content_path).tap do |content|
|
|
40
48
|
if content.include?("\u00A0")
|
|
@@ -44,6 +52,7 @@ module ActiveSupport
|
|
|
44
52
|
end
|
|
45
53
|
|
|
46
54
|
def render(context)
|
|
55
|
+
require "erb" unless defined?(ERB)
|
|
47
56
|
erb = ERB.new(@content).tap { |e| e.filename = @content_path }
|
|
48
57
|
context ? erb.result(context) : erb.result
|
|
49
58
|
end
|
|
@@ -16,11 +16,11 @@ class Array
|
|
|
16
16
|
# ==== Options
|
|
17
17
|
#
|
|
18
18
|
# * <tt>:words_connector</tt> - The sign or word used to join all but the last
|
|
19
|
-
# element in arrays with three or more elements (default: ", ").
|
|
19
|
+
# element in arrays with three or more elements (default: <tt>", "</tt>).
|
|
20
20
|
# * <tt>:last_word_connector</tt> - The sign or word used to join the last element
|
|
21
|
-
# in arrays with three or more elements (default: ", and ").
|
|
21
|
+
# in arrays with three or more elements (default: <tt>", and "</tt>).
|
|
22
22
|
# * <tt>:two_words_connector</tt> - The sign or word used to join the elements
|
|
23
|
-
# in arrays with two elements (default: " and ").
|
|
23
|
+
# in arrays with two elements (default: <tt>" and "</tt>).
|
|
24
24
|
# * <tt>:locale</tt> - If +i18n+ is available, you can set a locale and use
|
|
25
25
|
# the connector options defined on the 'support.array' namespace in the
|
|
26
26
|
# corresponding dictionary file.
|
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "benchmark"
|
|
4
|
-
return if Benchmark.respond_to?(:ms)
|
|
5
4
|
|
|
6
5
|
class << Benchmark
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
# # => 0.074
|
|
14
|
-
def ms(&block)
|
|
15
|
-
1000 * realtime(&block)
|
|
6
|
+
def ms(&block) # :nodoc
|
|
7
|
+
# NOTE: Please also remove the Active Support `benchmark` dependency when removing this
|
|
8
|
+
ActiveSupport.deprecator.warn <<~TEXT
|
|
9
|
+
`Benchmark.ms` is deprecated and will be removed in Rails 8.1 without replacement.
|
|
10
|
+
TEXT
|
|
11
|
+
ActiveSupport::Benchmark.realtime(:float_millisecond, &block)
|
|
16
12
|
end
|
|
17
13
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "active_support/core_ext/module/redefine_method"
|
|
4
|
+
require "active_support/class_attribute"
|
|
4
5
|
|
|
5
6
|
class Class
|
|
6
7
|
# Declare a class-level attribute whose value is inheritable by subclasses.
|
|
@@ -91,24 +92,29 @@ class Class
|
|
|
91
92
|
raise TypeError, "#{name.inspect} is not a symbol nor a string"
|
|
92
93
|
end
|
|
93
94
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
RUBY
|
|
95
|
+
name = name.to_sym
|
|
96
|
+
namespaced_name = :"__class_attr_#{name}"
|
|
97
|
+
::ActiveSupport::ClassAttribute.redefine(self, name, namespaced_name, default)
|
|
98
98
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
RUBY
|
|
99
|
+
delegators = [
|
|
100
|
+
"def #{name}; #{namespaced_name}; end",
|
|
101
|
+
"def #{name}=(value); self.#{namespaced_name} = value; end",
|
|
102
|
+
]
|
|
104
103
|
|
|
105
|
-
class_methods
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
104
|
+
class_methods.concat(delegators)
|
|
105
|
+
if singleton_class?
|
|
106
|
+
methods.concat(delegators)
|
|
107
|
+
else
|
|
108
|
+
methods << <<~RUBY if instance_reader
|
|
109
|
+
silence_redefinition_of_method def #{name}
|
|
110
|
+
if defined?(@#{name})
|
|
111
|
+
@#{name}
|
|
112
|
+
else
|
|
113
|
+
self.class.#{name}
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
RUBY
|
|
117
|
+
end
|
|
112
118
|
|
|
113
119
|
methods << <<~RUBY if instance_writer
|
|
114
120
|
silence_redefinition_of_method(:#{name}=)
|
|
@@ -125,7 +131,5 @@ class Class
|
|
|
125
131
|
|
|
126
132
|
location = caller_locations(1, 1).first
|
|
127
133
|
class_eval(["class << self", *class_methods, "end", *methods].join(";").tr("\n", ";"), location.path, location.lineno)
|
|
128
|
-
|
|
129
|
-
attrs.each { |name| public_send("#{name}=", default) }
|
|
130
134
|
end
|
|
131
135
|
end
|
|
@@ -17,6 +17,7 @@ class Date
|
|
|
17
17
|
date.strftime("%B #{day_format}, %Y") # => "April 25th, 2007"
|
|
18
18
|
},
|
|
19
19
|
rfc822: "%d %b %Y",
|
|
20
|
+
rfc2822: "%d %b %Y",
|
|
20
21
|
iso8601: lambda { |date| date.iso8601 }
|
|
21
22
|
}
|
|
22
23
|
|
|
@@ -34,6 +35,7 @@ class Date
|
|
|
34
35
|
# date.to_fs(:long) # => "November 10, 2007"
|
|
35
36
|
# date.to_fs(:long_ordinal) # => "November 10th, 2007"
|
|
36
37
|
# date.to_fs(:rfc822) # => "10 Nov 2007"
|
|
38
|
+
# date.to_fs(:rfc2822) # => "10 Nov 2007"
|
|
37
39
|
# date.to_fs(:iso8601) # => "2007-11-10"
|
|
38
40
|
#
|
|
39
41
|
# == Adding your own date formats to to_fs
|
|
@@ -26,8 +26,8 @@ module DateAndTime
|
|
|
26
26
|
# Only warn once, the first time the value is used (which should
|
|
27
27
|
# be the first time #to_time is called).
|
|
28
28
|
ActiveSupport.deprecator.warn(
|
|
29
|
-
"to_time will always preserve the timezone
|
|
30
|
-
"To opt in to the new behavior, set `
|
|
29
|
+
"`to_time` will always preserve the receiver timezone rather than system local time in Rails 8.1." \
|
|
30
|
+
"To opt in to the new behavior, set `config.active_support.to_time_preserves_timezone = :zone`."
|
|
31
31
|
)
|
|
32
32
|
|
|
33
33
|
@@preserve_timezone = false
|
|
@@ -11,8 +11,7 @@ class DateTime
|
|
|
11
11
|
#
|
|
12
12
|
# This method is aliased to <tt>to_formatted_s</tt>.
|
|
13
13
|
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
14
|
+
# === Examples
|
|
16
15
|
# datetime = DateTime.civil(2007, 12, 4, 0, 0, 0, 0) # => Tue, 04 Dec 2007 00:00:00 +0000
|
|
17
16
|
#
|
|
18
17
|
# datetime.to_fs(:db) # => "2007-12-04 00:00:00"
|
|
@@ -24,8 +23,7 @@ class DateTime
|
|
|
24
23
|
# datetime.to_fs(:rfc822) # => "Tue, 04 Dec 2007 00:00:00 +0000"
|
|
25
24
|
# datetime.to_fs(:iso8601) # => "2007-12-04T00:00:00+00:00"
|
|
26
25
|
#
|
|
27
|
-
#
|
|
28
|
-
#
|
|
26
|
+
# == Adding your own datetime formats to to_fs
|
|
29
27
|
# DateTime formats are shared with Time. You can add your own to the
|
|
30
28
|
# Time::DATE_FORMATS hash. Use the format name as the hash key and
|
|
31
29
|
# either a strftime string or Proc instance that takes a time or
|
|
@@ -192,34 +192,27 @@ module Enumerable
|
|
|
192
192
|
# # => [ Person.find(1), Person.find(5), Person.find(3) ]
|
|
193
193
|
#
|
|
194
194
|
# If the +series+ include keys that have no corresponding element in the Enumerable, these are ignored.
|
|
195
|
-
# If the Enumerable has additional elements that aren't named in the +series+, these are not included in the result
|
|
196
|
-
|
|
197
|
-
|
|
195
|
+
# If the Enumerable has additional elements that aren't named in the +series+, these are not included in the result, unless
|
|
196
|
+
# the +filter+ option is set to +false+.
|
|
197
|
+
def in_order_of(key, series, filter: true)
|
|
198
|
+
if filter
|
|
199
|
+
group_by(&key).values_at(*series).flatten(1).compact
|
|
200
|
+
else
|
|
201
|
+
sort_by { |v| series.index(v.public_send(key)) || series.size }.compact
|
|
202
|
+
end
|
|
198
203
|
end
|
|
199
204
|
|
|
200
205
|
# Returns the sole item in the enumerable. If there are no items, or more
|
|
201
|
-
# than one item, raises Enumerable::SoleItemExpectedError
|
|
206
|
+
# than one item, raises +Enumerable::SoleItemExpectedError+.
|
|
202
207
|
#
|
|
203
208
|
# ["x"].sole # => "x"
|
|
204
209
|
# Set.new.sole # => Enumerable::SoleItemExpectedError: no item found
|
|
205
210
|
# { a: 1, b: 2 }.sole # => Enumerable::SoleItemExpectedError: multiple items found
|
|
206
211
|
def sole
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
if found
|
|
212
|
-
raise SoleItemExpectedError, "multiple items found"
|
|
213
|
-
end
|
|
214
|
-
|
|
215
|
-
result = element.size == 1 ? element[0] : element
|
|
216
|
-
found = true
|
|
217
|
-
end
|
|
218
|
-
|
|
219
|
-
if found
|
|
220
|
-
result
|
|
221
|
-
else
|
|
222
|
-
raise SoleItemExpectedError, "no item found"
|
|
212
|
+
case count
|
|
213
|
+
when 1 then return first # rubocop:disable Style/RedundantReturn
|
|
214
|
+
when 0 then raise ActiveSupport::EnumerableCoreExt::SoleItemExpectedError, "no item found"
|
|
215
|
+
when 2.. then raise ActiveSupport::EnumerableCoreExt::SoleItemExpectedError, "multiple items found"
|
|
223
216
|
end
|
|
224
217
|
end
|
|
225
218
|
end
|
|
@@ -1,18 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
class Hash
|
|
4
|
-
# Returns a hash that includes everything except given keys.
|
|
5
|
-
# hash = { a: true, b: false, c: nil }
|
|
6
|
-
# hash.except(:c) # => { a: true, b: false }
|
|
7
|
-
# hash.except(:a, :b) # => { c: nil }
|
|
8
|
-
# hash # => { a: true, b: false, c: nil }
|
|
9
|
-
#
|
|
10
|
-
# This is useful for limiting a set of parameters to everything but a few known toggles:
|
|
11
|
-
# @person.update(params[:person].except(:admin))
|
|
12
|
-
def except(*keys)
|
|
13
|
-
slice(*self.keys - keys)
|
|
14
|
-
end unless method_defined?(:except)
|
|
15
|
-
|
|
16
4
|
# Removes the given keys from hash and returns it.
|
|
17
5
|
# hash = { a: true, b: false, c: nil }
|
|
18
6
|
# hash.except!(:c) # => { a: true, b: false }
|
|
@@ -24,14 +24,13 @@ class Module
|
|
|
24
24
|
|
|
25
25
|
def attr_internal_naming_format=(format)
|
|
26
26
|
if format.start_with?("@")
|
|
27
|
-
|
|
28
|
-
Setting `attr_internal_naming_format` with a `@` prefix is
|
|
27
|
+
raise ArgumentError, <<~MESSAGE.squish
|
|
28
|
+
Setting `attr_internal_naming_format` with a `@` prefix is not supported.
|
|
29
29
|
|
|
30
30
|
You can simply replace #{format.inspect} by #{format.delete_prefix("@").inspect}.
|
|
31
31
|
MESSAGE
|
|
32
|
-
|
|
33
|
-
format = format.delete_prefix("@")
|
|
34
32
|
end
|
|
33
|
+
|
|
35
34
|
@attr_internal_naming_format = format
|
|
36
35
|
end
|
|
37
36
|
end
|
|
@@ -65,11 +65,9 @@ class Object
|
|
|
65
65
|
end
|
|
66
66
|
end
|
|
67
67
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
to_h.as_json(options)
|
|
72
|
-
end
|
|
68
|
+
class Data # :nodoc:
|
|
69
|
+
def as_json(options = nil)
|
|
70
|
+
to_h.as_json(options)
|
|
73
71
|
end
|
|
74
72
|
end
|
|
75
73
|
|
|
@@ -105,7 +103,7 @@ end
|
|
|
105
103
|
|
|
106
104
|
class Symbol
|
|
107
105
|
def as_json(options = nil) # :nodoc:
|
|
108
|
-
|
|
106
|
+
name
|
|
109
107
|
end
|
|
110
108
|
end
|
|
111
109
|
|
|
@@ -164,7 +162,12 @@ end
|
|
|
164
162
|
|
|
165
163
|
class Array
|
|
166
164
|
def as_json(options = nil) # :nodoc:
|
|
167
|
-
|
|
165
|
+
if options
|
|
166
|
+
options = options.dup.freeze unless options.frozen?
|
|
167
|
+
map { |v| v.as_json(options) }
|
|
168
|
+
else
|
|
169
|
+
map { |v| v.as_json }
|
|
170
|
+
end
|
|
168
171
|
end
|
|
169
172
|
end
|
|
170
173
|
|
|
@@ -184,8 +187,11 @@ class Hash
|
|
|
184
187
|
end
|
|
185
188
|
|
|
186
189
|
result = {}
|
|
187
|
-
|
|
188
|
-
|
|
190
|
+
if options
|
|
191
|
+
options = options.dup.freeze unless options.frozen?
|
|
192
|
+
subset.each { |k, v| result[k.to_s] = v.as_json(options) }
|
|
193
|
+
else
|
|
194
|
+
subset.each { |k, v| result[k.to_s] = v.as_json }
|
|
189
195
|
end
|
|
190
196
|
result
|
|
191
197
|
end
|
|
@@ -145,14 +145,14 @@ class NilClass
|
|
|
145
145
|
#
|
|
146
146
|
# With +try+
|
|
147
147
|
# @person.try(:children).try(:first).try(:name)
|
|
148
|
-
def try(
|
|
148
|
+
def try(*)
|
|
149
149
|
nil
|
|
150
150
|
end
|
|
151
151
|
|
|
152
152
|
# Calling +try!+ on +nil+ always returns +nil+.
|
|
153
153
|
#
|
|
154
154
|
# nil.try!(:name) # => nil
|
|
155
|
-
def try!(
|
|
155
|
+
def try!(*)
|
|
156
156
|
nil
|
|
157
157
|
end
|
|
158
158
|
end
|
|
@@ -88,11 +88,11 @@ class String
|
|
|
88
88
|
# characters.
|
|
89
89
|
#
|
|
90
90
|
# >> "🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪".size
|
|
91
|
-
#
|
|
91
|
+
# => 20
|
|
92
92
|
# >> "🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪".bytesize
|
|
93
|
-
#
|
|
93
|
+
# => 80
|
|
94
94
|
# >> "🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪".truncate_bytes(20)
|
|
95
|
-
#
|
|
95
|
+
# => "🔪🔪🔪🔪…"
|
|
96
96
|
#
|
|
97
97
|
# The truncated text ends with the <tt>:omission</tt> string, defaulting
|
|
98
98
|
# to "…", for a total length not exceeding <tt>truncate_to</tt>.
|
|
@@ -12,12 +12,12 @@ class String
|
|
|
12
12
|
# class. If the proxy class doesn't respond to a certain method, it's forwarded to the encapsulated string.
|
|
13
13
|
#
|
|
14
14
|
# >> "lj".mb_chars.upcase.to_s
|
|
15
|
-
#
|
|
15
|
+
# => "LJ"
|
|
16
16
|
#
|
|
17
17
|
# NOTE: Ruby 2.4 and later support native Unicode case mappings:
|
|
18
18
|
#
|
|
19
19
|
# >> "lj".upcase
|
|
20
|
-
#
|
|
20
|
+
# => "LJ"
|
|
21
21
|
#
|
|
22
22
|
# == \Method chaining
|
|
23
23
|
#
|
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
class Thread::Backtrace::Location # :nodoc:
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
ErrorHighlight.spot(ex, backtrace_location: self)
|
|
7
|
-
end
|
|
8
|
-
else
|
|
9
|
-
def spot(ex)
|
|
10
|
-
end
|
|
4
|
+
def spot(ex)
|
|
5
|
+
ErrorHighlight.spot(ex, backtrace_location: self)
|
|
11
6
|
end
|
|
12
7
|
end
|
|
@@ -147,6 +147,13 @@ class Time
|
|
|
147
147
|
elsif zone.respond_to?(:utc_to_local)
|
|
148
148
|
new_time = ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, zone)
|
|
149
149
|
|
|
150
|
+
# Some versions of Ruby have a bug where Time.new with a zone object and
|
|
151
|
+
# fractional seconds will end up with a broken utc_offset.
|
|
152
|
+
# This is fixed in Ruby 3.3.1 and 3.2.4
|
|
153
|
+
unless new_time.utc_offset.integer?
|
|
154
|
+
new_time += 0
|
|
155
|
+
end
|
|
156
|
+
|
|
150
157
|
# When there are two occurrences of a nominal time due to DST ending,
|
|
151
158
|
# `Time.new` chooses the first chronological occurrence (the one with a
|
|
152
159
|
# larger UTC offset). However, for `change`, we want to choose the
|
|
@@ -217,8 +224,13 @@ class Time
|
|
|
217
224
|
# Returns a new Time representing the time a number of seconds since the instance time
|
|
218
225
|
def since(seconds)
|
|
219
226
|
self + seconds
|
|
220
|
-
rescue
|
|
221
|
-
to_datetime.since(seconds)
|
|
227
|
+
rescue TypeError
|
|
228
|
+
result = to_datetime.since(seconds)
|
|
229
|
+
ActiveSupport.deprecator.warn(
|
|
230
|
+
"Passing an instance of #{seconds.class} to #{self.class}#since is deprecated. This behavior will raise " \
|
|
231
|
+
"a `TypeError` in Rails 8.1."
|
|
232
|
+
)
|
|
233
|
+
result
|
|
222
234
|
end
|
|
223
235
|
alias :in :since
|
|
224
236
|
|
|
@@ -22,6 +22,7 @@ class Time
|
|
|
22
22
|
offset_format = time.formatted_offset(false)
|
|
23
23
|
time.strftime("%a, %d %b %Y %H:%M:%S #{offset_format}")
|
|
24
24
|
},
|
|
25
|
+
rfc2822: lambda { |time| time.rfc2822 },
|
|
25
26
|
iso8601: lambda { |time| time.iso8601 }
|
|
26
27
|
}
|
|
27
28
|
|
|
@@ -40,6 +41,7 @@ class Time
|
|
|
40
41
|
# time.to_fs(:long) # => "January 18, 2007 06:10"
|
|
41
42
|
# time.to_fs(:long_ordinal) # => "January 18th, 2007 06:10"
|
|
42
43
|
# time.to_fs(:rfc822) # => "Thu, 18 Jan 2007 06:10:17 -0600"
|
|
44
|
+
# time.to_fs(:rfc2822) # => "Thu, 18 Jan 2007 06:10:17 -0600"
|
|
43
45
|
# time.to_fs(:iso8601) # => "2007-01-18T06:10:17-06:00"
|
|
44
46
|
#
|
|
45
47
|
# == Adding your own time formats to +to_fs+
|
|
@@ -108,18 +108,15 @@ module ActiveSupport
|
|
|
108
108
|
# ==== Options
|
|
109
109
|
#
|
|
110
110
|
# * <tt>:default</tt> - The default value for the attributes. If the value
|
|
111
|
-
#
|
|
112
|
-
#
|
|
113
|
-
#
|
|
111
|
+
# is a proc or lambda, it will be called whenever an instance is
|
|
112
|
+
# constructed. Otherwise, the value will be duplicated with +#dup+.
|
|
113
|
+
# Default values are re-assigned when the attributes are reset.
|
|
114
114
|
def attribute(*names, default: NOT_SET)
|
|
115
115
|
invalid_attribute_names = names.map(&:to_sym) & INVALID_ATTRIBUTE_NAMES
|
|
116
116
|
if invalid_attribute_names.any?
|
|
117
117
|
raise ArgumentError, "Restricted attribute names: #{invalid_attribute_names.join(", ")}"
|
|
118
118
|
end
|
|
119
119
|
|
|
120
|
-
Delegation.generate(singleton_class, names, to: :instance, nilable: false, signature: "")
|
|
121
|
-
Delegation.generate(singleton_class, names.map { |n| "#{n}=" }, to: :instance, nilable: false, signature: "value")
|
|
122
|
-
|
|
123
120
|
ActiveSupport::CodeGenerator.batch(generated_attribute_methods, __FILE__, __LINE__) do |owner|
|
|
124
121
|
names.each do |name|
|
|
125
122
|
owner.define_cached_method(name, namespace: :current_attributes) do |batch|
|
|
@@ -137,6 +134,9 @@ module ActiveSupport
|
|
|
137
134
|
end
|
|
138
135
|
end
|
|
139
136
|
|
|
137
|
+
Delegation.generate(singleton_class, names, to: :instance, nilable: false, signature: "")
|
|
138
|
+
Delegation.generate(singleton_class, names.map { |n| "#{n}=" }, to: :instance, nilable: false, signature: "value")
|
|
139
|
+
|
|
140
140
|
self.defaults = defaults.merge(names.index_with { default })
|
|
141
141
|
end
|
|
142
142
|
|
|
@@ -185,16 +185,9 @@ module ActiveSupport
|
|
|
185
185
|
|
|
186
186
|
def method_added(name)
|
|
187
187
|
super
|
|
188
|
-
|
|
189
|
-
# We try to generate instance delegators early to not rely on method_missing.
|
|
190
188
|
return if name == :initialize
|
|
191
|
-
|
|
192
|
-
# If the added method isn't public, we don't delegate it.
|
|
193
189
|
return unless public_method_defined?(name)
|
|
194
|
-
|
|
195
|
-
# If we already have a class method by that name, we don't override it.
|
|
196
|
-
return if singleton_class.method_defined?(name) || singleton_class.private_method_defined?(name)
|
|
197
|
-
|
|
190
|
+
return if respond_to?(name, true)
|
|
198
191
|
Delegation.generate(singleton_class, [name], to: :instance, as: self, nilable: false)
|
|
199
192
|
end
|
|
200
193
|
end
|
|
@@ -139,7 +139,6 @@ module ActiveSupport
|
|
|
139
139
|
|
|
140
140
|
def extract_callstack(callstack)
|
|
141
141
|
return [] if callstack.empty?
|
|
142
|
-
return _extract_callstack(callstack) if callstack.first.is_a? String
|
|
143
142
|
|
|
144
143
|
offending_line = callstack.find { |frame|
|
|
145
144
|
# Code generated with `eval` doesn't have an `absolute_path`, e.g. templates.
|
|
@@ -150,24 +149,6 @@ module ActiveSupport
|
|
|
150
149
|
[offending_line.path, offending_line.lineno, offending_line.label]
|
|
151
150
|
end
|
|
152
151
|
|
|
153
|
-
def _extract_callstack(callstack)
|
|
154
|
-
ActiveSupport.deprecator.warn(<<~MESSAGE)
|
|
155
|
-
Passing the result of `caller` to ActiveSupport::Deprecation#warn is deprecated and will be removed in Rails 8.0.
|
|
156
|
-
|
|
157
|
-
Please pass the result of `caller_locations` instead.
|
|
158
|
-
MESSAGE
|
|
159
|
-
|
|
160
|
-
offending_line = callstack.find { |line| !ignored_callstack?(line) } || callstack.first
|
|
161
|
-
|
|
162
|
-
if offending_line
|
|
163
|
-
if md = offending_line.match(/^(.+?):(\d+)(?::in `(.*?)')?/)
|
|
164
|
-
md.captures
|
|
165
|
-
else
|
|
166
|
-
offending_line
|
|
167
|
-
end
|
|
168
|
-
end
|
|
169
|
-
end
|
|
170
|
-
|
|
171
152
|
RAILS_GEM_ROOT = File.expand_path("../../../..", __dir__) + "/" # :nodoc:
|
|
172
153
|
LIB_DIR = RbConfig::CONFIG["libdir"] # :nodoc:
|
|
173
154
|
|
|
@@ -68,7 +68,7 @@ module ActiveSupport
|
|
|
68
68
|
# and the second is a library name.
|
|
69
69
|
#
|
|
70
70
|
# ActiveSupport::Deprecation.new('2.0', 'MyLibrary')
|
|
71
|
-
def initialize(deprecation_horizon = "8.
|
|
71
|
+
def initialize(deprecation_horizon = "8.1", gem_name = "Rails")
|
|
72
72
|
self.gem_name = gem_name
|
|
73
73
|
self.deprecation_horizon = deprecation_horizon
|
|
74
74
|
# By default, warnings are not silenced and debugging is off.
|
|
@@ -491,17 +491,21 @@ module ActiveSupport
|
|
|
491
491
|
if @parts.empty?
|
|
492
492
|
time.since(sign * value)
|
|
493
493
|
else
|
|
494
|
-
@parts.
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
494
|
+
@parts.each do |type, number|
|
|
495
|
+
t = time
|
|
496
|
+
time =
|
|
497
|
+
if type == :seconds
|
|
498
|
+
t.since(sign * number)
|
|
499
|
+
elsif type == :minutes
|
|
500
|
+
t.since(sign * number * 60)
|
|
501
|
+
elsif type == :hours
|
|
502
|
+
t.since(sign * number * 3600)
|
|
503
|
+
else
|
|
504
|
+
t.advance(type => sign * number)
|
|
505
|
+
end
|
|
504
506
|
end
|
|
507
|
+
|
|
508
|
+
time
|
|
505
509
|
end
|
|
506
510
|
end
|
|
507
511
|
|
|
@@ -43,6 +43,12 @@ module ActiveSupport
|
|
|
43
43
|
end
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
+
class InvalidKeyError < RuntimeError
|
|
47
|
+
def initialize(content_path, key)
|
|
48
|
+
super "Key '#{key}' is invalid, it must respond to '#to_sym' from configuration in '#{content_path}'."
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
46
52
|
delegate_missing_to :options
|
|
47
53
|
|
|
48
54
|
def initialize(config_path:, key_path:, env_key:, raise_if_missing_key:)
|
|
@@ -61,7 +67,11 @@ module ActiveSupport
|
|
|
61
67
|
end
|
|
62
68
|
|
|
63
69
|
def validate! # :nodoc:
|
|
64
|
-
deserialize(read)
|
|
70
|
+
deserialize(read).each_key do |key|
|
|
71
|
+
key.to_sym
|
|
72
|
+
rescue NoMethodError
|
|
73
|
+
raise InvalidKeyError.new(content_path, key)
|
|
74
|
+
end
|
|
65
75
|
end
|
|
66
76
|
|
|
67
77
|
# Returns the decrypted content as a Hash with symbolized keys.
|
|
@@ -73,7 +83,7 @@ module ActiveSupport
|
|
|
73
83
|
# # => { some_secret: 123, some_namespace: { another_secret: 789 } }
|
|
74
84
|
#
|
|
75
85
|
def config
|
|
76
|
-
@config ||= deserialize(read)
|
|
86
|
+
@config ||= deep_symbolize_keys(deserialize(read))
|
|
77
87
|
end
|
|
78
88
|
|
|
79
89
|
def inspect # :nodoc:
|
|
@@ -81,6 +91,14 @@ module ActiveSupport
|
|
|
81
91
|
end
|
|
82
92
|
|
|
83
93
|
private
|
|
94
|
+
def deep_symbolize_keys(hash)
|
|
95
|
+
hash.deep_transform_keys do |key|
|
|
96
|
+
key.to_sym
|
|
97
|
+
rescue NoMethodError
|
|
98
|
+
raise InvalidKeyError.new(content_path, key)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
84
102
|
def deep_transform(hash)
|
|
85
103
|
return hash unless hash.is_a?(Hash)
|
|
86
104
|
|