activesupport 7.1.3.4 → 7.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +123 -1084
- data/lib/active_support/array_inquirer.rb +1 -1
- data/lib/active_support/backtrace_cleaner.rb +15 -3
- data/lib/active_support/broadcast_logger.rb +5 -4
- data/lib/active_support/cache/file_store.rb +15 -10
- data/lib/active_support/cache/mem_cache_store.rb +16 -74
- data/lib/active_support/cache/memory_store.rb +2 -1
- data/lib/active_support/cache/redis_cache_store.rb +16 -13
- data/lib/active_support/cache/serializer_with_fallback.rb +0 -23
- data/lib/active_support/cache.rb +61 -68
- data/lib/active_support/callbacks.rb +74 -113
- data/lib/active_support/code_generator.rb +15 -10
- data/lib/active_support/core_ext/array/conversions.rb +0 -2
- 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 +0 -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/erb/util.rb +5 -0
- data/lib/active_support/core_ext/hash/keys.rb +4 -4
- data/lib/active_support/core_ext/module/attr_internal.rb +17 -6
- data/lib/active_support/core_ext/module/delegation.rb +20 -148
- 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/duplicable.rb +24 -15
- data/lib/active_support/core_ext/object/instance_variables.rb +11 -19
- data/lib/active_support/core_ext/object/json.rb +1 -1
- 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/output_safety.rb +0 -7
- data/lib/active_support/core_ext/time/calculations.rb +18 -28
- data/lib/active_support/core_ext/time/compatibility.rb +16 -0
- data/lib/active_support/core_ext/time/conversions.rb +0 -2
- data/lib/active_support/core_ext.rb +0 -1
- data/lib/active_support/current_attributes.rb +34 -40
- data/lib/active_support/delegation.rb +202 -0
- data/lib/active_support/dependencies/autoload.rb +0 -12
- 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 +7 -2
- 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 +11 -6
- data/lib/active_support/error_reporter.rb +41 -3
- data/lib/active_support/evented_file_update_checker.rb +0 -1
- 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 +3 -3
- data/lib/active_support/hash_with_indifferent_access.rb +6 -8
- data/lib/active_support/html_safe_translation.rb +7 -4
- data/lib/active_support/json/encoding.rb +1 -1
- data/lib/active_support/log_subscriber.rb +1 -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/messages/codec.rb +1 -1
- data/lib/active_support/multibyte/chars.rb +2 -2
- data/lib/active_support/notifications/fanout.rb +4 -7
- data/lib/active_support/notifications/instrumenter.rb +32 -21
- data/lib/active_support/notifications.rb +28 -27
- data/lib/active_support/number_helper/number_converter.rb +2 -2
- data/lib/active_support/option_merger.rb +2 -2
- data/lib/active_support/ordered_options.rb +53 -15
- data/lib/active_support/proxy_object.rb +8 -5
- data/lib/active_support/railtie.rb +4 -11
- data/lib/active_support/string_inquirer.rb +1 -1
- data/lib/active_support/subscriber.rb +1 -0
- data/lib/active_support/syntax_error_proxy.rb +1 -11
- data/lib/active_support/tagged_logging.rb +4 -1
- data/lib/active_support/test_case.rb +3 -1
- data/lib/active_support/testing/assertions.rb +4 -4
- 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 +18 -8
- data/lib/active_support/testing/method_call_assertions.rb +2 -16
- data/lib/active_support/testing/setup_and_teardown.rb +2 -0
- data/lib/active_support/testing/strict_warnings.rb +5 -4
- data/lib/active_support/testing/tests_without_assertions.rb +19 -0
- data/lib/active_support/testing/time_helpers.rb +3 -3
- data/lib/active_support/time_with_zone.rb +7 -3
- data/lib/active_support/values/time_zone.rb +10 -1
- data/lib/active_support/xml_mini.rb +11 -2
- data/lib/active_support.rb +3 -2
- metadata +35 -15
- data/lib/active_support/deprecation/instance_delegator.rb +0 -65
- data/lib/active_support/ruby_features.rb +0 -7
@@ -1,19 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "set"
|
4
|
-
|
5
3
|
class Module
|
6
|
-
|
7
|
-
|
8
|
-
class DelegationError < NoMethodError; end
|
9
|
-
|
10
|
-
RUBY_RESERVED_KEYWORDS = %w(__ENCODING__ __LINE__ __FILE__ alias and BEGIN begin break
|
11
|
-
case class def defined? do else elsif END end ensure false for if in module next nil
|
12
|
-
not or redo rescue retry return self super then true undef unless until when while yield)
|
13
|
-
DELEGATION_RESERVED_KEYWORDS = %w(_ arg args block)
|
14
|
-
DELEGATION_RESERVED_METHOD_NAMES = Set.new(
|
15
|
-
RUBY_RESERVED_KEYWORDS + DELEGATION_RESERVED_KEYWORDS
|
16
|
-
).freeze
|
4
|
+
require "active_support/delegation"
|
5
|
+
DelegationError = ActiveSupport::DelegationError # :nodoc:
|
17
6
|
|
18
7
|
# Provides a +delegate+ class method to easily expose contained objects'
|
19
8
|
# public methods as your own.
|
@@ -21,7 +10,7 @@ class Module
|
|
21
10
|
# ==== Options
|
22
11
|
# * <tt>:to</tt> - Specifies the target object name as a symbol or string
|
23
12
|
# * <tt>:prefix</tt> - Prefixes the new method with the target name or a custom prefix
|
24
|
-
# * <tt>:allow_nil</tt> - If set to true, prevents a +
|
13
|
+
# * <tt>:allow_nil</tt> - If set to true, prevents a +ActiveSupport::DelegationError+
|
25
14
|
# from being raised
|
26
15
|
# * <tt>:private</tt> - If set to true, changes method visibility to private
|
27
16
|
#
|
@@ -132,7 +121,7 @@ class Module
|
|
132
121
|
# User.new.age # => 2
|
133
122
|
#
|
134
123
|
# If the target is +nil+ and does not respond to the delegated method a
|
135
|
-
# +
|
124
|
+
# +ActiveSupport::DelegationError+ is raised. If you wish to instead return +nil+,
|
136
125
|
# use the <tt>:allow_nil</tt> option.
|
137
126
|
#
|
138
127
|
# class User < ActiveRecord::Base
|
@@ -141,7 +130,7 @@ class Module
|
|
141
130
|
# end
|
142
131
|
#
|
143
132
|
# User.new.age
|
144
|
-
# # =>
|
133
|
+
# # => ActiveSupport::DelegationError: User#age delegated to profile.age, but profile is nil
|
145
134
|
#
|
146
135
|
# But if not having a profile yet is fine and should not be an error
|
147
136
|
# condition:
|
@@ -169,104 +158,15 @@ class Module
|
|
169
158
|
#
|
170
159
|
# The target method must be public, otherwise it will raise +NoMethodError+.
|
171
160
|
def delegate(*methods, to: nil, prefix: nil, allow_nil: nil, private: nil)
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
if prefix
|
182
|
-
"#{prefix == true ? to : prefix}_"
|
183
|
-
else
|
184
|
-
""
|
185
|
-
end
|
186
|
-
|
187
|
-
location = caller_locations(1, 1).first
|
188
|
-
file, line = location.path, location.lineno
|
189
|
-
|
190
|
-
receiver = to.to_s
|
191
|
-
receiver = "self.#{receiver}" if DELEGATION_RESERVED_METHOD_NAMES.include?(receiver)
|
192
|
-
|
193
|
-
method_def = []
|
194
|
-
method_names = []
|
195
|
-
|
196
|
-
method_def << "self.private" if private
|
197
|
-
|
198
|
-
methods.each do |method|
|
199
|
-
method_name = prefix ? "#{method_prefix}#{method}" : method
|
200
|
-
method_names << method_name.to_sym
|
201
|
-
|
202
|
-
# Attribute writer methods only accept one argument. Makes sure []=
|
203
|
-
# methods still accept two arguments.
|
204
|
-
definition = \
|
205
|
-
if /[^\]]=\z/.match?(method)
|
206
|
-
"arg"
|
207
|
-
else
|
208
|
-
method_object =
|
209
|
-
begin
|
210
|
-
if to.is_a?(Module)
|
211
|
-
to.method(method)
|
212
|
-
elsif receiver == "self.class"
|
213
|
-
method(method)
|
214
|
-
end
|
215
|
-
rescue NameError
|
216
|
-
# Do nothing. Fall back to `"..."`
|
217
|
-
end
|
218
|
-
|
219
|
-
if method_object
|
220
|
-
parameters = method_object.parameters
|
221
|
-
|
222
|
-
if (parameters.map(&:first) & [:opt, :rest, :keyreq, :key, :keyrest]).any?
|
223
|
-
"..."
|
224
|
-
else
|
225
|
-
defn = parameters.filter_map { |type, arg| arg if type == :req }
|
226
|
-
defn << "&block"
|
227
|
-
defn.join(", ")
|
228
|
-
end
|
229
|
-
else
|
230
|
-
"..."
|
231
|
-
end
|
232
|
-
end
|
233
|
-
|
234
|
-
# The following generated method calls the target exactly once, storing
|
235
|
-
# the returned value in a dummy variable.
|
236
|
-
#
|
237
|
-
# Reason is twofold: On one hand doing less calls is in general better.
|
238
|
-
# On the other hand it could be that the target has side-effects,
|
239
|
-
# whereas conceptually, from the user point of view, the delegator should
|
240
|
-
# be doing one call.
|
241
|
-
if allow_nil
|
242
|
-
method = method.to_s
|
243
|
-
|
244
|
-
method_def <<
|
245
|
-
"def #{method_name}(#{definition})" <<
|
246
|
-
" _ = #{receiver}" <<
|
247
|
-
" if !_.nil? || nil.respond_to?(:#{method})" <<
|
248
|
-
" _.#{method}(#{definition})" <<
|
249
|
-
" end" <<
|
250
|
-
"end"
|
251
|
-
else
|
252
|
-
method = method.to_s
|
253
|
-
method_name = method_name.to_s
|
254
|
-
|
255
|
-
method_def <<
|
256
|
-
"def #{method_name}(#{definition})" <<
|
257
|
-
" _ = #{receiver}" <<
|
258
|
-
" _.#{method}(#{definition})" <<
|
259
|
-
"rescue NoMethodError => e" <<
|
260
|
-
" if _.nil? && e.name == :#{method}" <<
|
261
|
-
%( raise DelegationError, "#{self}##{method_name} delegated to #{receiver}.#{method}, but #{receiver} is nil: \#{self.inspect}") <<
|
262
|
-
" else" <<
|
263
|
-
" raise" <<
|
264
|
-
" end" <<
|
265
|
-
"end"
|
266
|
-
end
|
267
|
-
end
|
268
|
-
module_eval(method_def.join(";"), file, line)
|
269
|
-
method_names
|
161
|
+
::ActiveSupport::Delegation.generate(
|
162
|
+
self,
|
163
|
+
methods,
|
164
|
+
location: caller_locations(1, 1).first,
|
165
|
+
to: to,
|
166
|
+
prefix: prefix,
|
167
|
+
allow_nil: allow_nil,
|
168
|
+
private: private,
|
169
|
+
)
|
270
170
|
end
|
271
171
|
|
272
172
|
# When building decorators, a common pattern may emerge:
|
@@ -308,7 +208,7 @@ class Module
|
|
308
208
|
# variables, methods, constants, etc.
|
309
209
|
#
|
310
210
|
# The delegated method must be public on the target, otherwise it will
|
311
|
-
# raise +DelegationError+. If you wish to instead return +nil+,
|
211
|
+
# raise +ActiveSupport::DelegationError+. If you wish to instead return +nil+,
|
312
212
|
# use the <tt>:allow_nil</tt> option.
|
313
213
|
#
|
314
214
|
# The <tt>marshal_dump</tt> and <tt>_dump</tt> methods are exempt from
|
@@ -316,38 +216,10 @@ class Module
|
|
316
216
|
# <tt>Marshal.dump(object)</tt>, should the delegation target method
|
317
217
|
# of <tt>object</tt> add or remove instance variables.
|
318
218
|
def delegate_missing_to(target, allow_nil: nil)
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
# It may look like an oversight, but we deliberately do not pass
|
325
|
-
# +include_private+, because they do not get delegated.
|
326
|
-
|
327
|
-
return false if name == :marshal_dump || name == :_dump
|
328
|
-
#{target}.respond_to?(name) || super
|
329
|
-
end
|
330
|
-
|
331
|
-
def method_missing(method, *args, &block)
|
332
|
-
if #{target}.respond_to?(method)
|
333
|
-
#{target}.public_send(method, *args, &block)
|
334
|
-
else
|
335
|
-
begin
|
336
|
-
super
|
337
|
-
rescue NoMethodError
|
338
|
-
if #{target}.nil?
|
339
|
-
if #{allow_nil == true}
|
340
|
-
nil
|
341
|
-
else
|
342
|
-
raise DelegationError, "\#{method} delegated to #{target}, but #{target} is nil"
|
343
|
-
end
|
344
|
-
else
|
345
|
-
raise
|
346
|
-
end
|
347
|
-
end
|
348
|
-
end
|
349
|
-
end
|
350
|
-
ruby2_keywords(:method_missing)
|
351
|
-
RUBY
|
219
|
+
::ActiveSupport::Delegation.generate_method_missing(
|
220
|
+
self,
|
221
|
+
target,
|
222
|
+
allow_nil: allow_nil,
|
223
|
+
)
|
352
224
|
end
|
353
225
|
end
|
@@ -14,15 +14,12 @@ class Module
|
|
14
14
|
# Kernel.warn message
|
15
15
|
# end
|
16
16
|
# end
|
17
|
-
def deprecate(*method_names, deprecator
|
17
|
+
def deprecate(*method_names, deprecator:, **options)
|
18
18
|
if deprecator.is_a?(ActiveSupport::Deprecation)
|
19
19
|
deprecator.deprecate_methods(self, *method_names, **options)
|
20
20
|
elsif deprecator
|
21
21
|
# we just need any instance to call deprecate_methods, but the deprecation will be emitted by deprecator
|
22
22
|
ActiveSupport.deprecator.deprecate_methods(self, *method_names, **options, deprecator: deprecator)
|
23
|
-
else
|
24
|
-
ActiveSupport.deprecator.warn("Module.deprecate without a deprecator is deprecated")
|
25
|
-
ActiveSupport::Deprecation._instance.deprecate_methods(self, *method_names, **options)
|
26
23
|
end
|
27
24
|
end
|
28
25
|
end
|
@@ -140,6 +140,6 @@ module ActiveSupport
|
|
140
140
|
end
|
141
141
|
end
|
142
142
|
|
143
|
-
Integer.
|
144
|
-
Float.
|
145
|
-
BigDecimal.
|
143
|
+
Integer.include ActiveSupport::NumericWithFormat
|
144
|
+
Float.include ActiveSupport::NumericWithFormat
|
145
|
+
BigDecimal.include ActiveSupport::NumericWithFormat
|
@@ -16,7 +16,7 @@ class Object
|
|
16
16
|
#
|
17
17
|
# @return [true, false]
|
18
18
|
def blank?
|
19
|
-
respond_to?(:empty?) ? !!empty? :
|
19
|
+
respond_to?(:empty?) ? !!empty? : false
|
20
20
|
end
|
21
21
|
|
22
22
|
# An object is present if it's not blank.
|
@@ -56,6 +56,10 @@ class NilClass
|
|
56
56
|
def blank?
|
57
57
|
true
|
58
58
|
end
|
59
|
+
|
60
|
+
def present? # :nodoc:
|
61
|
+
false
|
62
|
+
end
|
59
63
|
end
|
60
64
|
|
61
65
|
class FalseClass
|
@@ -67,6 +71,10 @@ class FalseClass
|
|
67
71
|
def blank?
|
68
72
|
true
|
69
73
|
end
|
74
|
+
|
75
|
+
def present? # :nodoc:
|
76
|
+
false
|
77
|
+
end
|
70
78
|
end
|
71
79
|
|
72
80
|
class TrueClass
|
@@ -78,6 +86,10 @@ class TrueClass
|
|
78
86
|
def blank?
|
79
87
|
false
|
80
88
|
end
|
89
|
+
|
90
|
+
def present? # :nodoc:
|
91
|
+
true
|
92
|
+
end
|
81
93
|
end
|
82
94
|
|
83
95
|
class Array
|
@@ -88,6 +100,10 @@ class Array
|
|
88
100
|
#
|
89
101
|
# @return [true, false]
|
90
102
|
alias_method :blank?, :empty?
|
103
|
+
|
104
|
+
def present? # :nodoc:
|
105
|
+
!empty?
|
106
|
+
end
|
91
107
|
end
|
92
108
|
|
93
109
|
class Hash
|
@@ -98,6 +114,22 @@ class Hash
|
|
98
114
|
#
|
99
115
|
# @return [true, false]
|
100
116
|
alias_method :blank?, :empty?
|
117
|
+
|
118
|
+
def present? # :nodoc:
|
119
|
+
!empty?
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
class Symbol
|
124
|
+
# A Symbol is blank if it's empty:
|
125
|
+
#
|
126
|
+
# :''.blank? # => true
|
127
|
+
# :symbol.blank? # => false
|
128
|
+
alias_method :blank?, :empty?
|
129
|
+
|
130
|
+
def present? # :nodoc:
|
131
|
+
!empty?
|
132
|
+
end
|
101
133
|
end
|
102
134
|
|
103
135
|
class String
|
@@ -129,6 +161,10 @@ class String
|
|
129
161
|
ENCODED_BLANKS[self.encoding].match?(self)
|
130
162
|
end
|
131
163
|
end
|
164
|
+
|
165
|
+
def present? # :nodoc:
|
166
|
+
!blank?
|
167
|
+
end
|
132
168
|
end
|
133
169
|
|
134
170
|
class Numeric # :nodoc:
|
@@ -141,6 +177,10 @@ class Numeric # :nodoc:
|
|
141
177
|
def blank?
|
142
178
|
false
|
143
179
|
end
|
180
|
+
|
181
|
+
def present?
|
182
|
+
true
|
183
|
+
end
|
144
184
|
end
|
145
185
|
|
146
186
|
class Time # :nodoc:
|
@@ -152,4 +192,8 @@ class Time # :nodoc:
|
|
152
192
|
def blank?
|
153
193
|
false
|
154
194
|
end
|
195
|
+
|
196
|
+
def present?
|
197
|
+
true
|
198
|
+
end
|
155
199
|
end
|
@@ -28,23 +28,32 @@ class Object
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
def duplicable?
|
37
|
-
false
|
38
|
-
end
|
31
|
+
methods_are_duplicable = begin
|
32
|
+
Object.instance_method(:duplicable?).dup
|
33
|
+
true
|
34
|
+
rescue TypeError
|
35
|
+
false
|
39
36
|
end
|
40
37
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
38
|
+
unless methods_are_duplicable
|
39
|
+
class Method
|
40
|
+
# Methods are not duplicable:
|
41
|
+
#
|
42
|
+
# method(:puts).duplicable? # => false
|
43
|
+
# method(:puts).dup # => TypeError: allocator undefined for Method
|
44
|
+
def duplicable?
|
45
|
+
false
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class UnboundMethod
|
50
|
+
# Unbound methods are not duplicable:
|
51
|
+
#
|
52
|
+
# method(:puts).unbind.duplicable? # => false
|
53
|
+
# method(:puts).unbind.dup # => TypeError: allocator undefined for UnboundMethod
|
54
|
+
def duplicable?
|
55
|
+
false
|
56
|
+
end
|
48
57
|
end
|
49
58
|
end
|
50
59
|
|
@@ -17,24 +17,16 @@ class Object
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
instance_variables.map(&:name)
|
32
|
-
end
|
33
|
-
else
|
34
|
-
def instance_variable_names
|
35
|
-
variables = instance_variables
|
36
|
-
variables.map! { |s| s.to_s.freeze }
|
37
|
-
variables
|
38
|
-
end
|
20
|
+
# Returns an array of instance variable names as strings including "@".
|
21
|
+
#
|
22
|
+
# class C
|
23
|
+
# def initialize(x, y)
|
24
|
+
# @x, @y = x, y
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# C.new(0, 1).instance_variable_names # => ["@y", "@x"]
|
29
|
+
def instance_variable_names
|
30
|
+
instance_variables.map(&:name)
|
39
31
|
end
|
40
32
|
end
|
@@ -46,7 +46,7 @@ module ActiveSupport
|
|
46
46
|
end
|
47
47
|
|
48
48
|
[Enumerable, Object, Array, FalseClass, Float, Hash, Integer, NilClass, String, TrueClass].reverse_each do |klass|
|
49
|
-
klass.
|
49
|
+
klass.include(ActiveSupport::ToJsonWithActiveSupportEncoder)
|
50
50
|
end
|
51
51
|
|
52
52
|
class Module
|
@@ -4,11 +4,13 @@ class Object
|
|
4
4
|
# Set and restore public attributes around a block.
|
5
5
|
#
|
6
6
|
# client.timeout # => 5
|
7
|
-
# client.with(timeout: 1) do
|
8
|
-
#
|
7
|
+
# client.with(timeout: 1) do |c|
|
8
|
+
# c.timeout # => 1
|
9
9
|
# end
|
10
10
|
# client.timeout # => 5
|
11
11
|
#
|
12
|
+
# The receiver is yielded to the provided block.
|
13
|
+
#
|
12
14
|
# This method is a shorthand for the common begin/ensure pattern:
|
13
15
|
#
|
14
16
|
# old_value = object.attribute
|
@@ -28,7 +30,7 @@ class Object
|
|
28
30
|
old_values[key] = public_send(key)
|
29
31
|
public_send("#{key}=", value)
|
30
32
|
end
|
31
|
-
yield
|
33
|
+
yield self
|
32
34
|
ensure
|
33
35
|
old_values.each do |key, old_value|
|
34
36
|
public_send("#{key}=", old_value)
|
@@ -4,7 +4,7 @@ class Range
|
|
4
4
|
# Compare two ranges and see if they overlap each other
|
5
5
|
# (1..5).overlap?(4..6) # => true
|
6
6
|
# (1..5).overlap?(7..9) # => false
|
7
|
-
unless Range.method_defined?(:overlap?)
|
7
|
+
unless Range.method_defined?(:overlap?) # Ruby 3.3+
|
8
8
|
def overlap?(other)
|
9
9
|
raise TypeError unless other.is_a? Range
|
10
10
|
|
@@ -16,18 +16,8 @@ module SecureRandom
|
|
16
16
|
#
|
17
17
|
# p SecureRandom.base58 # => "4kUgL2pdQMSCQtjE"
|
18
18
|
# p SecureRandom.base58(24) # => "77TMHrHJFvFDwodq8w7Ev2m7"
|
19
|
-
|
20
|
-
|
21
|
-
SecureRandom.alphanumeric(n, chars: BASE58_ALPHABET)
|
22
|
-
end
|
23
|
-
else
|
24
|
-
def self.base58(n = 16)
|
25
|
-
SecureRandom.random_bytes(n).unpack("C*").map do |byte|
|
26
|
-
idx = byte % 64
|
27
|
-
idx = SecureRandom.random_number(58) if idx >= 58
|
28
|
-
BASE58_ALPHABET[idx]
|
29
|
-
end.join
|
30
|
-
end
|
19
|
+
def self.base58(n = 16)
|
20
|
+
SecureRandom.alphanumeric(n, chars: BASE58_ALPHABET)
|
31
21
|
end
|
32
22
|
|
33
23
|
# SecureRandom.base36 generates a random base36 string in lowercase.
|
@@ -41,17 +31,11 @@ module SecureRandom
|
|
41
31
|
#
|
42
32
|
# p SecureRandom.base36 # => "4kugl2pdqmscqtje"
|
43
33
|
# p SecureRandom.base36(24) # => "77tmhrhjfvfdwodq8w7ev2m7"
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
SecureRandom.random_bytes(n).unpack("C*").map do |byte|
|
51
|
-
idx = byte % 64
|
52
|
-
idx = SecureRandom.random_number(36) if idx >= 36
|
53
|
-
BASE36_ALPHABET[idx]
|
54
|
-
end.join
|
55
|
-
end
|
34
|
+
def self.base36(n = 16)
|
35
|
+
SecureRandom.random_bytes(n).unpack("C*").map do |byte|
|
36
|
+
idx = byte % 64
|
37
|
+
idx = SecureRandom.random_number(36) if idx >= 36
|
38
|
+
BASE36_ALPHABET[idx]
|
39
|
+
end.join
|
56
40
|
end
|
57
41
|
end
|
@@ -22,7 +22,7 @@ class String
|
|
22
22
|
def to_time(form = :local)
|
23
23
|
parts = Date._parse(self, false)
|
24
24
|
used_keys = %i(year mon mday hour min sec sec_fraction offset)
|
25
|
-
return if
|
25
|
+
return if !parts.keys.intersect?(used_keys)
|
26
26
|
|
27
27
|
now = Time.now
|
28
28
|
time = Time.new(
|
@@ -109,7 +109,7 @@ class String
|
|
109
109
|
when omission.bytesize == truncate_to
|
110
110
|
omission.dup
|
111
111
|
else
|
112
|
-
self.class.new.tap do |cut|
|
112
|
+
self.class.new.force_encoding(encoding).tap do |cut|
|
113
113
|
cut_at = truncate_to - omission.bytesize
|
114
114
|
|
115
115
|
each_grapheme_cluster do |grapheme|
|
@@ -77,13 +77,6 @@ module ActiveSupport # :nodoc:
|
|
77
77
|
@html_safe = other.html_safe?
|
78
78
|
end
|
79
79
|
|
80
|
-
def clone_empty # :nodoc:
|
81
|
-
ActiveSupport.deprecator.warn <<~EOM
|
82
|
-
ActiveSupport::SafeBuffer#clone_empty is deprecated and will be removed in Rails 7.2.
|
83
|
-
EOM
|
84
|
-
self[0, 0]
|
85
|
-
end
|
86
|
-
|
87
80
|
def concat(value)
|
88
81
|
unless value.nil?
|
89
82
|
super(implicit_html_escape_interpolated_argument(value))
|
@@ -42,20 +42,20 @@ class Time
|
|
42
42
|
|
43
43
|
# Layers additional behavior on Time.at so that ActiveSupport::TimeWithZone and DateTime
|
44
44
|
# instances can be used when called with a single argument
|
45
|
-
def at_with_coercion(*args
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
at_without_coercion(time_or_number.to_f).getlocal
|
45
|
+
def at_with_coercion(time_or_number, *args)
|
46
|
+
if args.empty?
|
47
|
+
if time_or_number.is_a?(ActiveSupport::TimeWithZone)
|
48
|
+
at_without_coercion(time_or_number.to_r).getlocal
|
49
|
+
elsif time_or_number.is_a?(DateTime)
|
50
|
+
at_without_coercion(time_or_number.to_f).getlocal
|
51
|
+
else
|
52
|
+
at_without_coercion(time_or_number)
|
53
|
+
end
|
55
54
|
else
|
56
|
-
at_without_coercion(time_or_number)
|
55
|
+
at_without_coercion(time_or_number, *args)
|
57
56
|
end
|
58
57
|
end
|
58
|
+
ruby2_keywords :at_with_coercion
|
59
59
|
alias_method :at_without_coercion, :at
|
60
60
|
alias_method :at, :at_with_coercion
|
61
61
|
|
@@ -108,21 +108,6 @@ class Time
|
|
108
108
|
subsec
|
109
109
|
end
|
110
110
|
|
111
|
-
unless Time.method_defined?(:floor)
|
112
|
-
def floor(precision = 0)
|
113
|
-
change(nsec: 0) + subsec.floor(precision)
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
# Restricted Ruby version due to a bug in `Time#ceil`
|
118
|
-
# See https://bugs.ruby-lang.org/issues/17025 for more details
|
119
|
-
if RUBY_VERSION <= "2.8"
|
120
|
-
remove_possible_method :ceil
|
121
|
-
def ceil(precision = 0)
|
122
|
-
change(nsec: 0) + subsec.ceil(precision)
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
111
|
# Returns a new Time where one or more of the elements have been changed according
|
127
112
|
# to the +options+ parameter. The time options (<tt>:hour</tt>, <tt>:min</tt>,
|
128
113
|
# <tt>:sec</tt>, <tt>:usec</tt>, <tt>:nsec</tt>) reset cascadingly, so if only
|
@@ -159,7 +144,7 @@ class Time
|
|
159
144
|
::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, new_offset)
|
160
145
|
elsif utc?
|
161
146
|
::Time.utc(new_year, new_month, new_day, new_hour, new_min, new_sec)
|
162
|
-
elsif zone
|
147
|
+
elsif zone.respond_to?(:utc_to_local)
|
163
148
|
new_time = ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, zone)
|
164
149
|
|
165
150
|
# When there are two occurrences of a nominal time due to DST ending,
|
@@ -334,7 +319,12 @@ class Time
|
|
334
319
|
if other.class == Time
|
335
320
|
compare_without_coercion(other)
|
336
321
|
elsif other.is_a?(Time)
|
337
|
-
|
322
|
+
# also avoid ActiveSupport::TimeWithZone#to_time before Rails 8.0
|
323
|
+
if other.respond_to?(:comparable_time)
|
324
|
+
compare_without_coercion(other.comparable_time)
|
325
|
+
else
|
326
|
+
compare_without_coercion(other.to_time)
|
327
|
+
end
|
338
328
|
else
|
339
329
|
to_datetime <=> other
|
340
330
|
end
|
@@ -13,4 +13,20 @@ class Time
|
|
13
13
|
def to_time
|
14
14
|
preserve_timezone ? self : getlocal
|
15
15
|
end
|
16
|
+
|
17
|
+
def preserve_timezone # :nodoc:
|
18
|
+
active_support_local_zone == zone || super
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
@@active_support_local_tz = nil
|
23
|
+
|
24
|
+
def active_support_local_zone
|
25
|
+
@@active_support_local_zone = nil if @@active_support_local_tz != ENV["TZ"]
|
26
|
+
@@active_support_local_zone ||=
|
27
|
+
begin
|
28
|
+
@@active_support_local_tz = ENV["TZ"]
|
29
|
+
Time.new.zone
|
30
|
+
end
|
31
|
+
end
|
16
32
|
end
|
@@ -58,8 +58,6 @@ class Time
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
alias_method :to_formatted_s, :to_fs
|
61
|
-
alias_method :to_default_s, :to_s
|
62
|
-
deprecate to_default_s: :to_s, deprecator: ActiveSupport.deprecator
|
63
61
|
|
64
62
|
# Returns a formatted string of the offset from UTC, or an alternative
|
65
63
|
# string if the time zone is already UTC.
|