activesupport 6.0.3.7 → 7.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activesupport might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +220 -533
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/lib/active_support/actionable_error.rb +1 -1
- data/lib/active_support/array_inquirer.rb +2 -2
- data/lib/active_support/backtrace_cleaner.rb +3 -3
- data/lib/active_support/benchmarkable.rb +3 -3
- data/lib/active_support/cache/file_store.rb +18 -11
- data/lib/active_support/cache/mem_cache_store.rb +143 -37
- data/lib/active_support/cache/memory_store.rb +56 -28
- data/lib/active_support/cache/null_store.rb +10 -2
- data/lib/active_support/cache/redis_cache_store.rb +63 -88
- data/lib/active_support/cache/strategy/local_cache.rb +46 -57
- data/lib/active_support/cache.rb +273 -82
- data/lib/active_support/callbacks.rb +226 -118
- data/lib/active_support/code_generator.rb +65 -0
- data/lib/active_support/concern.rb +49 -5
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +2 -4
- data/lib/active_support/concurrency/share_lock.rb +2 -2
- data/lib/active_support/configurable.rb +9 -6
- data/lib/active_support/configuration_file.rb +51 -0
- data/lib/active_support/core_ext/array/access.rb +1 -5
- data/lib/active_support/core_ext/array/conversions.rb +9 -7
- data/lib/active_support/core_ext/array/deprecated_conversions.rb +25 -0
- data/lib/active_support/core_ext/array/grouping.rb +6 -6
- data/lib/active_support/core_ext/array.rb +1 -0
- data/lib/active_support/core_ext/benchmark.rb +2 -2
- data/lib/active_support/core_ext/big_decimal/conversions.rb +1 -1
- data/lib/active_support/core_ext/class/attribute.rb +34 -44
- data/lib/active_support/core_ext/class/subclasses.rb +21 -40
- data/lib/active_support/core_ext/date/blank.rb +1 -1
- data/lib/active_support/core_ext/date/calculations.rb +4 -4
- data/lib/active_support/core_ext/date/conversions.rb +5 -4
- data/lib/active_support/core_ext/date/deprecated_conversions.rb +26 -0
- data/lib/active_support/core_ext/date.rb +1 -0
- data/lib/active_support/core_ext/date_and_time/calculations.rb +13 -0
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
- data/lib/active_support/core_ext/date_time/blank.rb +1 -1
- data/lib/active_support/core_ext/date_time/conversions.rb +5 -5
- data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +22 -0
- data/lib/active_support/core_ext/date_time.rb +1 -0
- data/lib/active_support/core_ext/digest/uuid.rb +39 -13
- data/lib/active_support/core_ext/enumerable.rb +139 -15
- data/lib/active_support/core_ext/file/atomic.rb +1 -1
- data/lib/active_support/core_ext/hash/conversions.rb +2 -2
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +1 -1
- data/lib/active_support/core_ext/hash/except.rb +1 -1
- data/lib/active_support/core_ext/hash/keys.rb +2 -2
- data/lib/active_support/core_ext/hash/slice.rb +3 -2
- data/lib/active_support/core_ext/kernel/reporting.rb +4 -4
- data/lib/active_support/core_ext/load_error.rb +1 -1
- data/lib/active_support/core_ext/module/attr_internal.rb +2 -2
- data/lib/active_support/core_ext/module/attribute_accessors.rb +25 -29
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +26 -13
- data/lib/active_support/core_ext/module/concerning.rb +8 -2
- data/lib/active_support/core_ext/module/delegation.rb +40 -36
- data/lib/active_support/core_ext/module/introspection.rb +1 -25
- data/lib/active_support/core_ext/name_error.rb +23 -2
- data/lib/active_support/core_ext/numeric/conversions.rb +79 -72
- data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +60 -0
- data/lib/active_support/core_ext/numeric.rb +1 -0
- data/lib/active_support/core_ext/object/blank.rb +2 -2
- data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
- data/lib/active_support/core_ext/object/duplicable.rb +11 -0
- data/lib/active_support/core_ext/object/json.rb +42 -26
- data/lib/active_support/core_ext/object/to_query.rb +2 -2
- data/lib/active_support/core_ext/object/try.rb +20 -20
- data/lib/active_support/core_ext/object/with_options.rb +20 -1
- data/lib/active_support/core_ext/pathname/existence.rb +21 -0
- data/lib/active_support/core_ext/pathname.rb +3 -0
- data/lib/active_support/core_ext/range/compare_range.rb +6 -25
- data/lib/active_support/core_ext/range/conversions.rb +8 -8
- data/lib/active_support/core_ext/range/deprecated_conversions.rb +26 -0
- data/lib/active_support/core_ext/range/each.rb +1 -1
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +4 -20
- data/lib/active_support/core_ext/range.rb +1 -1
- data/lib/active_support/core_ext/regexp.rb +8 -1
- data/lib/active_support/core_ext/string/access.rb +5 -24
- data/lib/active_support/core_ext/string/conversions.rb +1 -0
- data/lib/active_support/core_ext/string/filters.rb +1 -1
- data/lib/active_support/core_ext/string/inflections.rb +39 -5
- data/lib/active_support/core_ext/string/inquiry.rb +1 -0
- data/lib/active_support/core_ext/string/multibyte.rb +2 -2
- data/lib/active_support/core_ext/string/output_safety.rb +69 -45
- data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -2
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +6 -0
- data/lib/active_support/core_ext/symbol.rb +3 -0
- data/lib/active_support/core_ext/time/calculations.rb +26 -6
- data/lib/active_support/core_ext/time/conversions.rb +6 -3
- data/lib/active_support/core_ext/time/deprecated_conversions.rb +22 -0
- data/lib/active_support/core_ext/time/zones.rb +4 -19
- data/lib/active_support/core_ext/time.rb +1 -0
- data/lib/active_support/core_ext/uri.rb +3 -23
- data/lib/active_support/core_ext.rb +2 -1
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/current_attributes.rb +39 -16
- data/lib/active_support/dependencies/interlock.rb +10 -18
- data/lib/active_support/dependencies/require_dependency.rb +28 -0
- data/lib/active_support/dependencies.rb +58 -764
- data/lib/active_support/deprecation/behaviors.rb +19 -3
- data/lib/active_support/deprecation/disallowed.rb +56 -0
- data/lib/active_support/deprecation/instance_delegator.rb +0 -1
- data/lib/active_support/deprecation/method_wrappers.rb +6 -5
- data/lib/active_support/deprecation/proxy_wrappers.rb +4 -4
- data/lib/active_support/deprecation/reporting.rb +50 -7
- data/lib/active_support/deprecation.rb +6 -1
- data/lib/active_support/descendants_tracker.rb +177 -64
- data/lib/active_support/digest.rb +5 -3
- data/lib/active_support/duration/iso8601_parser.rb +3 -3
- data/lib/active_support/duration/iso8601_serializer.rb +24 -10
- data/lib/active_support/duration.rb +134 -55
- data/lib/active_support/encrypted_configuration.rb +11 -1
- data/lib/active_support/encrypted_file.rb +20 -3
- data/lib/active_support/environment_inquirer.rb +20 -0
- data/lib/active_support/error_reporter.rb +117 -0
- data/lib/active_support/evented_file_update_checker.rb +70 -134
- data/lib/active_support/execution_context/test_helper.rb +13 -0
- data/lib/active_support/execution_context.rb +53 -0
- data/lib/active_support/execution_wrapper.rb +30 -4
- data/lib/active_support/executor/test_helper.rb +7 -0
- data/lib/active_support/fork_tracker.rb +71 -0
- data/lib/active_support/gem_version.rb +3 -3
- data/lib/active_support/hash_with_indifferent_access.rb +51 -25
- data/lib/active_support/html_safe_translation.rb +43 -0
- data/lib/active_support/i18n.rb +1 -0
- data/lib/active_support/i18n_railtie.rb +14 -19
- data/lib/active_support/inflector/inflections.rb +24 -9
- data/lib/active_support/inflector/methods.rb +29 -49
- data/lib/active_support/inflector/transliterate.rb +4 -4
- data/lib/active_support/isolated_execution_state.rb +56 -0
- data/lib/active_support/json/decoding.rb +4 -4
- data/lib/active_support/json/encoding.rb +8 -4
- data/lib/active_support/key_generator.rb +19 -2
- data/lib/active_support/locale/en.yml +8 -4
- data/lib/active_support/log_subscriber.rb +21 -3
- data/lib/active_support/logger.rb +1 -1
- data/lib/active_support/logger_silence.rb +2 -26
- data/lib/active_support/logger_thread_safe_level.rb +34 -21
- data/lib/active_support/message_encryptor.rb +12 -10
- data/lib/active_support/message_verifier.rb +50 -18
- data/lib/active_support/messages/metadata.rb +11 -3
- data/lib/active_support/messages/rotation_configuration.rb +2 -1
- data/lib/active_support/messages/rotator.rb +6 -5
- data/lib/active_support/multibyte/chars.rb +13 -52
- data/lib/active_support/multibyte/unicode.rb +1 -87
- data/lib/active_support/multibyte.rb +1 -1
- data/lib/active_support/notifications/fanout.rb +110 -69
- data/lib/active_support/notifications/instrumenter.rb +37 -29
- data/lib/active_support/notifications.rb +47 -26
- data/lib/active_support/number_helper/number_converter.rb +2 -4
- data/lib/active_support/number_helper/number_to_currency_converter.rb +10 -9
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_human_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +2 -2
- data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +9 -5
- data/lib/active_support/number_helper/rounding_helper.rb +12 -32
- data/lib/active_support/number_helper.rb +29 -16
- data/lib/active_support/option_merger.rb +9 -16
- data/lib/active_support/ordered_hash.rb +1 -1
- data/lib/active_support/ordered_options.rb +8 -2
- data/lib/active_support/parameter_filter.rb +21 -11
- data/lib/active_support/per_thread_registry.rb +6 -1
- data/lib/active_support/rails.rb +1 -4
- data/lib/active_support/railtie.rb +77 -5
- data/lib/active_support/rescuable.rb +6 -6
- data/lib/active_support/ruby_features.rb +7 -0
- data/lib/active_support/secure_compare_rotator.rb +51 -0
- data/lib/active_support/security_utils.rb +19 -12
- data/lib/active_support/string_inquirer.rb +2 -2
- data/lib/active_support/subscriber.rb +19 -25
- data/lib/active_support/tagged_logging.rb +31 -6
- data/lib/active_support/test_case.rb +9 -21
- data/lib/active_support/testing/assertions.rb +49 -12
- data/lib/active_support/testing/deprecation.rb +52 -1
- data/lib/active_support/testing/isolation.rb +2 -2
- data/lib/active_support/testing/method_call_assertions.rb +5 -5
- data/lib/active_support/testing/parallelization/server.rb +82 -0
- data/lib/active_support/testing/parallelization/worker.rb +103 -0
- data/lib/active_support/testing/parallelization.rb +16 -95
- data/lib/active_support/testing/parallelize_executor.rb +76 -0
- data/lib/active_support/testing/stream.rb +3 -5
- data/lib/active_support/testing/tagged_logging.rb +1 -1
- data/lib/active_support/testing/time_helpers.rb +53 -5
- data/lib/active_support/time_with_zone.rb +120 -55
- data/lib/active_support/values/time_zone.rb +49 -18
- data/lib/active_support/xml_mini/jdom.rb +1 -1
- data/lib/active_support/xml_mini/libxml.rb +5 -5
- data/lib/active_support/xml_mini/libxmlsax.rb +1 -1
- data/lib/active_support/xml_mini/nokogiri.rb +4 -4
- data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
- data/lib/active_support/xml_mini/rexml.rb +9 -2
- data/lib/active_support/xml_mini.rb +5 -4
- data/lib/active_support.rb +29 -1
- metadata +46 -45
- data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -5
- data/lib/active_support/core_ext/hash/compact.rb +0 -5
- data/lib/active_support/core_ext/hash/transform_values.rb +0 -5
- data/lib/active_support/core_ext/marshal.rb +0 -24
- data/lib/active_support/core_ext/module/reachable.rb +0 -6
- data/lib/active_support/core_ext/numeric/inquiry.rb +0 -5
- data/lib/active_support/core_ext/range/include_range.rb +0 -9
- data/lib/active_support/dependencies/zeitwerk_integration.rb +0 -117
@@ -1,11 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# == Attribute Accessors per Thread
|
4
|
+
#
|
3
5
|
# Extends the module object with class/module and instance accessors for
|
4
6
|
# class/module attributes, just like the native attr* accessors for instance
|
5
7
|
# attributes, but does so on a per-thread basis.
|
6
8
|
#
|
7
9
|
# So the values are scoped within the Thread.current space under the class name
|
8
10
|
# of the module.
|
11
|
+
#
|
12
|
+
# Note that it can also be scoped per-fiber if Rails.application.config.active_support.isolation_level
|
13
|
+
# is set to `:fiber`
|
9
14
|
class Module
|
10
15
|
# Defines a per-thread class attribute and creates class and instance reader methods.
|
11
16
|
# The underlying per-thread class variable is set to +nil+, if it is not previously defined.
|
@@ -14,9 +19,9 @@ class Module
|
|
14
19
|
# thread_mattr_reader :user
|
15
20
|
# end
|
16
21
|
#
|
17
|
-
# Current.user
|
18
|
-
# Thread.current[:attr_Current_user] = "DHH"
|
22
|
+
# Current.user = "DHH"
|
19
23
|
# Current.user # => "DHH"
|
24
|
+
# Thread.new { Current.user }.values # => nil
|
20
25
|
#
|
21
26
|
# The attribute name must be a valid method name in Ruby.
|
22
27
|
#
|
@@ -33,7 +38,7 @@ class Module
|
|
33
38
|
# end
|
34
39
|
#
|
35
40
|
# Current.new.user # => NoMethodError
|
36
|
-
def thread_mattr_reader(*syms, instance_reader: true, instance_accessor: true) # :nodoc:
|
41
|
+
def thread_mattr_reader(*syms, instance_reader: true, instance_accessor: true, default: nil) # :nodoc:
|
37
42
|
syms.each do |sym|
|
38
43
|
raise NameError.new("invalid attribute name: #{sym}") unless /^[_A-Za-z]\w*$/.match?(sym)
|
39
44
|
|
@@ -41,7 +46,8 @@ class Module
|
|
41
46
|
# to work with inheritance via polymorphism.
|
42
47
|
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
43
48
|
def self.#{sym}
|
44
|
-
|
49
|
+
@__thread_mattr_#{sym} ||= "attr_\#{name}_#{sym}"
|
50
|
+
::ActiveSupport::IsolatedExecutionState[@__thread_mattr_#{sym}]
|
45
51
|
end
|
46
52
|
EOS
|
47
53
|
|
@@ -52,6 +58,8 @@ class Module
|
|
52
58
|
end
|
53
59
|
EOS
|
54
60
|
end
|
61
|
+
|
62
|
+
::ActiveSupport::IsolatedExecutionState["attr_#{name}_#{sym}"] = default unless default.nil?
|
55
63
|
end
|
56
64
|
end
|
57
65
|
alias :thread_cattr_reader :thread_mattr_reader
|
@@ -74,7 +82,7 @@ class Module
|
|
74
82
|
# end
|
75
83
|
#
|
76
84
|
# Current.new.user = "DHH" # => NoMethodError
|
77
|
-
def thread_mattr_writer(*syms, instance_writer: true, instance_accessor: true) # :nodoc:
|
85
|
+
def thread_mattr_writer(*syms, instance_writer: true, instance_accessor: true, default: nil) # :nodoc:
|
78
86
|
syms.each do |sym|
|
79
87
|
raise NameError.new("invalid attribute name: #{sym}") unless /^[_A-Za-z]\w*$/.match?(sym)
|
80
88
|
|
@@ -82,7 +90,8 @@ class Module
|
|
82
90
|
# to work with inheritance via polymorphism.
|
83
91
|
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
84
92
|
def self.#{sym}=(obj)
|
85
|
-
|
93
|
+
@__thread_mattr_#{sym} ||= "attr_\#{name}_#{sym}"
|
94
|
+
::ActiveSupport::IsolatedExecutionState[@__thread_mattr_#{sym}] = obj
|
86
95
|
end
|
87
96
|
EOS
|
88
97
|
|
@@ -93,6 +102,8 @@ class Module
|
|
93
102
|
end
|
94
103
|
EOS
|
95
104
|
end
|
105
|
+
|
106
|
+
public_send("#{sym}=", default) unless default.nil?
|
96
107
|
end
|
97
108
|
end
|
98
109
|
alias :thread_cattr_writer :thread_mattr_writer
|
@@ -107,16 +118,18 @@ class Module
|
|
107
118
|
# Account.user # => "DHH"
|
108
119
|
# Account.new.user # => "DHH"
|
109
120
|
#
|
121
|
+
# Unlike `mattr_accessor`, values are *not* shared with subclasses or parent classes.
|
110
122
|
# If a subclass changes the value, the parent class' value is not changed.
|
111
|
-
#
|
112
|
-
# is not changed.
|
123
|
+
# If the parent class changes the value, the value of subclasses is not changed.
|
113
124
|
#
|
114
125
|
# class Customer < Account
|
115
126
|
# end
|
116
127
|
#
|
117
|
-
#
|
118
|
-
# Customer.user
|
119
|
-
#
|
128
|
+
# Account.user # => "DHH"
|
129
|
+
# Customer.user # => nil
|
130
|
+
# Customer.user = "Rafael"
|
131
|
+
# Customer.user # => "Rafael"
|
132
|
+
# Account.user # => "DHH"
|
120
133
|
#
|
121
134
|
# To omit the instance writer method, pass <tt>instance_writer: false</tt>.
|
122
135
|
# To omit the instance reader method, pass <tt>instance_reader: false</tt>.
|
@@ -136,8 +149,8 @@ class Module
|
|
136
149
|
#
|
137
150
|
# Current.new.user = "DHH" # => NoMethodError
|
138
151
|
# Current.new.user # => NoMethodError
|
139
|
-
def thread_mattr_accessor(*syms, instance_reader: true, instance_writer: true, instance_accessor: true)
|
140
|
-
thread_mattr_reader(*syms, instance_reader: instance_reader, instance_accessor: instance_accessor)
|
152
|
+
def thread_mattr_accessor(*syms, instance_reader: true, instance_writer: true, instance_accessor: true, default: nil)
|
153
|
+
thread_mattr_reader(*syms, instance_reader: instance_reader, instance_accessor: instance_accessor, default: default)
|
141
154
|
thread_mattr_writer(*syms, instance_writer: instance_writer, instance_accessor: instance_accessor)
|
142
155
|
end
|
143
156
|
alias :thread_cattr_accessor :thread_mattr_accessor
|
@@ -104,10 +104,16 @@ class Module
|
|
104
104
|
# * grok the behavior of our class in one glance,
|
105
105
|
# * clean up monolithic junk-drawer classes by separating their concerns, and
|
106
106
|
# * stop leaning on protected/private for crude "this is internal stuff" modularity.
|
107
|
+
#
|
108
|
+
# === Prepending concerning
|
109
|
+
#
|
110
|
+
# <tt>concerning</tt> supports a <tt>prepend: true</tt> argument which will <tt>prepend</tt> the
|
111
|
+
# concern instead of using <tt>include</tt> for it.
|
107
112
|
module Concerning
|
108
113
|
# Define a new concern and mix it in.
|
109
|
-
def concerning(topic, &block)
|
110
|
-
|
114
|
+
def concerning(topic, prepend: false, &block)
|
115
|
+
method = prepend ? :prepend : :include
|
116
|
+
__send__(method, concern(topic, &block))
|
111
117
|
end
|
112
118
|
|
113
119
|
# A low-cruft shortcut to define a concern.
|
@@ -170,7 +170,7 @@ class Module
|
|
170
170
|
# The target method must be public, otherwise it will raise +NoMethodError+.
|
171
171
|
def delegate(*methods, to: nil, prefix: nil, allow_nil: nil, private: nil)
|
172
172
|
unless to
|
173
|
-
raise ArgumentError, "Delegation needs a target. Supply
|
173
|
+
raise ArgumentError, "Delegation needs a target. Supply a keyword argument 'to' (e.g. delegate :hello, to: :greeter)."
|
174
174
|
end
|
175
175
|
|
176
176
|
if prefix == true && /^[^a-z_]/.match?(to)
|
@@ -190,16 +190,16 @@ class Module
|
|
190
190
|
to = to.to_s
|
191
191
|
to = "self.#{to}" if DELEGATION_RESERVED_METHOD_NAMES.include?(to)
|
192
192
|
|
193
|
-
|
193
|
+
method_def = []
|
194
|
+
method_names = []
|
195
|
+
|
196
|
+
methods.map do |method|
|
197
|
+
method_name = prefix ? "#{method_prefix}#{method}" : method
|
198
|
+
method_names << method_name.to_sym
|
199
|
+
|
194
200
|
# Attribute writer methods only accept one argument. Makes sure []=
|
195
201
|
# methods still accept two arguments.
|
196
|
-
definition =
|
197
|
-
"arg"
|
198
|
-
elsif RUBY_VERSION >= "2.7"
|
199
|
-
"..."
|
200
|
-
else
|
201
|
-
"*args, &block"
|
202
|
-
end
|
202
|
+
definition = /[^\]]=\z/.match?(method) ? "arg" : "..."
|
203
203
|
|
204
204
|
# The following generated method calls the target exactly once, storing
|
205
205
|
# the returned value in a dummy variable.
|
@@ -209,34 +209,33 @@ class Module
|
|
209
209
|
# whereas conceptually, from the user point of view, the delegator should
|
210
210
|
# be doing one call.
|
211
211
|
if allow_nil
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
"
|
216
|
-
" _
|
217
|
-
"
|
218
|
-
|
219
|
-
|
212
|
+
method = method.to_s
|
213
|
+
|
214
|
+
method_def <<
|
215
|
+
"def #{method_name}(#{definition})" <<
|
216
|
+
" _ = #{to}" <<
|
217
|
+
" if !_.nil? || nil.respond_to?(:#{method})" <<
|
218
|
+
" _.#{method}(#{definition})" <<
|
219
|
+
" end" <<
|
220
|
+
"end"
|
220
221
|
else
|
221
|
-
|
222
|
+
method = method.to_s
|
223
|
+
method_name = method_name.to_s
|
222
224
|
|
223
|
-
method_def
|
224
|
-
"def #{
|
225
|
-
"
|
226
|
-
" _.#{method}(#{definition})"
|
227
|
-
"rescue NoMethodError => e"
|
228
|
-
" if _.nil? && e.name == :#{method}"
|
229
|
-
"
|
230
|
-
" else"
|
231
|
-
" raise"
|
232
|
-
" end"
|
225
|
+
method_def <<
|
226
|
+
"def #{method_name}(#{definition})" <<
|
227
|
+
" _ = #{to}" <<
|
228
|
+
" _.#{method}(#{definition})" <<
|
229
|
+
"rescue NoMethodError => e" <<
|
230
|
+
" if _.nil? && e.name == :#{method}" <<
|
231
|
+
%( raise DelegationError, "#{self}##{method_name} delegated to #{to}.#{method}, but #{to} is nil: \#{self.inspect}") <<
|
232
|
+
" else" <<
|
233
|
+
" raise" <<
|
234
|
+
" end" <<
|
233
235
|
"end"
|
234
|
-
].join ";"
|
235
236
|
end
|
236
|
-
|
237
|
-
module_eval(method_def, file, line)
|
238
237
|
end
|
239
|
-
|
238
|
+
module_eval(method_def.join(";"), file, line)
|
240
239
|
private(*method_names) if private
|
241
240
|
method_names
|
242
241
|
end
|
@@ -280,13 +279,14 @@ class Module
|
|
280
279
|
# variables, methods, constants, etc.
|
281
280
|
#
|
282
281
|
# The delegated method must be public on the target, otherwise it will
|
283
|
-
# raise +
|
282
|
+
# raise +DelegationError+. If you wish to instead return +nil+,
|
283
|
+
# use the <tt>:allow_nil</tt> option.
|
284
284
|
#
|
285
285
|
# The <tt>marshal_dump</tt> and <tt>_dump</tt> methods are exempt from
|
286
286
|
# delegation due to possible interference when calling
|
287
287
|
# <tt>Marshal.dump(object)</tt>, should the delegation target method
|
288
288
|
# of <tt>object</tt> add or remove instance variables.
|
289
|
-
def delegate_missing_to(target)
|
289
|
+
def delegate_missing_to(target, allow_nil: nil)
|
290
290
|
target = target.to_s
|
291
291
|
target = "self.#{target}" if DELEGATION_RESERVED_METHOD_NAMES.include?(target)
|
292
292
|
|
@@ -307,14 +307,18 @@ class Module
|
|
307
307
|
super
|
308
308
|
rescue NoMethodError
|
309
309
|
if #{target}.nil?
|
310
|
-
|
310
|
+
if #{allow_nil == true}
|
311
|
+
nil
|
312
|
+
else
|
313
|
+
raise DelegationError, "\#{method} delegated to #{target}, but #{target} is nil"
|
314
|
+
end
|
311
315
|
else
|
312
316
|
raise
|
313
317
|
end
|
314
318
|
end
|
315
319
|
end
|
316
320
|
end
|
317
|
-
ruby2_keywords(:method_missing)
|
321
|
+
ruby2_keywords(:method_missing)
|
318
322
|
RUBY
|
319
323
|
end
|
320
324
|
end
|
@@ -11,20 +11,12 @@ class Module
|
|
11
11
|
if defined?(@parent_name)
|
12
12
|
@parent_name
|
13
13
|
else
|
14
|
-
parent_name = name =~ /::[^:]+\
|
14
|
+
parent_name = name =~ /::[^:]+\z/ ? -$` : nil
|
15
15
|
@parent_name = parent_name unless frozen?
|
16
16
|
parent_name
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
def parent_name
|
21
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
22
|
-
`Module#parent_name` has been renamed to `module_parent_name`.
|
23
|
-
`parent_name` is deprecated and will be removed in Rails 6.1.
|
24
|
-
MSG
|
25
|
-
module_parent_name
|
26
|
-
end
|
27
|
-
|
28
20
|
# Returns the module which contains this one according to its name.
|
29
21
|
#
|
30
22
|
# module M
|
@@ -44,14 +36,6 @@ class Module
|
|
44
36
|
module_parent_name ? ActiveSupport::Inflector.constantize(module_parent_name) : Object
|
45
37
|
end
|
46
38
|
|
47
|
-
def parent
|
48
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
49
|
-
`Module#parent` has been renamed to `module_parent`.
|
50
|
-
`parent` is deprecated and will be removed in Rails 6.1.
|
51
|
-
MSG
|
52
|
-
module_parent
|
53
|
-
end
|
54
|
-
|
55
39
|
# Returns all the parents of this module according to its name, ordered from
|
56
40
|
# nested outwards. The receiver is not contained within the result.
|
57
41
|
#
|
@@ -76,12 +60,4 @@ class Module
|
|
76
60
|
parents << Object unless parents.include? Object
|
77
61
|
parents
|
78
62
|
end
|
79
|
-
|
80
|
-
def parents
|
81
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
82
|
-
`Module#parents` has been renamed to `module_parents`.
|
83
|
-
`parents` is deprecated and will be removed in Rails 6.1.
|
84
|
-
MSG
|
85
|
-
module_parents
|
86
|
-
end
|
87
63
|
end
|
@@ -14,9 +14,22 @@ class NameError
|
|
14
14
|
# It extends NameError#message with spell corrections which are SLOW.
|
15
15
|
# We should use original_message message instead.
|
16
16
|
message = respond_to?(:original_message) ? original_message : self.message
|
17
|
+
return unless message.start_with?("uninitialized constant ")
|
17
18
|
|
18
|
-
|
19
|
-
|
19
|
+
receiver = begin
|
20
|
+
self.receiver
|
21
|
+
rescue ArgumentError
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
|
25
|
+
if receiver == Object
|
26
|
+
name.to_s
|
27
|
+
elsif receiver
|
28
|
+
"#{real_mod_name(receiver)}::#{self.name}"
|
29
|
+
else
|
30
|
+
if match = message.match(/((::)?([A-Z]\w*)(::[A-Z]\w*)*)$/)
|
31
|
+
match[1]
|
32
|
+
end
|
20
33
|
end
|
21
34
|
end
|
22
35
|
|
@@ -35,4 +48,12 @@ class NameError
|
|
35
48
|
missing_name == name.to_s
|
36
49
|
end
|
37
50
|
end
|
51
|
+
|
52
|
+
private
|
53
|
+
UNBOUND_METHOD_MODULE_NAME = Module.instance_method(:name)
|
54
|
+
private_constant :UNBOUND_METHOD_MODULE_NAME
|
55
|
+
|
56
|
+
def real_mod_name(mod)
|
57
|
+
UNBOUND_METHOD_MODULE_NAME.bind_call(mod)
|
58
|
+
end
|
38
59
|
end
|
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
require "active_support/core_ext/big_decimal/conversions"
|
4
4
|
require "active_support/number_helper"
|
5
|
-
require "active_support/core_ext/module/deprecation"
|
6
5
|
|
7
6
|
module ActiveSupport
|
8
7
|
module NumericWithFormat
|
@@ -10,6 +9,8 @@ module ActiveSupport
|
|
10
9
|
# Options are provided for phone numbers, currency, percentage,
|
11
10
|
# precision, positional notation, file size and pretty printing.
|
12
11
|
#
|
12
|
+
# This method is aliased to <tt>to_fs</tt>.
|
13
|
+
#
|
13
14
|
# ==== Options
|
14
15
|
#
|
15
16
|
# For details on which formats use which options, see ActiveSupport::NumberHelper
|
@@ -17,97 +18,102 @@ module ActiveSupport
|
|
17
18
|
# ==== Examples
|
18
19
|
#
|
19
20
|
# Phone Numbers:
|
20
|
-
# 5551234.
|
21
|
-
# 1235551234.
|
22
|
-
# 1235551234.
|
23
|
-
# 1235551234.
|
24
|
-
# 1235551234.
|
25
|
-
# 1235551234.
|
26
|
-
# 1235551234.
|
21
|
+
# 5551234.to_formatted_s(:phone) # => "555-1234"
|
22
|
+
# 1235551234.to_formatted_s(:phone) # => "123-555-1234"
|
23
|
+
# 1235551234.to_formatted_s(:phone, area_code: true) # => "(123) 555-1234"
|
24
|
+
# 1235551234.to_formatted_s(:phone, delimiter: ' ') # => "123 555 1234"
|
25
|
+
# 1235551234.to_formatted_s(:phone, area_code: true, extension: 555) # => "(123) 555-1234 x 555"
|
26
|
+
# 1235551234.to_formatted_s(:phone, country_code: 1) # => "+1-123-555-1234"
|
27
|
+
# 1235551234.to_formatted_s(:phone, country_code: 1, extension: 1343, delimiter: '.')
|
27
28
|
# # => "+1.123.555.1234 x 1343"
|
28
29
|
#
|
29
30
|
# Currency:
|
30
|
-
# 1234567890.50.
|
31
|
-
# 1234567890.506.
|
32
|
-
# 1234567890.506.
|
33
|
-
# 1234567890.506.
|
34
|
-
#
|
31
|
+
# 1234567890.50.to_formatted_s(:currency) # => "$1,234,567,890.50"
|
32
|
+
# 1234567890.506.to_formatted_s(:currency) # => "$1,234,567,890.51"
|
33
|
+
# 1234567890.506.to_formatted_s(:currency, precision: 3) # => "$1,234,567,890.506"
|
34
|
+
# 1234567890.506.to_formatted_s(:currency, round_mode: :down) # => "$1,234,567,890.50"
|
35
|
+
# 1234567890.506.to_formatted_s(:currency, locale: :fr) # => "1 234 567 890,51 €"
|
36
|
+
# -1234567890.50.to_formatted_s(:currency, negative_format: '(%u%n)')
|
35
37
|
# # => "($1,234,567,890.50)"
|
36
|
-
# 1234567890.50.
|
38
|
+
# 1234567890.50.to_formatted_s(:currency, unit: '£', separator: ',', delimiter: '')
|
37
39
|
# # => "£1234567890,50"
|
38
|
-
# 1234567890.50.
|
40
|
+
# 1234567890.50.to_formatted_s(:currency, unit: '£', separator: ',', delimiter: '', format: '%n %u')
|
39
41
|
# # => "1234567890,50 £"
|
40
42
|
#
|
41
43
|
# Percentage:
|
42
|
-
# 100.
|
43
|
-
# 100.
|
44
|
-
# 1000.
|
45
|
-
# 302.24398923423.
|
46
|
-
#
|
47
|
-
#
|
44
|
+
# 100.to_formatted_s(:percentage) # => "100.000%"
|
45
|
+
# 100.to_formatted_s(:percentage, precision: 0) # => "100%"
|
46
|
+
# 1000.to_formatted_s(:percentage, delimiter: '.', separator: ',') # => "1.000,000%"
|
47
|
+
# 302.24398923423.to_formatted_s(:percentage, precision: 5) # => "302.24399%"
|
48
|
+
# 302.24398923423.to_formatted_s(:percentage, round_mode: :down) # => "302.243%"
|
49
|
+
# 1000.to_formatted_s(:percentage, locale: :fr) # => "1 000,000%"
|
50
|
+
# 100.to_formatted_s(:percentage, format: '%n %') # => "100.000 %"
|
48
51
|
#
|
49
52
|
# Delimited:
|
50
|
-
# 12345678.
|
51
|
-
# 12345678.05.
|
52
|
-
# 12345678.
|
53
|
-
# 12345678.
|
54
|
-
# 12345678.05.
|
55
|
-
# 12345678.05.
|
56
|
-
# 98765432.98.
|
53
|
+
# 12345678.to_formatted_s(:delimited) # => "12,345,678"
|
54
|
+
# 12345678.05.to_formatted_s(:delimited) # => "12,345,678.05"
|
55
|
+
# 12345678.to_formatted_s(:delimited, delimiter: '.') # => "12.345.678"
|
56
|
+
# 12345678.to_formatted_s(:delimited, delimiter: ',') # => "12,345,678"
|
57
|
+
# 12345678.05.to_formatted_s(:delimited, separator: ' ') # => "12,345,678 05"
|
58
|
+
# 12345678.05.to_formatted_s(:delimited, locale: :fr) # => "12 345 678,05"
|
59
|
+
# 98765432.98.to_formatted_s(:delimited, delimiter: ' ', separator: ',')
|
57
60
|
# # => "98 765 432,98"
|
58
61
|
#
|
59
62
|
# Rounded:
|
60
|
-
# 111.2345.
|
61
|
-
# 111.2345.
|
62
|
-
#
|
63
|
-
#
|
64
|
-
#
|
65
|
-
# 111.2345.
|
66
|
-
#
|
67
|
-
#
|
68
|
-
#
|
63
|
+
# 111.2345.to_formatted_s(:rounded) # => "111.235"
|
64
|
+
# 111.2345.to_formatted_s(:rounded, precision: 2) # => "111.23"
|
65
|
+
# 111.2345.to_formatted_s(:rounded, precision: 2, round_mode: :up) # => "111.24"
|
66
|
+
# 13.to_formatted_s(:rounded, precision: 5) # => "13.00000"
|
67
|
+
# 389.32314.to_formatted_s(:rounded, precision: 0) # => "389"
|
68
|
+
# 111.2345.to_formatted_s(:rounded, significant: true) # => "111"
|
69
|
+
# 111.2345.to_formatted_s(:rounded, precision: 1, significant: true) # => "100"
|
70
|
+
# 13.to_formatted_s(:rounded, precision: 5, significant: true) # => "13.000"
|
71
|
+
# 111.234.to_formatted_s(:rounded, locale: :fr) # => "111,234"
|
72
|
+
# 13.to_formatted_s(:rounded, precision: 5, significant: true, strip_insignificant_zeros: true)
|
69
73
|
# # => "13"
|
70
|
-
# 389.32314.
|
71
|
-
# 1111.2345.
|
74
|
+
# 389.32314.to_formatted_s(:rounded, precision: 4, significant: true) # => "389.3"
|
75
|
+
# 1111.2345.to_formatted_s(:rounded, precision: 2, separator: ',', delimiter: '.')
|
72
76
|
# # => "1.111,23"
|
73
77
|
#
|
74
78
|
# Human-friendly size in Bytes:
|
75
|
-
# 123.
|
76
|
-
# 1234.
|
77
|
-
# 12345.
|
78
|
-
# 1234567.
|
79
|
-
# 1234567890.
|
80
|
-
# 1234567890123.
|
81
|
-
# 1234567890123456.
|
82
|
-
# 1234567890123456789.
|
83
|
-
# 1234567.
|
84
|
-
#
|
85
|
-
#
|
86
|
-
#
|
87
|
-
#
|
79
|
+
# 123.to_formatted_s(:human_size) # => "123 Bytes"
|
80
|
+
# 1234.to_formatted_s(:human_size) # => "1.21 KB"
|
81
|
+
# 12345.to_formatted_s(:human_size) # => "12.1 KB"
|
82
|
+
# 1234567.to_formatted_s(:human_size) # => "1.18 MB"
|
83
|
+
# 1234567890.to_formatted_s(:human_size) # => "1.15 GB"
|
84
|
+
# 1234567890123.to_formatted_s(:human_size) # => "1.12 TB"
|
85
|
+
# 1234567890123456.to_formatted_s(:human_size) # => "1.1 PB"
|
86
|
+
# 1234567890123456789.to_formatted_s(:human_size) # => "1.07 EB"
|
87
|
+
# 1234567.to_formatted_s(:human_size, precision: 2) # => "1.2 MB"
|
88
|
+
# 1234567.to_formatted_s(:human_size, precision: 2, round_mode: :up) # => "1.3 MB"
|
89
|
+
# 483989.to_formatted_s(:human_size, precision: 2) # => "470 KB"
|
90
|
+
# 1234567.to_formatted_s(:human_size, precision: 2, separator: ',') # => "1,2 MB"
|
91
|
+
# 1234567890123.to_formatted_s(:human_size, precision: 5) # => "1.1228 TB"
|
92
|
+
# 524288000.to_formatted_s(:human_size, precision: 5) # => "500 MB"
|
88
93
|
#
|
89
94
|
# Human-friendly format:
|
90
|
-
# 123.
|
91
|
-
# 1234.
|
92
|
-
# 12345.
|
93
|
-
# 1234567.
|
94
|
-
# 1234567890.
|
95
|
-
# 1234567890123.
|
96
|
-
# 1234567890123456.
|
97
|
-
# 1234567890123456789.
|
98
|
-
# 489939.
|
99
|
-
# 489939.
|
100
|
-
#
|
101
|
-
#
|
102
|
-
#
|
95
|
+
# 123.to_formatted_s(:human) # => "123"
|
96
|
+
# 1234.to_formatted_s(:human) # => "1.23 Thousand"
|
97
|
+
# 12345.to_formatted_s(:human) # => "12.3 Thousand"
|
98
|
+
# 1234567.to_formatted_s(:human) # => "1.23 Million"
|
99
|
+
# 1234567890.to_formatted_s(:human) # => "1.23 Billion"
|
100
|
+
# 1234567890123.to_formatted_s(:human) # => "1.23 Trillion"
|
101
|
+
# 1234567890123456.to_formatted_s(:human) # => "1.23 Quadrillion"
|
102
|
+
# 1234567890123456789.to_formatted_s(:human) # => "1230 Quadrillion"
|
103
|
+
# 489939.to_formatted_s(:human, precision: 2) # => "490 Thousand"
|
104
|
+
# 489939.to_formatted_s(:human, precision: 2, round_mode: :down) # => "480 Thousand"
|
105
|
+
# 489939.to_formatted_s(:human, precision: 4) # => "489.9 Thousand"
|
106
|
+
# 1234567.to_formatted_s(:human, precision: 4,
|
107
|
+
# significant: false) # => "1.2346 Million"
|
108
|
+
# 1234567.to_formatted_s(:human, precision: 1,
|
103
109
|
# separator: ',',
|
104
|
-
# significant: false)
|
105
|
-
def
|
110
|
+
# significant: false) # => "1,2 Million"
|
111
|
+
def to_formatted_s(format = nil, options = nil)
|
112
|
+
return to_s if format.nil?
|
113
|
+
|
106
114
|
case format
|
107
|
-
when nil
|
108
|
-
super()
|
109
115
|
when Integer, String
|
110
|
-
|
116
|
+
to_s(format)
|
111
117
|
when :phone
|
112
118
|
ActiveSupport::NumberHelper.number_to_phone(self, options || {})
|
113
119
|
when :currency
|
@@ -123,11 +129,12 @@ module ActiveSupport
|
|
123
129
|
when :human_size
|
124
130
|
ActiveSupport::NumberHelper.number_to_human_size(self, options || {})
|
125
131
|
when Symbol
|
126
|
-
|
132
|
+
to_s
|
127
133
|
else
|
128
|
-
|
134
|
+
to_s(format)
|
129
135
|
end
|
130
136
|
end
|
137
|
+
alias_method :to_fs, :to_formatted_s
|
131
138
|
end
|
132
139
|
end
|
133
140
|
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveSupport
|
4
|
+
module DeprecatedNumericWithFormat # :nodoc:
|
5
|
+
def to_s(format = nil, options = nil)
|
6
|
+
return super() if format.nil?
|
7
|
+
|
8
|
+
case format
|
9
|
+
when Integer, String
|
10
|
+
super(format)
|
11
|
+
when :phone
|
12
|
+
ActiveSupport::Deprecation.warn(
|
13
|
+
"#{self.class}#to_s(#{format.inspect}) is deprecated. Please use #{self.class}#to_formatted_s(#{format.inspect}) instead."
|
14
|
+
)
|
15
|
+
ActiveSupport::NumberHelper.number_to_phone(self, options || {})
|
16
|
+
when :currency
|
17
|
+
ActiveSupport::Deprecation.warn(
|
18
|
+
"#{self.class}#to_s(#{format.inspect}) is deprecated. Please use #{self.class}#to_formatted_s(#{format.inspect}) instead."
|
19
|
+
)
|
20
|
+
ActiveSupport::NumberHelper.number_to_currency(self, options || {})
|
21
|
+
when :percentage
|
22
|
+
ActiveSupport::Deprecation.warn(
|
23
|
+
"#{self.class}#to_s(#{format.inspect}) is deprecated. Please use #{self.class}#to_formatted_s(#{format.inspect}) instead."
|
24
|
+
)
|
25
|
+
ActiveSupport::NumberHelper.number_to_percentage(self, options || {})
|
26
|
+
when :delimited
|
27
|
+
ActiveSupport::Deprecation.warn(
|
28
|
+
"#{self.class}#to_s(#{format.inspect}) is deprecated. Please use #{self.class}#to_formatted_s(#{format.inspect}) instead."
|
29
|
+
)
|
30
|
+
ActiveSupport::NumberHelper.number_to_delimited(self, options || {})
|
31
|
+
when :rounded
|
32
|
+
ActiveSupport::Deprecation.warn(
|
33
|
+
"#{self.class}#to_s(#{format.inspect}) is deprecated. Please use #{self.class}#to_formatted_s(#{format.inspect}) instead."
|
34
|
+
)
|
35
|
+
ActiveSupport::NumberHelper.number_to_rounded(self, options || {})
|
36
|
+
when :human
|
37
|
+
ActiveSupport::Deprecation.warn(
|
38
|
+
"#{self.class}#to_s(#{format.inspect}) is deprecated. Please use #{self.class}#to_formatted_s(#{format.inspect}) instead."
|
39
|
+
)
|
40
|
+
ActiveSupport::NumberHelper.number_to_human(self, options || {})
|
41
|
+
when :human_size
|
42
|
+
ActiveSupport::Deprecation.warn(
|
43
|
+
"#{self.class}#to_s(#{format.inspect}) is deprecated. Please use #{self.class}#to_formatted_s(#{format.inspect}) instead."
|
44
|
+
)
|
45
|
+
ActiveSupport::NumberHelper.number_to_human_size(self, options || {})
|
46
|
+
when Symbol
|
47
|
+
ActiveSupport::Deprecation.warn(
|
48
|
+
"#{self.class}#to_s(#{format.inspect}) is deprecated. Please use #{self.class}#to_formatted_s(#{format.inspect}) instead."
|
49
|
+
)
|
50
|
+
super()
|
51
|
+
else
|
52
|
+
super(format)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
Integer.prepend ActiveSupport::DeprecatedNumericWithFormat
|
59
|
+
Float.prepend ActiveSupport::DeprecatedNumericWithFormat
|
60
|
+
BigDecimal.prepend ActiveSupport::DeprecatedNumericWithFormat
|
@@ -3,3 +3,4 @@
|
|
3
3
|
require "active_support/core_ext/numeric/bytes"
|
4
4
|
require "active_support/core_ext/numeric/time"
|
5
5
|
require "active_support/core_ext/numeric/conversions"
|
6
|
+
require "active_support/core_ext/numeric/deprecated_conversions" unless ENV["RAILS_DISABLE_DEPRECATED_TO_S_CONVERSION"]
|
@@ -131,7 +131,7 @@ class String
|
|
131
131
|
end
|
132
132
|
end
|
133
133
|
|
134
|
-
class Numeric
|
134
|
+
class Numeric # :nodoc:
|
135
135
|
# No number is blank:
|
136
136
|
#
|
137
137
|
# 1.blank? # => false
|
@@ -143,7 +143,7 @@ class Numeric #:nodoc:
|
|
143
143
|
end
|
144
144
|
end
|
145
145
|
|
146
|
-
class Time
|
146
|
+
class Time # :nodoc:
|
147
147
|
# No Time is blank:
|
148
148
|
#
|
149
149
|
# Time.now.blank? # => false
|