activesupport 4.2.0 → 5.2.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 +5 -5
- data/CHANGELOG.md +366 -232
- data/MIT-LICENSE +2 -2
- data/README.rdoc +4 -5
- data/lib/active_support.rb +17 -7
- data/lib/active_support/all.rb +5 -3
- data/lib/active_support/array_inquirer.rb +48 -0
- data/lib/active_support/backtrace_cleaner.rb +7 -5
- data/lib/active_support/benchmarkable.rb +6 -4
- data/lib/active_support/builder.rb +3 -1
- data/lib/active_support/cache.rb +271 -177
- data/lib/active_support/cache/file_store.rb +41 -35
- data/lib/active_support/cache/mem_cache_store.rb +97 -88
- data/lib/active_support/cache/memory_store.rb +27 -30
- data/lib/active_support/cache/null_store.rb +7 -8
- data/lib/active_support/cache/redis_cache_store.rb +454 -0
- data/lib/active_support/cache/strategy/local_cache.rb +67 -34
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
- data/lib/active_support/callbacks.rb +654 -560
- data/lib/active_support/concern.rb +5 -3
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +17 -0
- data/lib/active_support/concurrency/share_lock.rb +227 -0
- data/lib/active_support/configurable.rb +8 -5
- data/lib/active_support/core_ext.rb +3 -1
- data/lib/active_support/core_ext/array.rb +9 -6
- data/lib/active_support/core_ext/array/access.rb +29 -1
- data/lib/active_support/core_ext/array/conversions.rb +22 -18
- data/lib/active_support/core_ext/array/extract_options.rb +2 -0
- data/lib/active_support/core_ext/array/grouping.rb +11 -18
- data/lib/active_support/core_ext/array/inquiry.rb +19 -0
- data/lib/active_support/core_ext/array/prepend_and_append.rb +5 -3
- data/lib/active_support/core_ext/array/wrap.rb +7 -4
- data/lib/active_support/core_ext/benchmark.rb +3 -1
- data/lib/active_support/core_ext/big_decimal.rb +3 -1
- data/lib/active_support/core_ext/big_decimal/conversions.rb +10 -12
- data/lib/active_support/core_ext/class.rb +4 -3
- data/lib/active_support/core_ext/class/attribute.rb +41 -22
- data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
- data/lib/active_support/core_ext/class/subclasses.rb +20 -8
- data/lib/active_support/core_ext/date.rb +6 -4
- data/lib/active_support/core_ext/date/acts_like.rb +3 -1
- data/lib/active_support/core_ext/date/blank.rb +14 -0
- data/lib/active_support/core_ext/date/calculations.rb +11 -9
- data/lib/active_support/core_ext/date/conversions.rb +31 -23
- data/lib/active_support/core_ext/date/zones.rb +4 -2
- data/lib/active_support/core_ext/date_and_time/calculations.rb +179 -56
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +16 -0
- data/lib/active_support/core_ext/date_and_time/zones.rb +12 -12
- data/lib/active_support/core_ext/date_time.rb +7 -4
- data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
- data/lib/active_support/core_ext/date_time/blank.rb +14 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +58 -20
- data/lib/active_support/core_ext/date_time/compatibility.rb +18 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +16 -12
- data/lib/active_support/core_ext/digest/uuid.rb +7 -5
- data/lib/active_support/core_ext/enumerable.rb +107 -28
- data/lib/active_support/core_ext/file.rb +3 -1
- data/lib/active_support/core_ext/file/atomic.rb +38 -31
- data/lib/active_support/core_ext/hash.rb +11 -9
- data/lib/active_support/core_ext/hash/compact.rb +24 -15
- data/lib/active_support/core_ext/hash/conversions.rb +63 -43
- data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
- data/lib/active_support/core_ext/hash/except.rb +11 -8
- data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -3
- data/lib/active_support/core_ext/hash/keys.rb +33 -27
- data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
- data/lib/active_support/core_ext/hash/slice.rb +8 -8
- data/lib/active_support/core_ext/hash/transform_values.rb +16 -7
- data/lib/active_support/core_ext/integer.rb +5 -3
- data/lib/active_support/core_ext/integer/inflections.rb +3 -1
- data/lib/active_support/core_ext/integer/multiple.rb +2 -0
- data/lib/active_support/core_ext/integer/time.rb +11 -33
- data/lib/active_support/core_ext/kernel.rb +6 -5
- data/lib/active_support/core_ext/kernel/agnostics.rb +2 -0
- data/lib/active_support/core_ext/kernel/concern.rb +5 -1
- data/lib/active_support/core_ext/kernel/reporting.rb +4 -83
- data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
- data/lib/active_support/core_ext/load_error.rb +3 -22
- data/lib/active_support/core_ext/marshal.rb +13 -10
- data/lib/active_support/core_ext/module.rb +14 -11
- data/lib/active_support/core_ext/module/aliasing.rb +6 -44
- data/lib/active_support/core_ext/module/anonymous.rb +12 -1
- data/lib/active_support/core_ext/module/attr_internal.rb +8 -9
- data/lib/active_support/core_ext/module/attribute_accessors.rb +43 -40
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +150 -0
- data/lib/active_support/core_ext/module/concerning.rb +11 -12
- data/lib/active_support/core_ext/module/delegation.rb +121 -39
- data/lib/active_support/core_ext/module/deprecation.rb +4 -2
- data/lib/active_support/core_ext/module/introspection.rb +9 -9
- data/lib/active_support/core_ext/module/reachable.rb +5 -2
- data/lib/active_support/core_ext/module/redefine_method.rb +49 -0
- data/lib/active_support/core_ext/module/remove_method.rb +8 -3
- data/lib/active_support/core_ext/name_error.rb +22 -2
- data/lib/active_support/core_ext/numeric.rb +6 -3
- data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +79 -74
- data/lib/active_support/core_ext/numeric/inquiry.rb +28 -0
- data/lib/active_support/core_ext/numeric/time.rb +35 -38
- data/lib/active_support/core_ext/object.rb +14 -13
- data/lib/active_support/core_ext/object/acts_like.rb +12 -1
- data/lib/active_support/core_ext/object/blank.rb +29 -4
- data/lib/active_support/core_ext/object/conversions.rb +6 -4
- data/lib/active_support/core_ext/object/deep_dup.rb +13 -4
- data/lib/active_support/core_ext/object/duplicable.rb +98 -45
- data/lib/active_support/core_ext/object/inclusion.rb +5 -3
- data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
- data/lib/active_support/core_ext/object/json.rb +49 -19
- data/lib/active_support/core_ext/object/to_param.rb +3 -1
- data/lib/active_support/core_ext/object/to_query.rb +6 -4
- data/lib/active_support/core_ext/object/try.rb +70 -22
- data/lib/active_support/core_ext/object/with_options.rb +16 -3
- data/lib/active_support/core_ext/range.rb +7 -4
- data/lib/active_support/core_ext/range/conversions.rb +27 -7
- data/lib/active_support/core_ext/range/each.rb +19 -17
- data/lib/active_support/core_ext/range/include_range.rb +21 -19
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -0
- data/lib/active_support/core_ext/range/overlaps.rb +2 -0
- data/lib/active_support/core_ext/regexp.rb +6 -0
- data/lib/active_support/core_ext/securerandom.rb +25 -0
- data/lib/active_support/core_ext/string.rb +15 -13
- data/lib/active_support/core_ext/string/access.rb +9 -7
- data/lib/active_support/core_ext/string/behavior.rb +3 -1
- data/lib/active_support/core_ext/string/conversions.rb +8 -5
- data/lib/active_support/core_ext/string/exclude.rb +2 -0
- data/lib/active_support/core_ext/string/filters.rb +10 -8
- data/lib/active_support/core_ext/string/indent.rb +6 -4
- data/lib/active_support/core_ext/string/inflections.rb +61 -24
- data/lib/active_support/core_ext/string/inquiry.rb +3 -1
- data/lib/active_support/core_ext/string/multibyte.rb +15 -7
- data/lib/active_support/core_ext/string/output_safety.rb +35 -35
- data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
- data/lib/active_support/core_ext/string/strip.rb +4 -5
- data/lib/active_support/core_ext/string/zones.rb +4 -2
- data/lib/active_support/core_ext/time.rb +7 -5
- data/lib/active_support/core_ext/time/acts_like.rb +3 -1
- data/lib/active_support/core_ext/time/calculations.rb +101 -51
- data/lib/active_support/core_ext/time/compatibility.rb +16 -0
- data/lib/active_support/core_ext/time/conversions.rb +20 -13
- data/lib/active_support/core_ext/time/zones.rb +41 -7
- data/lib/active_support/core_ext/uri.rb +5 -4
- data/lib/active_support/current_attributes.rb +195 -0
- data/lib/active_support/dependencies.rb +143 -160
- data/lib/active_support/dependencies/autoload.rb +2 -0
- data/lib/active_support/dependencies/interlock.rb +57 -0
- data/lib/active_support/deprecation.rb +12 -9
- data/lib/active_support/deprecation/behaviors.rb +41 -12
- data/lib/active_support/deprecation/constant_accessor.rb +52 -0
- data/lib/active_support/deprecation/instance_delegator.rb +17 -2
- data/lib/active_support/deprecation/method_wrappers.rb +54 -21
- data/lib/active_support/deprecation/proxy_wrappers.rb +56 -28
- data/lib/active_support/deprecation/reporting.rb +32 -12
- data/lib/active_support/descendants_tracker.rb +2 -0
- data/lib/active_support/digest.rb +20 -0
- data/lib/active_support/duration.rb +326 -30
- data/lib/active_support/duration/iso8601_parser.rb +125 -0
- data/lib/active_support/duration/iso8601_serializer.rb +55 -0
- data/lib/active_support/encrypted_configuration.rb +49 -0
- data/lib/active_support/encrypted_file.rb +99 -0
- data/lib/active_support/evented_file_update_checker.rb +205 -0
- data/lib/active_support/execution_wrapper.rb +128 -0
- data/lib/active_support/executor.rb +8 -0
- data/lib/active_support/file_update_checker.rb +63 -37
- data/lib/active_support/gem_version.rb +4 -2
- data/lib/active_support/gzip.rb +7 -5
- data/lib/active_support/hash_with_indifferent_access.rb +130 -30
- data/lib/active_support/i18n.rb +8 -6
- data/lib/active_support/i18n_railtie.rb +34 -14
- data/lib/active_support/inflections.rb +13 -11
- data/lib/active_support/inflector.rb +7 -5
- data/lib/active_support/inflector/inflections.rb +61 -12
- data/lib/active_support/inflector/methods.rb +161 -136
- data/lib/active_support/inflector/transliterate.rb +48 -27
- data/lib/active_support/json.rb +4 -2
- data/lib/active_support/json/decoding.rb +16 -13
- data/lib/active_support/json/encoding.rb +15 -57
- data/lib/active_support/key_generator.rb +25 -25
- data/lib/active_support/lazy_load_hooks.rb +50 -20
- data/lib/active_support/locale/en.yml +2 -0
- data/lib/active_support/log_subscriber.rb +13 -10
- data/lib/active_support/log_subscriber/test_helper.rb +14 -12
- data/lib/active_support/logger.rb +54 -3
- data/lib/active_support/logger_silence.rb +12 -7
- data/lib/active_support/logger_thread_safe_level.rb +33 -0
- data/lib/active_support/message_encryptor.rb +173 -51
- data/lib/active_support/message_verifier.rb +150 -17
- data/lib/active_support/messages/metadata.rb +71 -0
- data/lib/active_support/messages/rotation_configuration.rb +22 -0
- data/lib/active_support/messages/rotator.rb +56 -0
- data/lib/active_support/multibyte.rb +4 -2
- data/lib/active_support/multibyte/chars.rb +37 -24
- data/lib/active_support/multibyte/unicode.rb +100 -96
- data/lib/active_support/notifications.rb +11 -7
- data/lib/active_support/notifications/fanout.rb +10 -8
- data/lib/active_support/notifications/instrumenter.rb +27 -7
- data/lib/active_support/number_helper.rb +94 -68
- data/lib/active_support/number_helper/number_converter.rb +13 -11
- data/lib/active_support/number_helper/number_to_currency_converter.rb +9 -9
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +9 -3
- data/lib/active_support/number_helper/number_to_human_converter.rb +11 -9
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +9 -8
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +13 -4
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +23 -56
- data/lib/active_support/number_helper/rounding_helper.rb +66 -0
- data/lib/active_support/option_merger.rb +3 -1
- data/lib/active_support/ordered_hash.rb +6 -4
- data/lib/active_support/ordered_options.rb +22 -4
- data/lib/active_support/per_thread_registry.rb +13 -6
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/rails.rb +16 -8
- data/lib/active_support/railtie.rb +43 -9
- data/lib/active_support/reloader.rb +131 -0
- data/lib/active_support/rescuable.rb +108 -53
- data/lib/active_support/security_utils.rb +17 -6
- data/lib/active_support/string_inquirer.rb +11 -3
- data/lib/active_support/subscriber.rb +15 -14
- data/lib/active_support/tagged_logging.rb +14 -11
- data/lib/active_support/test_case.rb +18 -46
- data/lib/active_support/testing/assertions.rb +137 -20
- data/lib/active_support/testing/autorun.rb +4 -2
- data/lib/active_support/testing/constant_lookup.rb +2 -1
- data/lib/active_support/testing/declarative.rb +3 -1
- data/lib/active_support/testing/deprecation.rb +14 -10
- data/lib/active_support/testing/file_fixtures.rb +36 -0
- data/lib/active_support/testing/isolation.rb +34 -25
- data/lib/active_support/testing/method_call_assertions.rb +43 -0
- data/lib/active_support/testing/setup_and_teardown.rb +12 -3
- data/lib/active_support/testing/stream.rb +44 -0
- data/lib/active_support/testing/tagged_logging.rb +3 -1
- data/lib/active_support/testing/time_helpers.rb +96 -27
- data/lib/active_support/time.rb +14 -12
- data/lib/active_support/time_with_zone.rb +195 -53
- data/lib/active_support/values/time_zone.rb +200 -61
- data/lib/active_support/values/unicode_tables.dat +0 -0
- data/lib/active_support/version.rb +3 -1
- data/lib/active_support/xml_mini.rb +69 -51
- data/lib/active_support/xml_mini/jdom.rb +116 -113
- data/lib/active_support/xml_mini/libxml.rb +17 -16
- data/lib/active_support/xml_mini/libxmlsax.rb +16 -18
- data/lib/active_support/xml_mini/nokogiri.rb +15 -15
- data/lib/active_support/xml_mini/nokogirisax.rb +15 -16
- data/lib/active_support/xml_mini/rexml.rb +17 -16
- metadata +55 -43
- data/lib/active_support/concurrency/latch.rb +0 -27
- data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -14
- data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
- data/lib/active_support/core_ext/date_time/zones.rb +0 -6
- data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
- data/lib/active_support/core_ext/module/method_transplanting.rb +0 -11
- data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
- data/lib/active_support/core_ext/object/itself.rb +0 -15
- data/lib/active_support/core_ext/struct.rb +0 -6
- data/lib/active_support/core_ext/thread.rb +0 -86
- data/lib/active_support/core_ext/time/marshal.rb +0 -30
@@ -1,18 +1,19 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "uri"
|
4
4
|
str = "\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E" # Ni-ho-nn-go in UTF-8, means Japanese.
|
5
5
|
parser = URI::Parser.new
|
6
6
|
|
7
7
|
unless str == parser.unescape(parser.escape(str))
|
8
|
+
require "active_support/core_ext/module/redefine_method"
|
8
9
|
URI::Parser.class_eval do
|
9
|
-
|
10
|
+
silence_redefinition_of_method :unescape
|
10
11
|
def unescape(str, escaped = /%[a-fA-F\d]{2}/)
|
11
12
|
# TODO: Are we actually sure that ASCII == UTF-8?
|
12
13
|
# YK: My initial experiments say yes, but let's be sure please
|
13
14
|
enc = str.encoding
|
14
15
|
enc = Encoding::UTF_8 if enc == Encoding::US_ASCII
|
15
|
-
str.gsub(escaped) { [
|
16
|
+
str.gsub(escaped) { |match| [match[1, 2].hex].pack("C") }.force_encoding(enc)
|
16
17
|
end
|
17
18
|
end
|
18
19
|
end
|
@@ -0,0 +1,195 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveSupport
|
4
|
+
# Abstract super class that provides a thread-isolated attributes singleton, which resets automatically
|
5
|
+
# before and after each request. This allows you to keep all the per-request attributes easily
|
6
|
+
# available to the whole system.
|
7
|
+
#
|
8
|
+
# The following full app-like example demonstrates how to use a Current class to
|
9
|
+
# facilitate easy access to the global, per-request attributes without passing them deeply
|
10
|
+
# around everywhere:
|
11
|
+
#
|
12
|
+
# # app/models/current.rb
|
13
|
+
# class Current < ActiveSupport::CurrentAttributes
|
14
|
+
# attribute :account, :user
|
15
|
+
# attribute :request_id, :user_agent, :ip_address
|
16
|
+
#
|
17
|
+
# resets { Time.zone = nil }
|
18
|
+
#
|
19
|
+
# def user=(user)
|
20
|
+
# super
|
21
|
+
# self.account = user.account
|
22
|
+
# Time.zone = user.time_zone
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# # app/controllers/concerns/authentication.rb
|
27
|
+
# module Authentication
|
28
|
+
# extend ActiveSupport::Concern
|
29
|
+
#
|
30
|
+
# included do
|
31
|
+
# before_action :authenticate
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# private
|
35
|
+
# def authenticate
|
36
|
+
# if authenticated_user = User.find_by(id: cookies.encrypted[:user_id])
|
37
|
+
# Current.user = authenticated_user
|
38
|
+
# else
|
39
|
+
# redirect_to new_session_url
|
40
|
+
# end
|
41
|
+
# end
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
# # app/controllers/concerns/set_current_request_details.rb
|
45
|
+
# module SetCurrentRequestDetails
|
46
|
+
# extend ActiveSupport::Concern
|
47
|
+
#
|
48
|
+
# included do
|
49
|
+
# before_action do
|
50
|
+
# Current.request_id = request.uuid
|
51
|
+
# Current.user_agent = request.user_agent
|
52
|
+
# Current.ip_address = request.ip
|
53
|
+
# end
|
54
|
+
# end
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# class ApplicationController < ActionController::Base
|
58
|
+
# include Authentication
|
59
|
+
# include SetCurrentRequestDetails
|
60
|
+
# end
|
61
|
+
#
|
62
|
+
# class MessagesController < ApplicationController
|
63
|
+
# def create
|
64
|
+
# Current.account.messages.create(message_params)
|
65
|
+
# end
|
66
|
+
# end
|
67
|
+
#
|
68
|
+
# class Message < ApplicationRecord
|
69
|
+
# belongs_to :creator, default: -> { Current.user }
|
70
|
+
# after_create { |message| Event.create(record: message) }
|
71
|
+
# end
|
72
|
+
#
|
73
|
+
# class Event < ApplicationRecord
|
74
|
+
# before_create do
|
75
|
+
# self.request_id = Current.request_id
|
76
|
+
# self.user_agent = Current.user_agent
|
77
|
+
# self.ip_address = Current.ip_address
|
78
|
+
# end
|
79
|
+
# end
|
80
|
+
#
|
81
|
+
# A word of caution: It's easy to overdo a global singleton like Current and tangle your model as a result.
|
82
|
+
# Current should only be used for a few, top-level globals, like account, user, and request details.
|
83
|
+
# The attributes stuck in Current should be used by more or less all actions on all requests. If you start
|
84
|
+
# sticking controller-specific attributes in there, you're going to create a mess.
|
85
|
+
class CurrentAttributes
|
86
|
+
include ActiveSupport::Callbacks
|
87
|
+
define_callbacks :reset
|
88
|
+
|
89
|
+
class << self
|
90
|
+
# Returns singleton instance for this class in this thread. If none exists, one is created.
|
91
|
+
def instance
|
92
|
+
current_instances[name] ||= new
|
93
|
+
end
|
94
|
+
|
95
|
+
# Declares one or more attributes that will be given both class and instance accessor methods.
|
96
|
+
def attribute(*names)
|
97
|
+
generated_attribute_methods.module_eval do
|
98
|
+
names.each do |name|
|
99
|
+
define_method(name) do
|
100
|
+
attributes[name.to_sym]
|
101
|
+
end
|
102
|
+
|
103
|
+
define_method("#{name}=") do |attribute|
|
104
|
+
attributes[name.to_sym] = attribute
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
names.each do |name|
|
110
|
+
define_singleton_method(name) do
|
111
|
+
instance.public_send(name)
|
112
|
+
end
|
113
|
+
|
114
|
+
define_singleton_method("#{name}=") do |attribute|
|
115
|
+
instance.public_send("#{name}=", attribute)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# Calls this block after #reset is called on the instance. Used for resetting external collaborators, like Time.zone.
|
121
|
+
def resets(&block)
|
122
|
+
set_callback :reset, :after, &block
|
123
|
+
end
|
124
|
+
|
125
|
+
delegate :set, :reset, to: :instance
|
126
|
+
|
127
|
+
def reset_all # :nodoc:
|
128
|
+
current_instances.each_value(&:reset)
|
129
|
+
end
|
130
|
+
|
131
|
+
def clear_all # :nodoc:
|
132
|
+
reset_all
|
133
|
+
current_instances.clear
|
134
|
+
end
|
135
|
+
|
136
|
+
private
|
137
|
+
def generated_attribute_methods
|
138
|
+
@generated_attribute_methods ||= Module.new.tap { |mod| include mod }
|
139
|
+
end
|
140
|
+
|
141
|
+
def current_instances
|
142
|
+
Thread.current[:current_attributes_instances] ||= {}
|
143
|
+
end
|
144
|
+
|
145
|
+
def method_missing(name, *args, &block)
|
146
|
+
# Caches the method definition as a singleton method of the receiver.
|
147
|
+
#
|
148
|
+
# By letting #delegate handle it, we avoid an enclosure that'll capture args.
|
149
|
+
singleton_class.delegate name, to: :instance
|
150
|
+
|
151
|
+
send(name, *args, &block)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
attr_accessor :attributes
|
156
|
+
|
157
|
+
def initialize
|
158
|
+
@attributes = {}
|
159
|
+
end
|
160
|
+
|
161
|
+
# Expose one or more attributes within a block. Old values are returned after the block concludes.
|
162
|
+
# Example demonstrating the common use of needing to set Current attributes outside the request-cycle:
|
163
|
+
#
|
164
|
+
# class Chat::PublicationJob < ApplicationJob
|
165
|
+
# def perform(attributes, room_number, creator)
|
166
|
+
# Current.set(person: creator) do
|
167
|
+
# Chat::Publisher.publish(attributes: attributes, room_number: room_number)
|
168
|
+
# end
|
169
|
+
# end
|
170
|
+
# end
|
171
|
+
def set(set_attributes)
|
172
|
+
old_attributes = compute_attributes(set_attributes.keys)
|
173
|
+
assign_attributes(set_attributes)
|
174
|
+
yield
|
175
|
+
ensure
|
176
|
+
assign_attributes(old_attributes)
|
177
|
+
end
|
178
|
+
|
179
|
+
# Reset all attributes. Should be called before and after actions, when used as a per-request singleton.
|
180
|
+
def reset
|
181
|
+
run_callbacks :reset do
|
182
|
+
self.attributes = {}
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
private
|
187
|
+
def assign_attributes(new_attributes)
|
188
|
+
new_attributes.each { |key, value| public_send("#{key}=", value) }
|
189
|
+
end
|
190
|
+
|
191
|
+
def compute_attributes(keys)
|
192
|
+
keys.collect { |key| [ key, public_send(key) ] }.to_h
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
@@ -1,73 +1,83 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
11
|
-
require
|
12
|
-
require
|
13
|
-
require
|
14
|
-
require
|
15
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "set"
|
4
|
+
require "thread"
|
5
|
+
require "concurrent/map"
|
6
|
+
require "pathname"
|
7
|
+
require "active_support/core_ext/module/aliasing"
|
8
|
+
require "active_support/core_ext/module/attribute_accessors"
|
9
|
+
require "active_support/core_ext/module/introspection"
|
10
|
+
require "active_support/core_ext/module/anonymous"
|
11
|
+
require "active_support/core_ext/object/blank"
|
12
|
+
require "active_support/core_ext/kernel/reporting"
|
13
|
+
require "active_support/core_ext/load_error"
|
14
|
+
require "active_support/core_ext/name_error"
|
15
|
+
require "active_support/core_ext/string/starts_ends_with"
|
16
|
+
require "active_support/dependencies/interlock"
|
17
|
+
require "active_support/inflector"
|
16
18
|
|
17
19
|
module ActiveSupport #:nodoc:
|
18
20
|
module Dependencies #:nodoc:
|
19
21
|
extend self
|
20
22
|
|
23
|
+
mattr_accessor :interlock, default: Interlock.new
|
24
|
+
|
25
|
+
# :doc:
|
26
|
+
|
27
|
+
# Execute the supplied block without interference from any
|
28
|
+
# concurrent loads.
|
29
|
+
def self.run_interlock
|
30
|
+
Dependencies.interlock.running { yield }
|
31
|
+
end
|
32
|
+
|
33
|
+
# Execute the supplied block while holding an exclusive lock,
|
34
|
+
# preventing any other thread from being inside a #run_interlock
|
35
|
+
# block at the same time.
|
36
|
+
def self.load_interlock
|
37
|
+
Dependencies.interlock.loading { yield }
|
38
|
+
end
|
39
|
+
|
40
|
+
# Execute the supplied block while holding an exclusive lock,
|
41
|
+
# preventing any other thread from being inside a #run_interlock
|
42
|
+
# block at the same time.
|
43
|
+
def self.unload_interlock
|
44
|
+
Dependencies.interlock.unloading { yield }
|
45
|
+
end
|
46
|
+
|
47
|
+
# :nodoc:
|
48
|
+
|
21
49
|
# Should we turn on Ruby warnings on the first load of dependent files?
|
22
|
-
mattr_accessor :warnings_on_first_load
|
23
|
-
self.warnings_on_first_load = false
|
50
|
+
mattr_accessor :warnings_on_first_load, default: false
|
24
51
|
|
25
52
|
# All files ever loaded.
|
26
|
-
mattr_accessor :history
|
27
|
-
self.history = Set.new
|
53
|
+
mattr_accessor :history, default: Set.new
|
28
54
|
|
29
55
|
# All files currently loaded.
|
30
|
-
mattr_accessor :loaded
|
31
|
-
self.loaded = Set.new
|
56
|
+
mattr_accessor :loaded, default: Set.new
|
32
57
|
|
33
58
|
# Stack of files being loaded.
|
34
|
-
mattr_accessor :loading
|
35
|
-
self.loading = []
|
59
|
+
mattr_accessor :loading, default: []
|
36
60
|
|
37
61
|
# Should we load files or require them?
|
38
|
-
mattr_accessor :mechanism
|
39
|
-
self.mechanism = ENV['NO_RELOAD'] ? :require : :load
|
62
|
+
mattr_accessor :mechanism, default: ENV["NO_RELOAD"] ? :require : :load
|
40
63
|
|
41
64
|
# The set of directories from which we may automatically load files. Files
|
42
65
|
# under these directories will be reloaded on each request in development mode,
|
43
66
|
# unless the directory also appears in autoload_once_paths.
|
44
|
-
mattr_accessor :autoload_paths
|
45
|
-
self.autoload_paths = []
|
67
|
+
mattr_accessor :autoload_paths, default: []
|
46
68
|
|
47
69
|
# The set of directories from which automatically loaded constants are loaded
|
48
70
|
# only once. All directories in this set must also be present in +autoload_paths+.
|
49
|
-
mattr_accessor :autoload_once_paths
|
50
|
-
self.autoload_once_paths = []
|
71
|
+
mattr_accessor :autoload_once_paths, default: []
|
51
72
|
|
52
73
|
# An array of qualified constant names that have been loaded. Adding a name
|
53
74
|
# to this array will cause it to be unloaded the next time Dependencies are
|
54
75
|
# cleared.
|
55
|
-
mattr_accessor :autoloaded_constants
|
56
|
-
self.autoloaded_constants = []
|
76
|
+
mattr_accessor :autoloaded_constants, default: []
|
57
77
|
|
58
78
|
# An array of constant names that need to be unloaded on every request. Used
|
59
79
|
# to allow arbitrary constants to be marked for unloading.
|
60
|
-
mattr_accessor :explicitly_unloadable_constants
|
61
|
-
self.explicitly_unloadable_constants = []
|
62
|
-
|
63
|
-
# The logger is used for generating information on the action run-time
|
64
|
-
# (including benchmarking) if available. Can be set to nil for no logging.
|
65
|
-
# Compatible with both Ruby's own Logger and Log4r loggers.
|
66
|
-
mattr_accessor :logger
|
67
|
-
|
68
|
-
# Set to +true+ to enable logging of const_missing and file loads.
|
69
|
-
mattr_accessor :log_activity
|
70
|
-
self.log_activity = false
|
80
|
+
mattr_accessor :explicitly_unloadable_constants, default: []
|
71
81
|
|
72
82
|
# The WatchStack keeps a stack of the modules being watched as files are
|
73
83
|
# loaded. If a file in the process of being loaded (parent.rb) triggers the
|
@@ -75,7 +85,7 @@ module ActiveSupport #:nodoc:
|
|
75
85
|
# handles the new constants.
|
76
86
|
#
|
77
87
|
# If child.rb is being autoloaded, its constants will be added to
|
78
|
-
# autoloaded_constants. If it was being
|
88
|
+
# autoloaded_constants. If it was being required, they will be discarded.
|
79
89
|
#
|
80
90
|
# This is handled by walking back up the watch stack and adding the constants
|
81
91
|
# found by child.rb to the list of original constants in parent.rb.
|
@@ -89,7 +99,7 @@ module ActiveSupport #:nodoc:
|
|
89
99
|
|
90
100
|
def initialize
|
91
101
|
@watching = []
|
92
|
-
@stack = Hash.new { |h,k| h[k] = [] }
|
102
|
+
@stack = Hash.new { |h, k| h[k] = [] }
|
93
103
|
end
|
94
104
|
|
95
105
|
def each(&block)
|
@@ -115,11 +125,11 @@ module ActiveSupport #:nodoc:
|
|
115
125
|
next unless mod.is_a?(Module)
|
116
126
|
|
117
127
|
# Get a list of the constants that were added
|
118
|
-
new_constants = mod.
|
128
|
+
new_constants = mod.constants(false) - original_constants
|
119
129
|
|
120
|
-
#
|
130
|
+
# @stack[namespace] returns an Array of the constants that are being evaluated
|
121
131
|
# for that namespace. For instance, if parent.rb requires child.rb, the first
|
122
|
-
# element of
|
132
|
+
# element of @stack[Object] will be an Array of the constants that were present
|
123
133
|
# before parent.rb was required. The second element will be an Array of the
|
124
134
|
# constants that were present before child.rb was required.
|
125
135
|
@stack[namespace].each do |namespace_constants|
|
@@ -128,7 +138,7 @@ module ActiveSupport #:nodoc:
|
|
128
138
|
|
129
139
|
# Normalize the list of new constants, and add them to the list we will return
|
130
140
|
new_constants.each do |suffix|
|
131
|
-
constants << ([namespace, suffix] - ["Object"]).join("::")
|
141
|
+
constants << ([namespace, suffix] - ["Object"]).join("::".freeze)
|
132
142
|
end
|
133
143
|
end
|
134
144
|
constants
|
@@ -143,7 +153,7 @@ module ActiveSupport #:nodoc:
|
|
143
153
|
@watching << namespaces.map do |namespace|
|
144
154
|
module_name = Dependencies.to_constant_name(namespace)
|
145
155
|
original_constants = Dependencies.qualified_const_defined?(module_name) ?
|
146
|
-
Inflector.constantize(module_name).
|
156
|
+
Inflector.constantize(module_name).constants(false) : []
|
147
157
|
|
148
158
|
@stack[module_name] << original_constants
|
149
159
|
module_name
|
@@ -151,14 +161,13 @@ module ActiveSupport #:nodoc:
|
|
151
161
|
end
|
152
162
|
|
153
163
|
private
|
154
|
-
|
155
|
-
|
156
|
-
|
164
|
+
def pop_modules(modules)
|
165
|
+
modules.each { |mod| @stack[mod].pop }
|
166
|
+
end
|
157
167
|
end
|
158
168
|
|
159
169
|
# An internal stack used to record which constants are loaded by any block.
|
160
|
-
mattr_accessor :constant_watch_stack
|
161
|
-
self.constant_watch_stack = WatchStack.new
|
170
|
+
mattr_accessor :constant_watch_stack, default: WatchStack.new
|
162
171
|
|
163
172
|
# Module includes this module.
|
164
173
|
module ModuleConstMissing #:nodoc:
|
@@ -224,7 +233,7 @@ module ActiveSupport #:nodoc:
|
|
224
233
|
# resolution deterministic for constants with the same relative name in
|
225
234
|
# different namespaces whose evaluation would depend on load order
|
226
235
|
# otherwise.
|
227
|
-
def require_dependency(file_name, message = "No such file to load -- %s")
|
236
|
+
def require_dependency(file_name, message = "No such file to load -- %s.rb")
|
228
237
|
file_name = file_name.to_path if file_name.respond_to?(:to_path)
|
229
238
|
unless file_name.is_a?(String)
|
230
239
|
raise ArgumentError, "the file name must either be a String or implement #to_path -- you passed #{file_name.inspect}"
|
@@ -234,7 +243,7 @@ module ActiveSupport #:nodoc:
|
|
234
243
|
end
|
235
244
|
|
236
245
|
def load_dependency(file)
|
237
|
-
if Dependencies.load? &&
|
246
|
+
if Dependencies.load? && Dependencies.constant_watch_stack.watching?
|
238
247
|
Dependencies.new_constants_in(Object) { yield }
|
239
248
|
else
|
240
249
|
yield
|
@@ -263,17 +272,17 @@ module ActiveSupport #:nodoc:
|
|
263
272
|
|
264
273
|
private
|
265
274
|
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
275
|
+
def load(file, wrap = false)
|
276
|
+
result = false
|
277
|
+
load_dependency(file) { result = super }
|
278
|
+
result
|
279
|
+
end
|
271
280
|
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
281
|
+
def require(file)
|
282
|
+
result = false
|
283
|
+
load_dependency(file) { result = super }
|
284
|
+
result
|
285
|
+
end
|
277
286
|
end
|
278
287
|
|
279
288
|
# Exception file-blaming.
|
@@ -324,56 +333,58 @@ module ActiveSupport #:nodoc:
|
|
324
333
|
end
|
325
334
|
|
326
335
|
def clear
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
336
|
+
Dependencies.unload_interlock do
|
337
|
+
loaded.clear
|
338
|
+
loading.clear
|
339
|
+
remove_unloadable_constants!
|
340
|
+
end
|
331
341
|
end
|
332
342
|
|
333
343
|
def require_or_load(file_name, const_path = nil)
|
334
|
-
log_call file_name, const_path
|
335
344
|
file_name = $` if file_name =~ /\.rb\z/
|
336
345
|
expanded = File.expand_path(file_name)
|
337
346
|
return if loaded.include?(expanded)
|
338
347
|
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
loading << expanded
|
343
|
-
|
344
|
-
begin
|
345
|
-
if load?
|
346
|
-
log "loading #{file_name}"
|
348
|
+
Dependencies.load_interlock do
|
349
|
+
# Maybe it got loaded while we were waiting for our lock:
|
350
|
+
return if loaded.include?(expanded)
|
347
351
|
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
+
# Record that we've seen this file *before* loading it to avoid an
|
353
|
+
# infinite loop with mutual dependencies.
|
354
|
+
loaded << expanded
|
355
|
+
loading << expanded
|
352
356
|
|
353
|
-
|
354
|
-
|
357
|
+
begin
|
358
|
+
if load?
|
359
|
+
# Enable warnings if this file has not been loaded before and
|
360
|
+
# warnings_on_first_load is set.
|
361
|
+
load_args = ["#{file_name}.rb"]
|
362
|
+
load_args << const_path unless const_path.nil?
|
363
|
+
|
364
|
+
if !warnings_on_first_load || history.include?(expanded)
|
365
|
+
result = load_file(*load_args)
|
366
|
+
else
|
367
|
+
enable_warnings { result = load_file(*load_args) }
|
368
|
+
end
|
355
369
|
else
|
356
|
-
|
370
|
+
result = require file_name
|
357
371
|
end
|
358
|
-
|
359
|
-
|
360
|
-
|
372
|
+
rescue Exception
|
373
|
+
loaded.delete expanded
|
374
|
+
raise
|
375
|
+
ensure
|
376
|
+
loading.pop
|
361
377
|
end
|
362
|
-
rescue Exception
|
363
|
-
loaded.delete expanded
|
364
|
-
raise
|
365
|
-
ensure
|
366
|
-
loading.pop
|
367
|
-
end
|
368
378
|
|
369
|
-
|
370
|
-
|
371
|
-
|
379
|
+
# Record history *after* loading so first load gets warnings.
|
380
|
+
history << expanded
|
381
|
+
result
|
382
|
+
end
|
372
383
|
end
|
373
384
|
|
374
385
|
# Is the provided constant path defined?
|
375
386
|
def qualified_const_defined?(path)
|
376
|
-
Object.
|
387
|
+
Object.const_defined?(path, false)
|
377
388
|
end
|
378
389
|
|
379
390
|
# Given +path+, a filesystem path to a ruby file, return an array of
|
@@ -386,13 +397,13 @@ module ActiveSupport #:nodoc:
|
|
386
397
|
|
387
398
|
bases.each do |root|
|
388
399
|
expanded_root = File.expand_path(root)
|
389
|
-
next unless
|
400
|
+
next unless expanded_path.start_with?(expanded_root)
|
390
401
|
|
391
|
-
|
392
|
-
|
393
|
-
next if nesting.blank?
|
402
|
+
root_size = expanded_root.size
|
403
|
+
next if expanded_path[root_size] != ?/.freeze
|
394
404
|
|
395
|
-
|
405
|
+
nesting = expanded_path[(root_size + 1)..-1]
|
406
|
+
paths << nesting.camelize unless nesting.blank?
|
396
407
|
end
|
397
408
|
|
398
409
|
paths.uniq!
|
@@ -401,7 +412,7 @@ module ActiveSupport #:nodoc:
|
|
401
412
|
|
402
413
|
# Search for a file in autoload_paths matching the provided suffix.
|
403
414
|
def search_for_file(path_suffix)
|
404
|
-
path_suffix = path_suffix.sub(/(\.rb)?$/, ".rb")
|
415
|
+
path_suffix = path_suffix.sub(/(\.rb)?$/, ".rb".freeze)
|
405
416
|
|
406
417
|
autoload_paths.each do |root|
|
407
418
|
path = File.join(root, path_suffix)
|
@@ -421,7 +432,7 @@ module ActiveSupport #:nodoc:
|
|
421
432
|
end
|
422
433
|
|
423
434
|
def load_once_path?(path)
|
424
|
-
# to_s works around a
|
435
|
+
# to_s works around a ruby issue where String#starts_with?(Pathname)
|
425
436
|
# will raise a TypeError: no implicit conversion of Pathname into String
|
426
437
|
autoload_once_paths.any? { |base| path.starts_with? base.to_s }
|
427
438
|
end
|
@@ -436,6 +447,7 @@ module ActiveSupport #:nodoc:
|
|
436
447
|
mod = Module.new
|
437
448
|
into.const_set const_name, mod
|
438
449
|
autoloaded_constants << qualified_name unless autoload_once_paths.include?(base_path)
|
450
|
+
autoloaded_constants.uniq!
|
439
451
|
mod
|
440
452
|
end
|
441
453
|
|
@@ -448,7 +460,6 @@ module ActiveSupport #:nodoc:
|
|
448
460
|
# set of names that the file at +path+ may define. See
|
449
461
|
# +loadable_constants_for_path+ for more details.
|
450
462
|
def load_file(path, const_paths = loadable_constants_for_path(path))
|
451
|
-
log_call path, const_paths
|
452
463
|
const_paths = [const_paths].compact unless const_paths.is_a? Array
|
453
464
|
parent_paths = const_paths.collect { |const_path| const_path[/.*(?=::)/] || ::Object }
|
454
465
|
|
@@ -459,7 +470,6 @@ module ActiveSupport #:nodoc:
|
|
459
470
|
|
460
471
|
autoloaded_constants.concat newly_defined_paths unless load_once_path?(path)
|
461
472
|
autoloaded_constants.uniq!
|
462
|
-
log "loading #{path} defined #{newly_defined_paths * ', '}" unless newly_defined_paths.empty?
|
463
473
|
result
|
464
474
|
end
|
465
475
|
|
@@ -473,8 +483,6 @@ module ActiveSupport #:nodoc:
|
|
473
483
|
# it is not possible to load the constant into from_mod, try its parent
|
474
484
|
# module using +const_missing+.
|
475
485
|
def load_missing_constant(from_mod, const_name)
|
476
|
-
log_call from_mod, const_name
|
477
|
-
|
478
486
|
unless qualified_const_defined?(from_mod.name) && Inflector.constantize(from_mod.name).equal?(from_mod)
|
479
487
|
raise ArgumentError, "A copy of #{from_mod} has been removed from the module tree but is still active!"
|
480
488
|
end
|
@@ -486,7 +494,7 @@ module ActiveSupport #:nodoc:
|
|
486
494
|
|
487
495
|
if file_path
|
488
496
|
expanded = File.expand_path(file_path)
|
489
|
-
expanded.sub!(/\.rb\z/,
|
497
|
+
expanded.sub!(/\.rb\z/, "".freeze)
|
490
498
|
|
491
499
|
if loading.include?(expanded)
|
492
500
|
raise "Circular dependency detected while autoloading constant #{qualified_name}"
|
@@ -530,7 +538,7 @@ module ActiveSupport #:nodoc:
|
|
530
538
|
end
|
531
539
|
|
532
540
|
name_error = NameError.new("uninitialized constant #{qualified_name}", const_name)
|
533
|
-
name_error.set_backtrace(caller.reject {|l| l.starts_with? __FILE__ })
|
541
|
+
name_error.set_backtrace(caller.reject { |l| l.starts_with? __FILE__ })
|
534
542
|
raise name_error
|
535
543
|
end
|
536
544
|
|
@@ -550,7 +558,7 @@ module ActiveSupport #:nodoc:
|
|
550
558
|
|
551
559
|
class ClassCache
|
552
560
|
def initialize
|
553
|
-
@store =
|
561
|
+
@store = Concurrent::Map.new
|
554
562
|
end
|
555
563
|
|
556
564
|
def empty?
|
@@ -574,7 +582,7 @@ module ActiveSupport #:nodoc:
|
|
574
582
|
|
575
583
|
def store(klass)
|
576
584
|
return self unless klass.respond_to?(:name)
|
577
|
-
raise(ArgumentError,
|
585
|
+
raise(ArgumentError, "anonymous classes cannot be cached") if klass.name.empty?
|
578
586
|
@store[klass.name] = klass
|
579
587
|
self
|
580
588
|
end
|
@@ -607,8 +615,8 @@ module ActiveSupport #:nodoc:
|
|
607
615
|
def autoloaded?(desc)
|
608
616
|
return false if desc.is_a?(Module) && desc.anonymous?
|
609
617
|
name = to_constant_name desc
|
610
|
-
return false unless qualified_const_defined?
|
611
|
-
|
618
|
+
return false unless qualified_const_defined?(name)
|
619
|
+
autoloaded_constants.include?(name)
|
612
620
|
end
|
613
621
|
|
614
622
|
# Will the provided constant descriptor be unloaded?
|
@@ -638,54 +646,49 @@ module ActiveSupport #:nodoc:
|
|
638
646
|
# exception, any new constants are regarded as being only partially defined
|
639
647
|
# and will be removed immediately.
|
640
648
|
def new_constants_in(*descs)
|
641
|
-
log_call(*descs)
|
642
|
-
|
643
649
|
constant_watch_stack.watch_namespaces(descs)
|
644
|
-
|
650
|
+
success = false
|
645
651
|
|
646
652
|
begin
|
647
653
|
yield # Now yield to the code that is to define new constants.
|
648
|
-
|
654
|
+
success = true
|
649
655
|
ensure
|
650
656
|
new_constants = constant_watch_stack.new_constants
|
651
657
|
|
652
|
-
|
653
|
-
return new_constants unless aborting
|
658
|
+
return new_constants if success
|
654
659
|
|
655
|
-
|
656
|
-
new_constants.each { |c| remove_constant(c) }
|
660
|
+
# Remove partially loaded constants.
|
661
|
+
new_constants.each { |c| remove_constant(c) }
|
657
662
|
end
|
658
|
-
|
659
|
-
[]
|
660
663
|
end
|
661
664
|
|
662
665
|
# Convert the provided const desc to a qualified constant name (as a string).
|
663
666
|
# A module, class, symbol, or string may be provided.
|
664
667
|
def to_constant_name(desc) #:nodoc:
|
665
668
|
case desc
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
669
|
+
when String then desc.sub(/^::/, "")
|
670
|
+
when Symbol then desc.to_s
|
671
|
+
when Module
|
672
|
+
desc.name ||
|
673
|
+
raise(ArgumentError, "Anonymous modules have no name to be referenced by")
|
674
|
+
else raise TypeError, "Not a valid constant descriptor: #{desc.inspect}"
|
672
675
|
end
|
673
676
|
end
|
674
677
|
|
675
678
|
def remove_constant(const) #:nodoc:
|
676
679
|
# Normalize ::Foo, ::Object::Foo, Object::Foo, Object::Object::Foo, etc. as Foo.
|
677
|
-
normalized = const.to_s.sub(/\A::/,
|
678
|
-
normalized.sub!(/\A(Object::)+/,
|
680
|
+
normalized = const.to_s.sub(/\A::/, "")
|
681
|
+
normalized.sub!(/\A(Object::)+/, "")
|
679
682
|
|
680
|
-
constants = normalized.split(
|
683
|
+
constants = normalized.split("::")
|
681
684
|
to_remove = constants.pop
|
682
685
|
|
683
686
|
# Remove the file path from the loaded list.
|
684
687
|
file_path = search_for_file(const.underscore)
|
685
688
|
if file_path
|
686
689
|
expanded = File.expand_path(file_path)
|
687
|
-
expanded.sub!(/\.rb\z/,
|
688
|
-
|
690
|
+
expanded.sub!(/\.rb\z/, "")
|
691
|
+
loaded.delete(expanded)
|
689
692
|
end
|
690
693
|
|
691
694
|
if constants.empty?
|
@@ -698,13 +701,11 @@ module ActiveSupport #:nodoc:
|
|
698
701
|
# here than require the caller to be clever. We check the parent
|
699
702
|
# rather than the very const argument because we do not want to
|
700
703
|
# trigger Kernel#autoloads, see the comment below.
|
701
|
-
parent_name = constants.join(
|
704
|
+
parent_name = constants.join("::")
|
702
705
|
return unless qualified_const_defined?(parent_name)
|
703
706
|
parent = constantize(parent_name)
|
704
707
|
end
|
705
708
|
|
706
|
-
log "removing constant #{const}"
|
707
|
-
|
708
709
|
# In an autoloaded user.rb like this
|
709
710
|
#
|
710
711
|
# autoload :Foo, 'foo'
|
@@ -725,7 +726,7 @@ module ActiveSupport #:nodoc:
|
|
725
726
|
begin
|
726
727
|
constantized = parent.const_get(to_remove, false)
|
727
728
|
rescue NameError
|
728
|
-
|
729
|
+
# The constant is no longer reachable, just skip it.
|
729
730
|
return
|
730
731
|
else
|
731
732
|
constantized.before_remove_const if constantized.respond_to?(:before_remove_const)
|
@@ -735,27 +736,9 @@ module ActiveSupport #:nodoc:
|
|
735
736
|
begin
|
736
737
|
parent.instance_eval { remove_const to_remove }
|
737
738
|
rescue NameError
|
738
|
-
|
739
|
+
# The constant is no longer reachable, just skip it.
|
739
740
|
end
|
740
741
|
end
|
741
|
-
|
742
|
-
protected
|
743
|
-
def log_call(*args)
|
744
|
-
if log_activity?
|
745
|
-
arg_str = args.collect { |arg| arg.inspect } * ', '
|
746
|
-
/in `([a-z_\?\!]+)'/ =~ caller(1).first
|
747
|
-
selector = $1 || '<unknown>'
|
748
|
-
log "called #{selector}(#{arg_str})"
|
749
|
-
end
|
750
|
-
end
|
751
|
-
|
752
|
-
def log(msg)
|
753
|
-
logger.debug "Dependencies: #{msg}" if log_activity?
|
754
|
-
end
|
755
|
-
|
756
|
-
def log_activity?
|
757
|
-
logger && log_activity
|
758
|
-
end
|
759
742
|
end
|
760
743
|
end
|
761
744
|
|