activesupport 7.2.1 → 8.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +67 -189
- data/lib/active_support/backtrace_cleaner.rb +1 -1
- data/lib/active_support/benchmark.rb +21 -0
- data/lib/active_support/benchmarkable.rb +3 -2
- data/lib/active_support/broadcast_logger.rb +14 -14
- data/lib/active_support/cache/file_store.rb +12 -2
- data/lib/active_support/cache/memory_store.rb +6 -2
- data/lib/active_support/cache/redis_cache_store.rb +5 -2
- data/lib/active_support/cache.rb +18 -13
- data/lib/active_support/callbacks.rb +1 -2
- 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/benchmark.rb +6 -9
- data/lib/active_support/core_ext/class/attribute.rb +10 -19
- 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/enumerable.rb +8 -3
- 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/object/json.rb +20 -12
- data/lib/active_support/core_ext/string/multibyte.rb +1 -1
- 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/compatibility.rb +9 -1
- data/lib/active_support/core_ext/time/conversions.rb +2 -0
- data/lib/active_support/core_ext/time/zones.rb +1 -1
- data/lib/active_support/current_attributes.rb +7 -3
- data/lib/active_support/delegation.rb +0 -2
- data/lib/active_support/dependencies.rb +0 -1
- data/lib/active_support/deprecation/reporting.rb +2 -21
- 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/encrypted_file.rb +1 -1
- data/lib/active_support/error_reporter.rb +25 -1
- data/lib/active_support/evented_file_update_checker.rb +0 -1
- data/lib/active_support/gem_version.rb +3 -3
- data/lib/active_support/hash_with_indifferent_access.rb +16 -16
- 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/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 +2 -2
- data/lib/active_support/testing/parallelization/server.rb +3 -0
- data/lib/active_support/testing/strict_warnings.rb +3 -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 +17 -15
- data/lib/active_support.rb +10 -3
- metadata +40 -11
- data/lib/active_support/proxy_object.rb +0 -20
@@ -313,10 +313,6 @@ module ActiveSupport
|
|
313
313
|
end
|
314
314
|
alias_method :without, :except
|
315
315
|
|
316
|
-
def stringify_keys!; self end
|
317
|
-
def deep_stringify_keys!; self end
|
318
|
-
def stringify_keys; dup end
|
319
|
-
def deep_stringify_keys; dup end
|
320
316
|
undef :symbolize_keys!
|
321
317
|
undef :deep_symbolize_keys!
|
322
318
|
def symbolize_keys; to_hash.symbolize_keys! end
|
@@ -378,13 +374,10 @@ module ActiveSupport
|
|
378
374
|
|
379
375
|
# Convert to a regular hash with string keys.
|
380
376
|
def to_hash
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
_new_hash[key] = convert_value(value, conversion: :to_hash)
|
386
|
-
end
|
387
|
-
_new_hash
|
377
|
+
copy = Hash[self]
|
378
|
+
copy.transform_values! { |v| convert_value_to_hash(v) }
|
379
|
+
set_defaults(copy)
|
380
|
+
copy
|
388
381
|
end
|
389
382
|
|
390
383
|
def to_proc
|
@@ -398,11 +391,7 @@ module ActiveSupport
|
|
398
391
|
|
399
392
|
def convert_value(value, conversion: nil)
|
400
393
|
if value.is_a? Hash
|
401
|
-
|
402
|
-
value.to_hash
|
403
|
-
else
|
404
|
-
value.nested_under_indifferent_access
|
405
|
-
end
|
394
|
+
value.nested_under_indifferent_access
|
406
395
|
elsif value.is_a?(Array)
|
407
396
|
if conversion != :assignment || value.frozen?
|
408
397
|
value = value.dup
|
@@ -413,6 +402,17 @@ module ActiveSupport
|
|
413
402
|
end
|
414
403
|
end
|
415
404
|
|
405
|
+
def convert_value_to_hash(value)
|
406
|
+
if value.is_a? Hash
|
407
|
+
value.to_hash
|
408
|
+
elsif value.is_a?(Array)
|
409
|
+
value.map { |e| convert_value_to_hash(e) }
|
410
|
+
else
|
411
|
+
value
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
415
|
+
|
416
416
|
def set_defaults(target)
|
417
417
|
if default_proc
|
418
418
|
target.default_proc = default_proc.dup
|
@@ -14,15 +14,18 @@ module I18n
|
|
14
14
|
|
15
15
|
config.eager_load_namespaces << I18n
|
16
16
|
|
17
|
-
#
|
18
|
-
#
|
19
|
-
config.
|
17
|
+
# Make sure i18n is ready before eager loading, in case any eager loaded
|
18
|
+
# code needs it.
|
19
|
+
config.before_eager_load do |app|
|
20
20
|
I18n::Railtie.initialize_i18n(app)
|
21
21
|
end
|
22
22
|
|
23
|
-
#
|
24
|
-
#
|
25
|
-
|
23
|
+
# i18n initialization needs to run after application initialization, since
|
24
|
+
# initializers may configure i18n.
|
25
|
+
#
|
26
|
+
# If the application eager loaded, this was done on before_eager_load. The
|
27
|
+
# hook is still OK, though, because initialize_i18n is idempotent.
|
28
|
+
config.after_initialize do |app|
|
26
29
|
I18n::Railtie.initialize_i18n(app)
|
27
30
|
end
|
28
31
|
|
@@ -49,7 +52,8 @@ module I18n
|
|
49
52
|
when :load_path
|
50
53
|
I18n.load_path += value
|
51
54
|
when :raise_on_missing_translations
|
52
|
-
|
55
|
+
strict = value == :strict
|
56
|
+
setup_raise_on_missing_translations_config(app, strict)
|
53
57
|
else
|
54
58
|
I18n.public_send("#{setting}=", value)
|
55
59
|
end
|
@@ -62,8 +66,9 @@ module I18n
|
|
62
66
|
|
63
67
|
if app.config.reloading_enabled?
|
64
68
|
directories = watched_dirs_with_extensions(reloadable_paths)
|
65
|
-
|
66
|
-
|
69
|
+
root_load_paths = I18n.load_path.select { |path| path.to_s.start_with?(Rails.root.to_s) }
|
70
|
+
reloader = app.config.file_watcher.new(root_load_paths, directories) do
|
71
|
+
I18n.load_path.delete_if { |path| path.to_s.start_with?(Rails.root.to_s) && !File.exist?(path) }
|
67
72
|
I18n.load_path |= reloadable_paths.flat_map(&:existent)
|
68
73
|
end
|
69
74
|
|
@@ -71,17 +76,20 @@ module I18n
|
|
71
76
|
app.reloader.to_run do
|
72
77
|
reloader.execute_if_updated { require_unload_lock! }
|
73
78
|
end
|
74
|
-
reloader.execute
|
75
79
|
end
|
76
80
|
|
77
81
|
@i18n_inited = true
|
78
82
|
end
|
79
83
|
|
80
|
-
def self.setup_raise_on_missing_translations_config(app)
|
84
|
+
def self.setup_raise_on_missing_translations_config(app, strict)
|
81
85
|
ActiveSupport.on_load(:action_view) do
|
82
86
|
ActionView::Helpers::TranslationHelper.raise_on_missing_translations = app.config.i18n.raise_on_missing_translations
|
83
87
|
end
|
84
88
|
|
89
|
+
ActiveSupport.on_load(:active_model_translation) do
|
90
|
+
ActiveModel::Translation.raise_on_missing_translations = app.config.i18n.raise_on_missing_translations if strict
|
91
|
+
end
|
92
|
+
|
85
93
|
if app.config.i18n.raise_on_missing_translations &&
|
86
94
|
I18n.exception_handler.is_a?(I18n::ExceptionHandler) # Only override the i18n gem's default exception handler.
|
87
95
|
|
@@ -36,14 +36,14 @@ module ActiveSupport
|
|
36
36
|
# Encode the given object into a JSON string
|
37
37
|
def encode(value)
|
38
38
|
unless options.empty?
|
39
|
-
value = value.as_json(options.dup)
|
39
|
+
value = value.as_json(options.dup.freeze)
|
40
40
|
end
|
41
41
|
json = stringify(jsonify(value))
|
42
42
|
|
43
43
|
# Rails does more escaping than the JSON gem natively does (we
|
44
44
|
# escape \u2028 and \u2029 and optionally >, <, & to work around
|
45
45
|
# certain browser problems).
|
46
|
-
if Encoding.escape_html_entities_in_json
|
46
|
+
if @options.fetch(:escape_html_entities, Encoding.escape_html_entities_in_json)
|
47
47
|
json.gsub!(">", '\u003e')
|
48
48
|
json.gsub!("<", '\u003c')
|
49
49
|
json.gsub!("&", '\u0026')
|
@@ -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
|
|
@@ -96,6 +96,10 @@ module ActiveSupport
|
|
96
96
|
config.eager_load_namespaces << TZInfo
|
97
97
|
end
|
98
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
|
101
|
+
end
|
102
|
+
|
99
103
|
# Sets the default week start
|
100
104
|
# If assigned value is not a valid day symbol (e.g. :sunday, :monday, ...), an exception will be raised.
|
101
105
|
initializer "active_support.initialize_beginning_of_week" do |app|
|
@@ -113,6 +113,11 @@ module ActiveSupport
|
|
113
113
|
end
|
114
114
|
end
|
115
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
|
+
|
116
121
|
def self.new(logger)
|
117
122
|
logger = logger.clone
|
118
123
|
|
@@ -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
|
@@ -1,10 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/testing/parallelize_executor"
|
4
|
+
|
3
5
|
module ActiveSupport
|
4
6
|
module Testing
|
5
7
|
module Isolation
|
6
|
-
require "thread"
|
7
|
-
|
8
8
|
SubprocessCrashed = Class.new(StandardError)
|
9
9
|
|
10
10
|
def self.included(klass) # :nodoc:
|
@@ -6,6 +6,8 @@ require "drb/unix" unless Gem.win_platform?
|
|
6
6
|
module ActiveSupport
|
7
7
|
module Testing
|
8
8
|
class Parallelization # :nodoc:
|
9
|
+
PrerecordResultClass = Struct.new(:name)
|
10
|
+
|
9
11
|
class Server
|
10
12
|
include DRb::DRbUndumped
|
11
13
|
|
@@ -21,6 +23,7 @@ module ActiveSupport
|
|
21
23
|
@in_flight.delete([result.klass, result.name])
|
22
24
|
|
23
25
|
reporter.synchronize do
|
26
|
+
reporter.prerecord(PrerecordResultClass.new(result.klass), result.name)
|
24
27
|
reporter.record(result)
|
25
28
|
end
|
26
29
|
end
|
@@ -14,6 +14,9 @@ module ActiveSupport
|
|
14
14
|
# Expected non-verbose warning emitted by Rails.
|
15
15
|
/Ignoring .*\.yml because it has expired/,
|
16
16
|
/Failed to validate the schema cache because/,
|
17
|
+
|
18
|
+
# TODO: We need to decide what to do with this.
|
19
|
+
/Status code :unprocessable_entity is deprecated/,
|
17
20
|
)
|
18
21
|
|
19
22
|
SUPPRESSED_WARNINGS = Regexp.union(
|
@@ -166,9 +166,10 @@ module ActiveSupport
|
|
166
166
|
else
|
167
167
|
now = date_or_time
|
168
168
|
now = now.to_time unless now.is_a?(Time)
|
169
|
-
now = now.change(usec: 0) unless with_usec
|
170
169
|
end
|
171
170
|
|
171
|
+
now = now.change(usec: 0) unless with_usec
|
172
|
+
|
172
173
|
# +now+ must be in local system timezone, because +Time.at(now)+
|
173
174
|
# and +now.to_date+ (see stubs below) will use +now+'s timezone too!
|
174
175
|
now = now.getlocal
|
@@ -85,7 +85,7 @@ module ActiveSupport
|
|
85
85
|
end
|
86
86
|
alias_method :getlocal, :localtime
|
87
87
|
|
88
|
-
# Returns true if the current time is within Daylight Savings Time for the
|
88
|
+
# Returns true if the current time is within Daylight Savings \Time for the
|
89
89
|
# specified time zone.
|
90
90
|
#
|
91
91
|
# Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
|
@@ -138,7 +138,7 @@ module ActiveSupport
|
|
138
138
|
#
|
139
139
|
# Time.zone.now.inspect # => "Thu, 04 Dec 2014 11:00:25.624541392 EST -05:00"
|
140
140
|
def inspect
|
141
|
-
"#{time.strftime('%
|
141
|
+
"#{time.strftime('%F %H:%M:%S.%9N')} #{zone} #{formatted_offset}"
|
142
142
|
end
|
143
143
|
|
144
144
|
# Returns a string of the object's date and time in the ISO 8601 standard
|
@@ -157,11 +157,11 @@ module ActiveSupport
|
|
157
157
|
# to +false+.
|
158
158
|
#
|
159
159
|
# # With ActiveSupport::JSON::Encoding.use_standard_json_time_format = true
|
160
|
-
# Time.utc(2005,2,1,15,15,10).in_time_zone("Hawaii").
|
160
|
+
# Time.utc(2005,2,1,15,15,10).in_time_zone("Hawaii").as_json
|
161
161
|
# # => "2005-02-01T05:15:10.000-10:00"
|
162
162
|
#
|
163
163
|
# # With ActiveSupport::JSON::Encoding.use_standard_json_time_format = false
|
164
|
-
# Time.utc(2005,2,1,15,15,10).in_time_zone("Hawaii").
|
164
|
+
# Time.utc(2005,2,1,15,15,10).in_time_zone("Hawaii").as_json
|
165
165
|
# # => "2005/02/01 05:15:10 -1000"
|
166
166
|
def as_json(options = nil)
|
167
167
|
if ActiveSupport::JSON::Encoding.use_standard_json_time_format
|
@@ -215,8 +215,7 @@ module ActiveSupport
|
|
215
215
|
elsif formatter = ::Time::DATE_FORMATS[format]
|
216
216
|
formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
|
217
217
|
else
|
218
|
-
|
219
|
-
"#{time.strftime("%Y-%m-%d %H:%M:%S")} #{formatted_offset(false, 'UTC')}"
|
218
|
+
to_s
|
220
219
|
end
|
221
220
|
end
|
222
221
|
alias_method :to_formatted_s, :to_fs
|
@@ -300,7 +299,16 @@ module ActiveSupport
|
|
300
299
|
if duration_of_variable_length?(other)
|
301
300
|
method_missing(:+, other)
|
302
301
|
else
|
303
|
-
|
302
|
+
begin
|
303
|
+
result = utc + other
|
304
|
+
rescue TypeError
|
305
|
+
result = utc.to_datetime.since(other)
|
306
|
+
ActiveSupport.deprecator.warn(
|
307
|
+
"Adding an instance of #{other.class} to an instance of #{self.class} is deprecated. This behavior will raise " \
|
308
|
+
"a `TypeError` in Rails 8.1."
|
309
|
+
)
|
310
|
+
result.in_time_zone(time_zone)
|
311
|
+
end
|
304
312
|
result.in_time_zone(time_zone)
|
305
313
|
end
|
306
314
|
end
|
@@ -336,7 +344,7 @@ module ActiveSupport
|
|
336
344
|
elsif duration_of_variable_length?(other)
|
337
345
|
method_missing(:-, other)
|
338
346
|
else
|
339
|
-
result = utc
|
347
|
+
result = utc - other
|
340
348
|
result.in_time_zone(time_zone)
|
341
349
|
end
|
342
350
|
end
|
@@ -479,11 +487,13 @@ module ActiveSupport
|
|
479
487
|
@to_datetime ||= utc.to_datetime.new_offset(Rational(utc_offset, 86_400))
|
480
488
|
end
|
481
489
|
|
482
|
-
# Returns an instance of +Time+, either with the same
|
483
|
-
# as +self+ or in the local system timezone
|
484
|
-
# of +ActiveSupport.to_time_preserves_timezone+.
|
490
|
+
# Returns an instance of +Time+, either with the same timezone as +self+,
|
491
|
+
# with the same UTC offset as +self+ or in the local system timezone
|
492
|
+
# depending on the setting of +ActiveSupport.to_time_preserves_timezone+.
|
485
493
|
def to_time
|
486
|
-
if preserve_timezone
|
494
|
+
if preserve_timezone == :zone
|
495
|
+
@to_time_with_timezone ||= getlocal(time_zone)
|
496
|
+
elsif preserve_timezone
|
487
497
|
@to_time_with_instance_offset ||= getlocal(utc_offset)
|
488
498
|
else
|
489
499
|
@to_time_with_system_offset ||= getlocal
|
@@ -535,7 +545,6 @@ module ActiveSupport
|
|
535
545
|
# Ensure proxy class responds to all methods that underlying time instance
|
536
546
|
# responds to.
|
537
547
|
def respond_to_missing?(sym, include_priv)
|
538
|
-
return false if sym.to_sym == :acts_like_date?
|
539
548
|
time.respond_to?(sym, include_priv)
|
540
549
|
end
|
541
550
|
|
@@ -12,7 +12,7 @@ module ActiveSupport
|
|
12
12
|
# * Limit the set of zones provided by TZInfo to a meaningful subset of 134
|
13
13
|
# zones.
|
14
14
|
# * Retrieve and display zones with a friendlier name
|
15
|
-
# (e.g., "Eastern Time (US & Canada)" instead of "America/New_York").
|
15
|
+
# (e.g., "Eastern \Time (US & Canada)" instead of "America/New_York").
|
16
16
|
# * Lazily load +TZInfo::Timezone+ instances only when they're needed.
|
17
17
|
# * Create ActiveSupport::TimeWithZone instances via TimeZone's +local+,
|
18
18
|
# +parse+, +at+, and +now+ methods.
|
@@ -208,9 +208,7 @@ module ActiveSupport
|
|
208
208
|
TZInfo::Timezone.get(MAPPING[name] || name)
|
209
209
|
end
|
210
210
|
|
211
|
-
# :
|
212
|
-
alias_method :create, :new
|
213
|
-
# :startdoc:
|
211
|
+
alias_method :create, :new # :nodoc:
|
214
212
|
|
215
213
|
# Returns a TimeZone instance with the given name, or +nil+ if no
|
216
214
|
# such TimeZone instance exists. (This exists to support the use of
|
@@ -357,7 +355,7 @@ module ActiveSupport
|
|
357
355
|
"(GMT#{formatted_offset}) #{name}"
|
358
356
|
end
|
359
357
|
|
360
|
-
# Method for creating new ActiveSupport::TimeWithZone instance in time zone
|
358
|
+
# \Method for creating new ActiveSupport::TimeWithZone instance in time zone
|
361
359
|
# of +self+ from given values.
|
362
360
|
#
|
363
361
|
# Time.zone = 'Hawaii' # => "Hawaii"
|
@@ -367,7 +365,7 @@ module ActiveSupport
|
|
367
365
|
ActiveSupport::TimeWithZone.new(nil, self, time)
|
368
366
|
end
|
369
367
|
|
370
|
-
# Method for creating new ActiveSupport::TimeWithZone instance in time zone
|
368
|
+
# \Method for creating new ActiveSupport::TimeWithZone instance in time zone
|
371
369
|
# of +self+ from number of seconds since the Unix epoch.
|
372
370
|
#
|
373
371
|
# Time.zone = 'Hawaii' # => "Hawaii"
|
@@ -382,7 +380,7 @@ module ActiveSupport
|
|
382
380
|
Time.at(*args).utc.in_time_zone(self)
|
383
381
|
end
|
384
382
|
|
385
|
-
# Method for creating new ActiveSupport::TimeWithZone instance in time zone
|
383
|
+
# \Method for creating new ActiveSupport::TimeWithZone instance in time zone
|
386
384
|
# of +self+ from an ISO 8601 string.
|
387
385
|
#
|
388
386
|
# Time.zone = 'Hawaii' # => "Hawaii"
|
@@ -434,7 +432,7 @@ module ActiveSupport
|
|
434
432
|
raise ArgumentError, "invalid date"
|
435
433
|
end
|
436
434
|
|
437
|
-
# Method for creating new ActiveSupport::TimeWithZone instance in time zone
|
435
|
+
# \Method for creating new ActiveSupport::TimeWithZone instance in time zone
|
438
436
|
# of +self+ from parsed string.
|
439
437
|
#
|
440
438
|
# Time.zone = 'Hawaii' # => "Hawaii"
|
@@ -456,7 +454,7 @@ module ActiveSupport
|
|
456
454
|
parts_to_time(Date._parse(str, false), now)
|
457
455
|
end
|
458
456
|
|
459
|
-
# Method for creating new ActiveSupport::TimeWithZone instance in time zone
|
457
|
+
# \Method for creating new ActiveSupport::TimeWithZone instance in time zone
|
460
458
|
# of +self+ from an RFC 3339 string.
|
461
459
|
#
|
462
460
|
# Time.zone = 'Hawaii' # => "Hawaii"
|
@@ -554,15 +552,11 @@ module ActiveSupport
|
|
554
552
|
tzinfo.local_to_utc(time, dst)
|
555
553
|
end
|
556
554
|
|
557
|
-
|
558
|
-
# instances.
|
559
|
-
def period_for_utc(time)
|
555
|
+
def period_for_utc(time) # :nodoc:
|
560
556
|
tzinfo.period_for_utc(time)
|
561
557
|
end
|
562
558
|
|
563
|
-
|
564
|
-
# instances.
|
565
|
-
def period_for_local(time, dst = true)
|
559
|
+
def period_for_local(time, dst = true) # :nodoc:
|
566
560
|
tzinfo.period_for_local(time, dst) { |periods| periods.last }
|
567
561
|
end
|
568
562
|
|
@@ -570,6 +564,14 @@ module ActiveSupport
|
|
570
564
|
tzinfo.periods_for_local(time)
|
571
565
|
end
|
572
566
|
|
567
|
+
def abbr(time) # :nodoc:
|
568
|
+
tzinfo.abbr(time)
|
569
|
+
end
|
570
|
+
|
571
|
+
def dst?(time) # :nodoc:
|
572
|
+
tzinfo.dst?(time)
|
573
|
+
end
|
574
|
+
|
573
575
|
def init_with(coder) # :nodoc:
|
574
576
|
initialize(coder["name"])
|
575
577
|
end
|
data/lib/active_support.rb
CHANGED
@@ -57,11 +57,12 @@ module ActiveSupport
|
|
57
57
|
|
58
58
|
eager_autoload do
|
59
59
|
autoload :BacktraceCleaner
|
60
|
-
autoload :
|
60
|
+
autoload :Benchmark
|
61
61
|
autoload :Benchmarkable
|
62
62
|
autoload :Cache
|
63
63
|
autoload :Callbacks
|
64
64
|
autoload :Configurable
|
65
|
+
autoload :ClassAttribute
|
65
66
|
autoload :Deprecation
|
66
67
|
autoload :Delegation
|
67
68
|
autoload :Digest
|
@@ -115,9 +116,15 @@ module ActiveSupport
|
|
115
116
|
end
|
116
117
|
|
117
118
|
def self.to_time_preserves_timezone=(value)
|
118
|
-
|
119
|
+
if !value
|
119
120
|
ActiveSupport.deprecator.warn(
|
120
|
-
"
|
121
|
+
"`to_time` will always preserve the receiver timezone rather than system local time in Rails 8.1. " \
|
122
|
+
"To opt in to the new behavior, set `config.active_support.to_time_preserves_timezone = :zone`."
|
123
|
+
)
|
124
|
+
elsif value != :zone
|
125
|
+
ActiveSupport.deprecator.warn(
|
126
|
+
"`to_time` will always preserve the full timezone rather than offset of the receiver in Rails 8.1. " \
|
127
|
+
"To opt in to the new behavior, set `config.active_support.to_time_preserves_timezone = :zone`."
|
121
128
|
)
|
122
129
|
end
|
123
130
|
|