activesupport 7.0.4.3 → 7.2.4
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 +270 -266
- data/MIT-LICENSE +1 -1
- data/README.rdoc +7 -7
- data/lib/active_support/actionable_error.rb +3 -1
- data/lib/active_support/array_inquirer.rb +3 -1
- data/lib/active_support/backtrace_cleaner.rb +39 -7
- data/lib/active_support/benchmarkable.rb +1 -0
- data/lib/active_support/broadcast_logger.rb +238 -0
- data/lib/active_support/builder.rb +1 -1
- data/lib/active_support/cache/coder.rb +153 -0
- data/lib/active_support/cache/entry.rb +134 -0
- data/lib/active_support/cache/file_store.rb +51 -19
- data/lib/active_support/cache/mem_cache_store.rb +101 -134
- data/lib/active_support/cache/memory_store.rb +85 -30
- data/lib/active_support/cache/null_store.rb +8 -2
- data/lib/active_support/cache/redis_cache_store.rb +168 -153
- data/lib/active_support/cache/serializer_with_fallback.rb +152 -0
- data/lib/active_support/cache/strategy/local_cache.rb +64 -13
- data/lib/active_support/cache.rb +364 -292
- data/lib/active_support/callbacks.rb +121 -136
- data/lib/active_support/code_generator.rb +15 -10
- data/lib/active_support/concern.rb +4 -2
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +42 -3
- data/lib/active_support/concurrency/null_lock.rb +13 -0
- data/lib/active_support/configurable.rb +10 -0
- data/lib/active_support/core_ext/array/conversions.rb +1 -2
- data/lib/active_support/core_ext/array.rb +0 -1
- data/lib/active_support/core_ext/benchmark.rb +1 -0
- data/lib/active_support/core_ext/class/attribute.rb +2 -2
- data/lib/active_support/core_ext/class/subclasses.rb +17 -34
- data/lib/active_support/core_ext/date/blank.rb +4 -0
- data/lib/active_support/core_ext/date/calculations.rb +15 -0
- data/lib/active_support/core_ext/date/conversions.rb +1 -2
- data/lib/active_support/core_ext/date.rb +0 -1
- data/lib/active_support/core_ext/date_and_time/calculations.rb +10 -0
- 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/calculations.rb +4 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +6 -4
- data/lib/active_support/core_ext/date_time.rb +0 -1
- data/lib/active_support/core_ext/digest/uuid.rb +7 -10
- data/lib/active_support/core_ext/enumerable.rb +25 -80
- data/lib/active_support/core_ext/erb/util.rb +201 -0
- data/lib/active_support/core_ext/hash/conversions.rb +1 -1
- data/lib/active_support/core_ext/hash/deep_merge.rb +22 -14
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +3 -3
- data/lib/active_support/core_ext/hash/keys.rb +7 -7
- data/lib/active_support/core_ext/integer/inflections.rb +12 -12
- data/lib/active_support/core_ext/module/attr_internal.rb +17 -6
- data/lib/active_support/core_ext/module/attribute_accessors.rb +6 -0
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +34 -16
- data/lib/active_support/core_ext/module/concerning.rb +6 -6
- data/lib/active_support/core_ext/module/delegation.rb +20 -119
- data/lib/active_support/core_ext/module/deprecation.rb +12 -12
- data/lib/active_support/core_ext/module/introspection.rb +3 -1
- data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +5 -3
- data/lib/active_support/core_ext/numeric.rb +0 -1
- data/lib/active_support/core_ext/object/blank.rb +45 -1
- data/lib/active_support/core_ext/object/deep_dup.rb +16 -0
- data/lib/active_support/core_ext/object/duplicable.rb +25 -16
- data/lib/active_support/core_ext/object/inclusion.rb +13 -5
- data/lib/active_support/core_ext/object/instance_variables.rb +4 -2
- data/lib/active_support/core_ext/object/json.rb +18 -8
- data/lib/active_support/core_ext/object/to_query.rb +0 -2
- data/lib/active_support/core_ext/object/try.rb +2 -2
- data/lib/active_support/core_ext/object/with.rb +46 -0
- data/lib/active_support/core_ext/object/with_options.rb +9 -9
- data/lib/active_support/core_ext/object.rb +1 -0
- data/lib/active_support/core_ext/pathname/blank.rb +20 -0
- data/lib/active_support/core_ext/pathname/existence.rb +2 -0
- data/lib/active_support/core_ext/pathname.rb +1 -0
- data/lib/active_support/core_ext/range/conversions.rb +28 -7
- data/lib/active_support/core_ext/range/overlap.rb +40 -0
- data/lib/active_support/core_ext/range/sole.rb +17 -0
- data/lib/active_support/core_ext/range.rb +2 -2
- data/lib/active_support/core_ext/securerandom.rb +24 -12
- data/lib/active_support/core_ext/string/conversions.rb +1 -1
- data/lib/active_support/core_ext/string/filters.rb +24 -18
- data/lib/active_support/core_ext/string/indent.rb +1 -1
- data/lib/active_support/core_ext/string/inflections.rb +16 -9
- data/lib/active_support/core_ext/string/multibyte.rb +3 -3
- data/lib/active_support/core_ext/string/output_safety.rb +37 -178
- data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
- data/lib/active_support/core_ext/time/calculations.rb +40 -30
- data/lib/active_support/core_ext/time/compatibility.rb +24 -0
- data/lib/active_support/core_ext/time/conversions.rb +1 -3
- data/lib/active_support/core_ext/time/zones.rb +7 -8
- data/lib/active_support/core_ext/time.rb +0 -1
- data/lib/active_support/core_ext.rb +0 -1
- data/lib/active_support/current_attributes.rb +60 -46
- data/lib/active_support/deep_mergeable.rb +53 -0
- data/lib/active_support/delegation.rb +202 -0
- data/lib/active_support/dependencies/autoload.rb +9 -16
- data/lib/active_support/deprecation/behaviors.rb +65 -42
- data/lib/active_support/deprecation/constant_accessor.rb +47 -25
- data/lib/active_support/deprecation/deprecators.rb +104 -0
- data/lib/active_support/deprecation/disallowed.rb +6 -8
- data/lib/active_support/deprecation/method_wrappers.rb +6 -23
- data/lib/active_support/deprecation/proxy_wrappers.rb +34 -22
- data/lib/active_support/deprecation/reporting.rb +49 -27
- data/lib/active_support/deprecation.rb +39 -9
- data/lib/active_support/deprecator.rb +7 -0
- data/lib/active_support/descendants_tracker.rb +66 -172
- data/lib/active_support/duration/iso8601_parser.rb +2 -2
- data/lib/active_support/duration/iso8601_serializer.rb +1 -4
- data/lib/active_support/duration.rb +13 -7
- data/lib/active_support/encrypted_configuration.rb +63 -11
- data/lib/active_support/encrypted_file.rb +17 -13
- data/lib/active_support/environment_inquirer.rb +22 -2
- data/lib/active_support/error_reporter/test_helper.rb +15 -0
- data/lib/active_support/error_reporter.rb +163 -36
- data/lib/active_support/evented_file_update_checker.rb +17 -3
- data/lib/active_support/execution_wrapper.rb +5 -6
- data/lib/active_support/file_update_checker.rb +6 -4
- data/lib/active_support/fork_tracker.rb +4 -32
- data/lib/active_support/gem_version.rb +3 -3
- data/lib/active_support/gzip.rb +2 -0
- data/lib/active_support/hash_with_indifferent_access.rb +50 -30
- data/lib/active_support/html_safe_translation.rb +19 -6
- data/lib/active_support/i18n.rb +1 -1
- data/lib/active_support/i18n_railtie.rb +20 -13
- data/lib/active_support/inflector/inflections.rb +2 -0
- data/lib/active_support/inflector/methods.rb +30 -20
- data/lib/active_support/inflector/transliterate.rb +3 -1
- data/lib/active_support/isolated_execution_state.rb +26 -22
- data/lib/active_support/json/decoding.rb +4 -3
- data/lib/active_support/json/encoding.rb +49 -49
- data/lib/active_support/key_generator.rb +9 -1
- data/lib/active_support/lazy_load_hooks.rb +8 -6
- data/lib/active_support/locale/en.yml +2 -0
- data/lib/active_support/log_subscriber.rb +74 -34
- data/lib/active_support/logger.rb +22 -60
- data/lib/active_support/logger_thread_safe_level.rb +10 -32
- data/lib/active_support/message_encryptor.rb +197 -53
- data/lib/active_support/message_encryptors.rb +141 -0
- data/lib/active_support/message_pack/cache_serializer.rb +23 -0
- data/lib/active_support/message_pack/extensions.rb +305 -0
- data/lib/active_support/message_pack/serializer.rb +63 -0
- data/lib/active_support/message_pack.rb +50 -0
- data/lib/active_support/message_verifier.rb +229 -89
- data/lib/active_support/message_verifiers.rb +137 -0
- data/lib/active_support/messages/codec.rb +65 -0
- data/lib/active_support/messages/metadata.rb +111 -45
- data/lib/active_support/messages/rotation_coordinator.rb +93 -0
- data/lib/active_support/messages/rotator.rb +38 -31
- data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
- data/lib/active_support/multibyte/chars.rb +8 -3
- data/lib/active_support/multibyte/unicode.rb +9 -37
- data/lib/active_support/notifications/fanout.rb +248 -87
- data/lib/active_support/notifications/instrumenter.rb +93 -25
- data/lib/active_support/notifications.rb +30 -29
- data/lib/active_support/number_helper/number_converter.rb +16 -7
- data/lib/active_support/number_helper/number_to_currency_converter.rb +6 -6
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +18 -5
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +3 -3
- data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -0
- data/lib/active_support/number_helper.rb +379 -317
- data/lib/active_support/option_merger.rb +2 -2
- data/lib/active_support/ordered_hash.rb +3 -3
- data/lib/active_support/ordered_options.rb +67 -15
- data/lib/active_support/parameter_filter.rb +103 -84
- data/lib/active_support/proxy_object.rb +8 -3
- data/lib/active_support/railtie.rb +25 -20
- data/lib/active_support/reloader.rb +12 -4
- data/lib/active_support/rescuable.rb +2 -0
- data/lib/active_support/secure_compare_rotator.rb +16 -9
- data/lib/active_support/string_inquirer.rb +4 -2
- data/lib/active_support/subscriber.rb +10 -27
- data/lib/active_support/syntax_error_proxy.rb +60 -0
- data/lib/active_support/tagged_logging.rb +64 -25
- data/lib/active_support/test_case.rb +156 -7
- data/lib/active_support/testing/assertions.rb +28 -12
- data/lib/active_support/testing/autorun.rb +0 -2
- data/lib/active_support/testing/constant_stubbing.rb +54 -0
- data/lib/active_support/testing/deprecation.rb +20 -27
- data/lib/active_support/testing/error_reporter_assertions.rb +107 -0
- data/lib/active_support/testing/isolation.rb +46 -33
- data/lib/active_support/testing/method_call_assertions.rb +7 -8
- data/lib/active_support/testing/parallelization/server.rb +18 -2
- data/lib/active_support/testing/parallelization/worker.rb +2 -2
- data/lib/active_support/testing/parallelization.rb +12 -1
- data/lib/active_support/testing/parallelize_executor.rb +8 -3
- data/lib/active_support/testing/setup_and_teardown.rb +2 -0
- data/lib/active_support/testing/stream.rb +1 -1
- data/lib/active_support/testing/tests_without_assertions.rb +19 -0
- data/lib/active_support/testing/time_helpers.rb +38 -16
- data/lib/active_support/time_with_zone.rb +16 -41
- data/lib/active_support/values/time_zone.rb +25 -14
- data/lib/active_support/version.rb +1 -1
- data/lib/active_support/xml_mini/jdom.rb +3 -10
- data/lib/active_support/xml_mini/nokogiri.rb +1 -1
- data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
- data/lib/active_support/xml_mini/rexml.rb +1 -1
- data/lib/active_support/xml_mini.rb +14 -3
- data/lib/active_support.rb +15 -3
- metadata +154 -24
- data/lib/active_support/core_ext/array/deprecated_conversions.rb +0 -25
- data/lib/active_support/core_ext/date/deprecated_conversions.rb +0 -26
- data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +0 -22
- data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +0 -60
- data/lib/active_support/core_ext/range/deprecated_conversions.rb +0 -26
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -7
- data/lib/active_support/core_ext/range/overlaps.rb +0 -10
- data/lib/active_support/core_ext/time/deprecated_conversions.rb +0 -22
- data/lib/active_support/core_ext/uri.rb +0 -5
- data/lib/active_support/deprecation/instance_delegator.rb +0 -38
- data/lib/active_support/per_thread_registry.rb +0 -65
- data/lib/active_support/ruby_features.rb +0 -7
|
@@ -4,5 +4,4 @@ require "active_support/core_ext/time/acts_like"
|
|
|
4
4
|
require "active_support/core_ext/time/calculations"
|
|
5
5
|
require "active_support/core_ext/time/compatibility"
|
|
6
6
|
require "active_support/core_ext/time/conversions"
|
|
7
|
-
require "active_support/core_ext/time/deprecated_conversions" unless ENV["RAILS_DISABLE_DEPRECATED_TO_S_CONVERSION"]
|
|
8
7
|
require "active_support/core_ext/time/zones"
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "active_support/callbacks"
|
|
4
|
+
require "active_support/core_ext/object/with"
|
|
4
5
|
require "active_support/core_ext/enumerable"
|
|
5
6
|
require "active_support/core_ext/module/delegation"
|
|
6
7
|
|
|
7
8
|
module ActiveSupport
|
|
9
|
+
# = Current Attributes
|
|
10
|
+
#
|
|
8
11
|
# Abstract super class that provides a thread-isolated attributes singleton, which resets automatically
|
|
9
12
|
# before and after each request. This allows you to keep all the per-request attributes easily
|
|
10
13
|
# available to the whole system.
|
|
@@ -90,6 +93,10 @@ module ActiveSupport
|
|
|
90
93
|
include ActiveSupport::Callbacks
|
|
91
94
|
define_callbacks :reset
|
|
92
95
|
|
|
96
|
+
INVALID_ATTRIBUTE_NAMES = [:set, :reset, :resets, :instance, :before_reset, :after_reset, :reset_all, :clear_all] # :nodoc:
|
|
97
|
+
|
|
98
|
+
NOT_SET = Object.new.freeze # :nodoc:
|
|
99
|
+
|
|
93
100
|
class << self
|
|
94
101
|
# Returns singleton instance for this class in this thread. If none exists, one is created.
|
|
95
102
|
def instance
|
|
@@ -97,7 +104,22 @@ module ActiveSupport
|
|
|
97
104
|
end
|
|
98
105
|
|
|
99
106
|
# Declares one or more attributes that will be given both class and instance accessor methods.
|
|
100
|
-
|
|
107
|
+
#
|
|
108
|
+
# ==== Options
|
|
109
|
+
#
|
|
110
|
+
# * <tt>:default</tt> - The default value for the attributes. If the value
|
|
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
|
+
def attribute(*names, default: NOT_SET)
|
|
115
|
+
invalid_attribute_names = names.map(&:to_sym) & INVALID_ATTRIBUTE_NAMES
|
|
116
|
+
if invalid_attribute_names.any?
|
|
117
|
+
raise ArgumentError, "Restricted attribute names: #{invalid_attribute_names.join(", ")}"
|
|
118
|
+
end
|
|
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
|
+
|
|
101
123
|
ActiveSupport::CodeGenerator.batch(generated_attribute_methods, __FILE__, __LINE__) do |owner|
|
|
102
124
|
names.each do |name|
|
|
103
125
|
owner.define_cached_method(name, namespace: :current_attributes) do |batch|
|
|
@@ -115,32 +137,17 @@ module ActiveSupport
|
|
|
115
137
|
end
|
|
116
138
|
end
|
|
117
139
|
|
|
118
|
-
|
|
119
|
-
names.each do |name|
|
|
120
|
-
owner.define_cached_method(name, namespace: :current_attributes_delegation) do |batch|
|
|
121
|
-
batch <<
|
|
122
|
-
"def #{name}" <<
|
|
123
|
-
"instance.#{name}" <<
|
|
124
|
-
"end"
|
|
125
|
-
end
|
|
126
|
-
owner.define_cached_method("#{name}=", namespace: :current_attributes_delegation) do |batch|
|
|
127
|
-
batch <<
|
|
128
|
-
"def #{name}=(value)" <<
|
|
129
|
-
"instance.#{name} = value" <<
|
|
130
|
-
"end"
|
|
131
|
-
end
|
|
132
|
-
end
|
|
133
|
-
end
|
|
140
|
+
self.defaults = defaults.merge(names.index_with { default })
|
|
134
141
|
end
|
|
135
142
|
|
|
136
|
-
# Calls this
|
|
137
|
-
def before_reset(&block)
|
|
138
|
-
set_callback :reset, :before, &block
|
|
143
|
+
# Calls this callback before #reset is called on the instance. Used for resetting external collaborators that depend on current values.
|
|
144
|
+
def before_reset(*methods, &block)
|
|
145
|
+
set_callback :reset, :before, *methods, &block
|
|
139
146
|
end
|
|
140
147
|
|
|
141
|
-
# Calls this
|
|
142
|
-
def resets(&block)
|
|
143
|
-
set_callback :reset, :after, &block
|
|
148
|
+
# Calls this callback after #reset is called on the instance. Used for resetting external collaborators, like Time.zone.
|
|
149
|
+
def resets(*methods, &block)
|
|
150
|
+
set_callback :reset, :after, *methods, &block
|
|
144
151
|
end
|
|
145
152
|
alias_method :after_reset, :resets
|
|
146
153
|
|
|
@@ -168,25 +175,36 @@ module ActiveSupport
|
|
|
168
175
|
@current_instances_key ||= name.to_sym
|
|
169
176
|
end
|
|
170
177
|
|
|
171
|
-
def method_missing(name,
|
|
172
|
-
|
|
173
|
-
#
|
|
174
|
-
# By letting #delegate handle it, we avoid an enclosure that'll capture args.
|
|
175
|
-
singleton_class.delegate name, to: :instance
|
|
176
|
-
|
|
177
|
-
send(name, *args, &block)
|
|
178
|
+
def method_missing(name, ...)
|
|
179
|
+
instance.public_send(name, ...)
|
|
178
180
|
end
|
|
179
|
-
ruby2_keywords(:method_missing)
|
|
180
181
|
|
|
181
182
|
def respond_to_missing?(name, _)
|
|
182
|
-
|
|
183
|
+
instance.respond_to?(name) || super
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def method_added(name)
|
|
187
|
+
super
|
|
188
|
+
|
|
189
|
+
# We try to generate instance delegators early to not rely on method_missing.
|
|
190
|
+
return if name == :initialize
|
|
191
|
+
|
|
192
|
+
# If the added method isn't public, we don't delegate it.
|
|
193
|
+
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
|
+
|
|
198
|
+
Delegation.generate(singleton_class, [name], to: :instance, as: self, nilable: false)
|
|
183
199
|
end
|
|
184
200
|
end
|
|
185
201
|
|
|
202
|
+
class_attribute :defaults, instance_writer: false, default: {}.freeze
|
|
203
|
+
|
|
186
204
|
attr_accessor :attributes
|
|
187
205
|
|
|
188
206
|
def initialize
|
|
189
|
-
@attributes =
|
|
207
|
+
@attributes = resolve_defaults
|
|
190
208
|
end
|
|
191
209
|
|
|
192
210
|
# Expose one or more attributes within a block. Old values are returned after the block concludes.
|
|
@@ -199,28 +217,24 @@ module ActiveSupport
|
|
|
199
217
|
# end
|
|
200
218
|
# end
|
|
201
219
|
# end
|
|
202
|
-
def set(
|
|
203
|
-
|
|
204
|
-
assign_attributes(set_attributes)
|
|
205
|
-
yield
|
|
206
|
-
ensure
|
|
207
|
-
assign_attributes(old_attributes)
|
|
220
|
+
def set(attributes, &block)
|
|
221
|
+
with(**attributes, &block)
|
|
208
222
|
end
|
|
209
223
|
|
|
210
224
|
# Reset all attributes. Should be called before and after actions, when used as a per-request singleton.
|
|
211
225
|
def reset
|
|
212
226
|
run_callbacks :reset do
|
|
213
|
-
self.attributes =
|
|
227
|
+
self.attributes = resolve_defaults
|
|
214
228
|
end
|
|
215
229
|
end
|
|
216
230
|
|
|
217
231
|
private
|
|
218
|
-
def
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
232
|
+
def resolve_defaults
|
|
233
|
+
defaults.each_with_object({}) do |(key, value), result|
|
|
234
|
+
if value != NOT_SET
|
|
235
|
+
result[key] = Proc === value ? value.call : value.dup
|
|
236
|
+
end
|
|
237
|
+
end
|
|
224
238
|
end
|
|
225
239
|
end
|
|
226
240
|
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveSupport
|
|
4
|
+
# Provides +deep_merge+ and +deep_merge!+ methods. Expects the including class
|
|
5
|
+
# to provide a <tt>merge!(other, &block)</tt> method.
|
|
6
|
+
module DeepMergeable # :nodoc:
|
|
7
|
+
# Returns a new instance with the values from +other+ merged recursively.
|
|
8
|
+
#
|
|
9
|
+
# class Hash
|
|
10
|
+
# include ActiveSupport::DeepMergeable
|
|
11
|
+
# end
|
|
12
|
+
#
|
|
13
|
+
# hash_1 = { a: true, b: { c: [1, 2, 3] } }
|
|
14
|
+
# hash_2 = { a: false, b: { x: [3, 4, 5] } }
|
|
15
|
+
#
|
|
16
|
+
# hash_1.deep_merge(hash_2)
|
|
17
|
+
# # => { a: false, b: { c: [1, 2, 3], x: [3, 4, 5] } }
|
|
18
|
+
#
|
|
19
|
+
# A block can be provided to merge non-<tt>DeepMergeable</tt> values:
|
|
20
|
+
#
|
|
21
|
+
# hash_1 = { a: 100, b: 200, c: { c1: 100 } }
|
|
22
|
+
# hash_2 = { b: 250, c: { c1: 200 } }
|
|
23
|
+
#
|
|
24
|
+
# hash_1.deep_merge(hash_2) do |key, this_val, other_val|
|
|
25
|
+
# this_val + other_val
|
|
26
|
+
# end
|
|
27
|
+
# # => { a: 100, b: 450, c: { c1: 300 } }
|
|
28
|
+
#
|
|
29
|
+
def deep_merge(other, &block)
|
|
30
|
+
dup.deep_merge!(other, &block)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Same as #deep_merge, but modifies +self+.
|
|
34
|
+
def deep_merge!(other, &block)
|
|
35
|
+
merge!(other) do |key, this_val, other_val|
|
|
36
|
+
if this_val.is_a?(DeepMergeable) && this_val.deep_merge?(other_val)
|
|
37
|
+
this_val.deep_merge(other_val, &block)
|
|
38
|
+
elsif block_given?
|
|
39
|
+
block.call(key, this_val, other_val)
|
|
40
|
+
else
|
|
41
|
+
other_val
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Returns true if +other+ can be deep merged into +self+. Classes may
|
|
47
|
+
# override this method to restrict or expand the domain of deep mergeable
|
|
48
|
+
# values. Defaults to checking that +other+ is of type +self.class+.
|
|
49
|
+
def deep_merge?(other)
|
|
50
|
+
other.is_a?(self.class)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "set"
|
|
4
|
+
|
|
5
|
+
module ActiveSupport
|
|
6
|
+
# Error generated by +delegate+ when a method is called on +nil+ and +allow_nil+
|
|
7
|
+
# option is not used.
|
|
8
|
+
class DelegationError < NoMethodError
|
|
9
|
+
class << self
|
|
10
|
+
def nil_target(method_name, target) # :nodoc:
|
|
11
|
+
new("#{method_name} delegated to #{target}, but #{target} is nil")
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
module Delegation # :nodoc:
|
|
17
|
+
RUBY_RESERVED_KEYWORDS = %w(__ENCODING__ __LINE__ __FILE__ alias and BEGIN begin break
|
|
18
|
+
case class def defined? do else elsif END end ensure false for if in module next nil
|
|
19
|
+
not or redo rescue retry return self super then true undef unless until when while yield)
|
|
20
|
+
RESERVED_METHOD_NAMES = (RUBY_RESERVED_KEYWORDS + %w(_ arg args block)).to_set.freeze
|
|
21
|
+
|
|
22
|
+
class << self
|
|
23
|
+
def generate(owner, methods, location: nil, to: nil, prefix: nil, allow_nil: nil, nilable: true, private: nil, as: nil, signature: nil)
|
|
24
|
+
unless to
|
|
25
|
+
raise ArgumentError, "Delegation needs a target. Supply a keyword argument 'to' (e.g. delegate :hello, to: :greeter)."
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
if prefix == true && /^[^a-z_]/.match?(to)
|
|
29
|
+
raise ArgumentError, "Can only automatically set the delegation prefix when delegating to a method."
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
method_prefix = \
|
|
33
|
+
if prefix
|
|
34
|
+
"#{prefix == true ? to : prefix}_"
|
|
35
|
+
else
|
|
36
|
+
""
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
location ||= caller_locations(1, 1).first
|
|
40
|
+
file, line = location.path, location.lineno
|
|
41
|
+
|
|
42
|
+
receiver = if to.is_a?(Module)
|
|
43
|
+
if to.name.nil?
|
|
44
|
+
raise ArgumentError, "Can't delegate to anonymous class or module: #{to}"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
unless Inflector.safe_constantize(to.name).equal?(to)
|
|
48
|
+
raise ArgumentError, "Can't delegate to detached class or module: #{to.name}"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
"::#{to.name}"
|
|
52
|
+
else
|
|
53
|
+
to.to_s
|
|
54
|
+
end
|
|
55
|
+
receiver = "self.#{receiver}" if RESERVED_METHOD_NAMES.include?(receiver)
|
|
56
|
+
|
|
57
|
+
explicit_receiver = false
|
|
58
|
+
receiver_class = if as
|
|
59
|
+
explicit_receiver = true
|
|
60
|
+
as
|
|
61
|
+
elsif to.is_a?(Module)
|
|
62
|
+
to.singleton_class
|
|
63
|
+
elsif receiver == "self.class"
|
|
64
|
+
nilable = false # self.class can't possibly be nil
|
|
65
|
+
owner.singleton_class
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
method_def = []
|
|
69
|
+
method_names = []
|
|
70
|
+
|
|
71
|
+
method_def << "self.private" if private
|
|
72
|
+
|
|
73
|
+
methods.each do |method|
|
|
74
|
+
method_name = prefix ? "#{method_prefix}#{method}" : method
|
|
75
|
+
method_names << method_name.to_sym
|
|
76
|
+
|
|
77
|
+
# Attribute writer methods only accept one argument. Makes sure []=
|
|
78
|
+
# methods still accept two arguments.
|
|
79
|
+
definition = \
|
|
80
|
+
if signature
|
|
81
|
+
signature
|
|
82
|
+
elsif /[^\]]=\z/.match?(method)
|
|
83
|
+
"arg"
|
|
84
|
+
else
|
|
85
|
+
method_object = if receiver_class
|
|
86
|
+
begin
|
|
87
|
+
receiver_class.public_instance_method(method)
|
|
88
|
+
rescue NameError
|
|
89
|
+
raise if explicit_receiver
|
|
90
|
+
# Do nothing. Fall back to `"..."`
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
if method_object
|
|
95
|
+
parameters = method_object.parameters
|
|
96
|
+
|
|
97
|
+
if parameters.map(&:first).intersect?([:opt, :rest, :keyreq, :key, :keyrest])
|
|
98
|
+
"..."
|
|
99
|
+
else
|
|
100
|
+
defn = parameters.filter_map { |type, arg| arg if type == :req }
|
|
101
|
+
defn << "&"
|
|
102
|
+
defn.join(", ")
|
|
103
|
+
end
|
|
104
|
+
else
|
|
105
|
+
"..."
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# The following generated method calls the target exactly once, storing
|
|
110
|
+
# the returned value in a dummy variable.
|
|
111
|
+
#
|
|
112
|
+
# Reason is twofold: On one hand doing less calls is in general better.
|
|
113
|
+
# On the other hand it could be that the target has side-effects,
|
|
114
|
+
# whereas conceptually, from the user point of view, the delegator should
|
|
115
|
+
# be doing one call.
|
|
116
|
+
if nilable == false
|
|
117
|
+
method_def <<
|
|
118
|
+
"def #{method_name}(#{definition})" <<
|
|
119
|
+
" (#{receiver}).#{method}(#{definition})" <<
|
|
120
|
+
"end"
|
|
121
|
+
elsif allow_nil
|
|
122
|
+
method = method.to_s
|
|
123
|
+
|
|
124
|
+
method_def <<
|
|
125
|
+
"def #{method_name}(#{definition})" <<
|
|
126
|
+
" _ = #{receiver}" <<
|
|
127
|
+
" if !_.nil? || nil.respond_to?(:#{method})" <<
|
|
128
|
+
" _.#{method}(#{definition})" <<
|
|
129
|
+
" end" <<
|
|
130
|
+
"end"
|
|
131
|
+
else
|
|
132
|
+
method = method.to_s
|
|
133
|
+
method_name = method_name.to_s
|
|
134
|
+
|
|
135
|
+
method_def <<
|
|
136
|
+
"def #{method_name}(#{definition})" <<
|
|
137
|
+
" _ = #{receiver}" <<
|
|
138
|
+
" _.#{method}(#{definition})" <<
|
|
139
|
+
"rescue NoMethodError => e" <<
|
|
140
|
+
" if _.nil? && e.name == :#{method}" <<
|
|
141
|
+
" raise ::ActiveSupport::DelegationError.nil_target(:#{method_name}, :'#{receiver}')" <<
|
|
142
|
+
" else" <<
|
|
143
|
+
" raise" <<
|
|
144
|
+
" end" <<
|
|
145
|
+
"end"
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
owner.module_eval(method_def.join(";"), file, line)
|
|
149
|
+
method_names
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def generate_method_missing(owner, target, allow_nil: nil)
|
|
153
|
+
target = target.to_s
|
|
154
|
+
target = "self.#{target}" if RESERVED_METHOD_NAMES.include?(target) || target == "__target"
|
|
155
|
+
|
|
156
|
+
if allow_nil
|
|
157
|
+
owner.module_eval <<~RUBY, __FILE__, __LINE__ + 1
|
|
158
|
+
def respond_to_missing?(name, include_private = false)
|
|
159
|
+
# It may look like an oversight, but we deliberately do not pass
|
|
160
|
+
# +include_private+, because they do not get delegated.
|
|
161
|
+
|
|
162
|
+
return false if name == :marshal_dump || name == :_dump
|
|
163
|
+
#{target}.respond_to?(name) || super
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def method_missing(method, ...)
|
|
167
|
+
__target = #{target}
|
|
168
|
+
if __target.nil? && !nil.respond_to?(method)
|
|
169
|
+
nil
|
|
170
|
+
elsif __target.respond_to?(method)
|
|
171
|
+
__target.public_send(method, ...)
|
|
172
|
+
else
|
|
173
|
+
super
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
RUBY
|
|
177
|
+
else
|
|
178
|
+
owner.module_eval <<~RUBY, __FILE__, __LINE__ + 1
|
|
179
|
+
def respond_to_missing?(name, include_private = false)
|
|
180
|
+
# It may look like an oversight, but we deliberately do not pass
|
|
181
|
+
# +include_private+, because they do not get delegated.
|
|
182
|
+
|
|
183
|
+
return false if name == :marshal_dump || name == :_dump
|
|
184
|
+
#{target}.respond_to?(name) || super
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def method_missing(method, ...)
|
|
188
|
+
__target = #{target}
|
|
189
|
+
if __target.nil? && !nil.respond_to?(method)
|
|
190
|
+
raise ::ActiveSupport::DelegationError.nil_target(method, :'#{target}')
|
|
191
|
+
elsif __target.respond_to?(method)
|
|
192
|
+
__target.public_send(method, ...)
|
|
193
|
+
else
|
|
194
|
+
super
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
RUBY
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
end
|
|
@@ -3,10 +3,12 @@
|
|
|
3
3
|
require "active_support/inflector/methods"
|
|
4
4
|
|
|
5
5
|
module ActiveSupport
|
|
6
|
+
# = Active Support \Autoload
|
|
7
|
+
#
|
|
6
8
|
# Autoload and eager load conveniences for your library.
|
|
7
9
|
#
|
|
8
10
|
# This module allows you to define autoloads based on
|
|
9
|
-
# Rails conventions (i.e. no need to define the path
|
|
11
|
+
# \Rails conventions (i.e. no need to define the path
|
|
10
12
|
# it is automatically guessed based on the filename)
|
|
11
13
|
# and also define a set of constants that needs to be
|
|
12
14
|
# eager loaded:
|
|
@@ -25,15 +27,6 @@ module ActiveSupport
|
|
|
25
27
|
#
|
|
26
28
|
# MyLib.eager_load!
|
|
27
29
|
module Autoload
|
|
28
|
-
def self.extended(base) # :nodoc:
|
|
29
|
-
base.class_eval do
|
|
30
|
-
@_autoloads = {}
|
|
31
|
-
@_under_path = nil
|
|
32
|
-
@_at_path = nil
|
|
33
|
-
@_eager_autoload = false
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
30
|
def autoload(const_name, path = @_at_path)
|
|
38
31
|
unless path
|
|
39
32
|
full = [name, @_under_path, const_name.to_s].compact.join("::")
|
|
@@ -41,7 +34,8 @@ module ActiveSupport
|
|
|
41
34
|
end
|
|
42
35
|
|
|
43
36
|
if @_eager_autoload
|
|
44
|
-
@
|
|
37
|
+
@_eagerloaded_constants ||= []
|
|
38
|
+
@_eagerloaded_constants << const_name
|
|
45
39
|
end
|
|
46
40
|
|
|
47
41
|
super const_name, path
|
|
@@ -69,11 +63,10 @@ module ActiveSupport
|
|
|
69
63
|
end
|
|
70
64
|
|
|
71
65
|
def eager_load!
|
|
72
|
-
@
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
@_autoloads
|
|
66
|
+
if @_eagerloaded_constants
|
|
67
|
+
@_eagerloaded_constants.each { |const_name| const_get(const_name) }
|
|
68
|
+
@_eagerloaded_constants = nil
|
|
69
|
+
end
|
|
77
70
|
end
|
|
78
71
|
end
|
|
79
72
|
end
|
|
@@ -11,18 +11,18 @@ module ActiveSupport
|
|
|
11
11
|
class Deprecation
|
|
12
12
|
# Default warning behaviors per Rails.env.
|
|
13
13
|
DEFAULT_BEHAVIORS = {
|
|
14
|
-
raise: ->(message, callstack,
|
|
14
|
+
raise: ->(message, callstack, deprecator) do
|
|
15
15
|
e = DeprecationException.new(message)
|
|
16
16
|
e.set_backtrace(callstack.map(&:to_s))
|
|
17
17
|
raise e
|
|
18
|
-
|
|
18
|
+
end,
|
|
19
19
|
|
|
20
|
-
stderr: ->(message, callstack,
|
|
20
|
+
stderr: ->(message, callstack, deprecator) do
|
|
21
21
|
$stderr.puts(message)
|
|
22
|
-
$stderr.puts callstack.join("\n ") if debug
|
|
23
|
-
|
|
22
|
+
$stderr.puts callstack.join("\n ") if deprecator.debug
|
|
23
|
+
end,
|
|
24
24
|
|
|
25
|
-
log: ->(message, callstack,
|
|
25
|
+
log: ->(message, callstack, deprecator) do
|
|
26
26
|
logger =
|
|
27
27
|
if defined?(Rails.logger) && Rails.logger
|
|
28
28
|
Rails.logger
|
|
@@ -31,33 +31,41 @@ module ActiveSupport
|
|
|
31
31
|
ActiveSupport::Logger.new($stderr)
|
|
32
32
|
end
|
|
33
33
|
logger.warn message
|
|
34
|
-
logger.debug callstack.join("\n ") if debug
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
notify: ->(message, callstack,
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
34
|
+
logger.debug callstack.join("\n ") if deprecator.debug
|
|
35
|
+
end,
|
|
36
|
+
|
|
37
|
+
notify: ->(message, callstack, deprecator) do
|
|
38
|
+
ActiveSupport::Notifications.instrument(
|
|
39
|
+
"deprecation.#{deprecator.gem_name.underscore.tr("/", "_")}",
|
|
40
|
+
message: message,
|
|
41
|
+
callstack: callstack,
|
|
42
|
+
gem_name: deprecator.gem_name,
|
|
43
|
+
deprecation_horizon: deprecator.deprecation_horizon,
|
|
44
|
+
)
|
|
45
|
+
end,
|
|
46
|
+
|
|
47
|
+
silence: ->(message, callstack, deprecator) { },
|
|
48
|
+
|
|
49
|
+
report: ->(message, callstack, deprecator) do
|
|
50
|
+
error = DeprecationException.new(message)
|
|
51
|
+
error.set_backtrace(callstack.map(&:to_s))
|
|
52
|
+
ActiveSupport.error_reporter.report(error)
|
|
53
|
+
end
|
|
47
54
|
}
|
|
48
55
|
|
|
49
56
|
# Behavior module allows to determine how to display deprecation messages.
|
|
50
57
|
# You can create a custom behavior or set any from the +DEFAULT_BEHAVIORS+
|
|
51
58
|
# constant. Available behaviors are:
|
|
52
59
|
#
|
|
53
|
-
# [
|
|
54
|
-
# [
|
|
55
|
-
# [
|
|
56
|
-
# [
|
|
57
|
-
# [+
|
|
60
|
+
# [+:raise+] Raise ActiveSupport::DeprecationException.
|
|
61
|
+
# [+:stderr+] Log all deprecation warnings to <tt>$stderr</tt>.
|
|
62
|
+
# [+:log+] Log all deprecation warnings to +Rails.logger+.
|
|
63
|
+
# [+:notify+] Use ActiveSupport::Notifications to notify +deprecation.rails+.
|
|
64
|
+
# [+:report+] Use ActiveSupport::ErrorReporter to report deprecations.
|
|
65
|
+
# [+:silence+] Do nothing. On \Rails, set <tt>config.active_support.report_deprecations = false</tt> to disable all behaviors.
|
|
58
66
|
#
|
|
59
67
|
# Setting behaviors only affects deprecations that happen after boot time.
|
|
60
|
-
# For more information you can read the documentation of the
|
|
68
|
+
# For more information you can read the documentation of the #behavior= method.
|
|
61
69
|
module Behavior
|
|
62
70
|
# Whether to print a backtrace along with the warning.
|
|
63
71
|
attr_accessor :debug
|
|
@@ -77,32 +85,36 @@ module ActiveSupport
|
|
|
77
85
|
#
|
|
78
86
|
# Available behaviors:
|
|
79
87
|
#
|
|
80
|
-
# [
|
|
81
|
-
# [
|
|
82
|
-
# [
|
|
83
|
-
# [
|
|
84
|
-
# [+
|
|
88
|
+
# [+:raise+] Raise ActiveSupport::DeprecationException.
|
|
89
|
+
# [+:stderr+] Log all deprecation warnings to <tt>$stderr</tt>.
|
|
90
|
+
# [+:log+] Log all deprecation warnings to +Rails.logger+.
|
|
91
|
+
# [+:notify+] Use ActiveSupport::Notifications to notify +deprecation.rails+.
|
|
92
|
+
# [+:report+] Use ActiveSupport::ErrorReporter to report deprecations.
|
|
93
|
+
# [+:silence+] Do nothing.
|
|
85
94
|
#
|
|
86
95
|
# Setting behaviors only affects deprecations that happen after boot time.
|
|
87
96
|
# Deprecation warnings raised by gems are not affected by this setting
|
|
88
|
-
# because they happen before Rails boots up.
|
|
97
|
+
# because they happen before \Rails boots up.
|
|
89
98
|
#
|
|
90
|
-
# ActiveSupport::Deprecation.
|
|
91
|
-
#
|
|
92
|
-
#
|
|
93
|
-
#
|
|
99
|
+
# deprecator = ActiveSupport::Deprecation.new
|
|
100
|
+
# deprecator.behavior = :stderr
|
|
101
|
+
# deprecator.behavior = [:stderr, :log]
|
|
102
|
+
# deprecator.behavior = MyCustomHandler
|
|
103
|
+
# deprecator.behavior = ->(message, callstack, deprecation_horizon, gem_name) {
|
|
94
104
|
# # custom stuff
|
|
95
105
|
# }
|
|
96
106
|
#
|
|
97
|
-
# If you are using Rails, you can set
|
|
98
|
-
#
|
|
107
|
+
# If you are using \Rails, you can set
|
|
108
|
+
# <tt>config.active_support.report_deprecations = false</tt> to disable
|
|
109
|
+
# all deprecation behaviors. This is similar to the +:silence+ option but
|
|
110
|
+
# more performant.
|
|
99
111
|
def behavior=(behavior)
|
|
100
112
|
@behavior = Array(behavior).map { |b| DEFAULT_BEHAVIORS[b] || arity_coerce(b) }
|
|
101
113
|
end
|
|
102
114
|
|
|
103
115
|
# Sets the behavior for disallowed deprecations (those configured by
|
|
104
|
-
# ActiveSupport::Deprecation
|
|
105
|
-
# value. As with
|
|
116
|
+
# ActiveSupport::Deprecation#disallowed_warnings=) to the specified
|
|
117
|
+
# value. As with #behavior=, this can be a single value, array, or an
|
|
106
118
|
# object that responds to +call+.
|
|
107
119
|
def disallowed_behavior=(behavior)
|
|
108
120
|
@disallowed_behavior = Array(behavior).map { |b| DEFAULT_BEHAVIORS[b] || arity_coerce(b) }
|
|
@@ -114,12 +126,23 @@ module ActiveSupport
|
|
|
114
126
|
raise ArgumentError, "#{behavior.inspect} is not a valid deprecation behavior."
|
|
115
127
|
end
|
|
116
128
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
129
|
+
case arity_of_callable(behavior)
|
|
130
|
+
when 2
|
|
131
|
+
->(message, callstack, deprecator) do
|
|
132
|
+
behavior.call(message, callstack)
|
|
133
|
+
end
|
|
134
|
+
when -2..3
|
|
120
135
|
behavior
|
|
136
|
+
else
|
|
137
|
+
->(message, callstack, deprecator) do
|
|
138
|
+
behavior.call(message, callstack, deprecator.deprecation_horizon, deprecator.gem_name)
|
|
139
|
+
end
|
|
121
140
|
end
|
|
122
141
|
end
|
|
142
|
+
|
|
143
|
+
def arity_of_callable(callable)
|
|
144
|
+
callable.respond_to?(:arity) ? callable.arity : callable.method(:call).arity
|
|
145
|
+
end
|
|
123
146
|
end
|
|
124
147
|
end
|
|
125
148
|
end
|