activesupport 5.2.3.rc1 → 6.0.0.beta1
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 +183 -469
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/lib/active_support.rb +1 -1
- data/lib/active_support/backtrace_cleaner.rb +23 -0
- data/lib/active_support/cache.rb +40 -18
- data/lib/active_support/cache/file_store.rb +19 -12
- data/lib/active_support/cache/mem_cache_store.rb +5 -0
- data/lib/active_support/cache/memory_store.rb +5 -0
- data/lib/active_support/cache/null_store.rb +5 -0
- data/lib/active_support/cache/redis_cache_store.rb +28 -4
- data/lib/active_support/callbacks.rb +16 -5
- data/lib/active_support/configurable.rb +4 -8
- data/lib/active_support/core_ext/array.rb +1 -1
- data/lib/active_support/core_ext/array/extract.rb +21 -0
- data/lib/active_support/core_ext/array/prepend_and_append.rb +2 -6
- data/lib/active_support/core_ext/class/attribute.rb +1 -1
- data/lib/active_support/core_ext/class/subclasses.rb +1 -1
- data/lib/active_support/core_ext/date/calculations.rb +6 -5
- data/lib/active_support/core_ext/date_and_time/calculations.rb +24 -17
- data/lib/active_support/core_ext/date_time/calculations.rb +1 -1
- data/lib/active_support/core_ext/enumerable.rb +71 -67
- data/lib/active_support/core_ext/hash.rb +0 -2
- data/lib/active_support/core_ext/hash/compact.rb +2 -26
- data/lib/active_support/core_ext/hash/keys.rb +0 -29
- data/lib/active_support/core_ext/hash/slice.rb +3 -25
- data/lib/active_support/core_ext/hash/transform_values.rb +2 -29
- data/lib/active_support/core_ext/integer/multiple.rb +1 -1
- data/lib/active_support/core_ext/load_error.rb +1 -1
- data/lib/active_support/core_ext/module.rb +0 -1
- data/lib/active_support/core_ext/module/attribute_accessors.rb +2 -5
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +8 -14
- data/lib/active_support/core_ext/module/delegation.rb +27 -7
- data/lib/active_support/core_ext/module/introspection.rb +37 -13
- data/lib/active_support/core_ext/module/reachable.rb +1 -6
- data/lib/active_support/core_ext/module/redefine_method.rb +8 -17
- data/lib/active_support/core_ext/numeric.rb +0 -1
- data/lib/active_support/core_ext/numeric/conversions.rb +124 -128
- data/lib/active_support/core_ext/numeric/inquiry.rb +2 -25
- data/lib/active_support/core_ext/object/blank.rb +1 -2
- data/lib/active_support/core_ext/object/duplicable.rb +5 -2
- data/lib/active_support/core_ext/object/json.rb +1 -0
- data/lib/active_support/core_ext/object/try.rb +15 -7
- data/lib/active_support/core_ext/object/with_options.rb +1 -1
- data/lib/active_support/core_ext/range/compare_range.rb +1 -1
- data/lib/active_support/core_ext/range/conversions.rb +31 -29
- data/lib/active_support/core_ext/range/include_range.rb +6 -0
- data/lib/active_support/core_ext/regexp.rb +0 -4
- data/lib/active_support/core_ext/securerandom.rb +23 -3
- data/lib/active_support/core_ext/string/access.rb +8 -0
- data/lib/active_support/core_ext/string/filters.rb +41 -0
- data/lib/active_support/core_ext/string/multibyte.rb +4 -3
- data/lib/active_support/core_ext/string/output_safety.rb +16 -5
- data/lib/active_support/core_ext/string/strip.rb +3 -1
- data/lib/active_support/core_ext/uri.rb +1 -0
- data/lib/active_support/current_attributes.rb +2 -0
- data/lib/active_support/dependencies.rb +28 -11
- data/lib/active_support/deprecation.rb +1 -1
- data/lib/active_support/deprecation/behaviors.rb +1 -1
- data/lib/active_support/deprecation/method_wrappers.rb +4 -5
- data/lib/active_support/deprecation/proxy_wrappers.rb +0 -2
- data/lib/active_support/descendants_tracker.rb +6 -5
- data/lib/active_support/duration.rb +4 -2
- data/lib/active_support/duration/iso8601_parser.rb +2 -3
- data/lib/active_support/duration/iso8601_serializer.rb +3 -4
- data/lib/active_support/encrypted_configuration.rb +0 -4
- data/lib/active_support/evented_file_update_checker.rb +25 -7
- data/lib/active_support/execution_wrapper.rb +1 -0
- data/lib/active_support/gem_version.rb +4 -4
- data/lib/active_support/hash_with_indifferent_access.rb +16 -28
- data/lib/active_support/i18n.rb +1 -0
- data/lib/active_support/i18n_railtie.rb +8 -1
- data/lib/active_support/inflector/inflections.rb +1 -4
- data/lib/active_support/inflector/methods.rb +15 -27
- data/lib/active_support/inflector/transliterate.rb +6 -6
- data/lib/active_support/json/decoding.rb +23 -23
- data/lib/active_support/json/encoding.rb +6 -2
- data/lib/active_support/key_generator.rb +0 -32
- data/lib/active_support/lazy_load_hooks.rb +5 -1
- data/lib/active_support/locale/en.rb +31 -0
- data/lib/active_support/log_subscriber.rb +31 -8
- data/lib/active_support/logger.rb +0 -15
- data/lib/active_support/logger_silence.rb +28 -12
- data/lib/active_support/logger_thread_safe_level.rb +26 -4
- data/lib/active_support/message_encryptor.rb +2 -4
- data/lib/active_support/message_verifier.rb +2 -2
- data/lib/active_support/multibyte/chars.rb +29 -48
- data/lib/active_support/multibyte/unicode.rb +44 -281
- data/lib/active_support/notifications.rb +32 -4
- data/lib/active_support/notifications/fanout.rb +40 -2
- data/lib/active_support/notifications/instrumenter.rb +73 -2
- data/lib/active_support/number_helper.rb +7 -0
- data/lib/active_support/number_helper/number_to_currency_converter.rb +2 -2
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +3 -1
- data/lib/active_support/number_helper/number_to_human_converter.rb +3 -1
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +3 -1
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +2 -0
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +5 -3
- data/lib/active_support/parameter_filter.rb +124 -0
- data/lib/active_support/rails.rb +0 -6
- data/lib/active_support/reloader.rb +4 -5
- data/lib/active_support/subscriber.rb +16 -26
- data/lib/active_support/tagged_logging.rb +13 -4
- data/lib/active_support/test_case.rb +91 -0
- data/lib/active_support/testing/assertions.rb +15 -1
- data/lib/active_support/testing/deprecation.rb +0 -1
- data/lib/active_support/testing/file_fixtures.rb +2 -0
- data/lib/active_support/testing/isolation.rb +2 -2
- data/lib/active_support/testing/method_call_assertions.rb +28 -1
- data/lib/active_support/testing/parallelization.rb +109 -0
- data/lib/active_support/testing/stream.rb +1 -1
- data/lib/active_support/testing/time_helpers.rb +7 -7
- data/lib/active_support/time_with_zone.rb +15 -5
- data/lib/active_support/values/time_zone.rb +12 -7
- data/lib/active_support/xml_mini.rb +2 -9
- data/lib/active_support/xml_mini/jdom.rb +2 -2
- data/lib/active_support/xml_mini/libxml.rb +2 -2
- data/lib/active_support/xml_mini/libxmlsax.rb +4 -4
- data/lib/active_support/xml_mini/nokogiri.rb +2 -2
- data/lib/active_support/xml_mini/nokogirisax.rb +3 -3
- data/lib/active_support/xml_mini/rexml.rb +2 -2
- metadata +9 -6
- data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,28 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
class Numeric
|
5
|
-
# Returns true if the number is positive.
|
6
|
-
#
|
7
|
-
# 1.positive? # => true
|
8
|
-
# 0.positive? # => false
|
9
|
-
# -1.positive? # => false
|
10
|
-
def positive?
|
11
|
-
self > 0
|
12
|
-
end
|
3
|
+
require "active_support/deprecation"
|
13
4
|
|
14
|
-
|
15
|
-
#
|
16
|
-
# -1.negative? # => true
|
17
|
-
# 0.negative? # => false
|
18
|
-
# 1.negative? # => false
|
19
|
-
def negative?
|
20
|
-
self < 0
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
class Complex
|
25
|
-
undef :positive?
|
26
|
-
undef :negative?
|
27
|
-
end
|
28
|
-
end
|
5
|
+
ActiveSupport::Deprecation.warn "Ruby 2.5+ (required by Rails 6) provides Numeric#positive? and Numeric#negative? natively, so requiring active_support/core_ext/numeric/inquiry is no longer necessary. Requiring it will raise LoadError in Rails 6.1."
|
@@ -1,11 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "active_support/core_ext/regexp"
|
4
3
|
require "concurrent/map"
|
5
4
|
|
6
5
|
class Object
|
7
6
|
# An object is blank if it's false, empty, or a whitespace string.
|
8
|
-
# For example, +
|
7
|
+
# For example, +nil+, '', ' ', [], {}, and +false+ are all blank.
|
9
8
|
#
|
10
9
|
# This simplifies
|
11
10
|
#
|
@@ -75,8 +75,11 @@ end
|
|
75
75
|
|
76
76
|
class Symbol
|
77
77
|
begin
|
78
|
-
:symbol.dup
|
79
|
-
|
78
|
+
:symbol.dup
|
79
|
+
|
80
|
+
# Some symbols couldn't be duped in Ruby 2.4.0 only, due to a bug.
|
81
|
+
# This feature check catches any regression.
|
82
|
+
"symbol_from_string".to_sym.dup
|
80
83
|
rescue TypeError
|
81
84
|
|
82
85
|
# Symbols are not duplicable:
|
@@ -14,6 +14,7 @@ require "active_support/core_ext/time/conversions"
|
|
14
14
|
require "active_support/core_ext/date_time/conversions"
|
15
15
|
require "active_support/core_ext/date/conversions"
|
16
16
|
|
17
|
+
#--
|
17
18
|
# The JSON gem adds a few modules to Ruby core classes containing :to_json definition, overwriting
|
18
19
|
# their default behavior. That said, we need to define the basic to_json method in all of them,
|
19
20
|
# otherwise they will always use to_json gem implementation, which is backwards incompatible in
|
@@ -4,19 +4,27 @@ require "delegate"
|
|
4
4
|
|
5
5
|
module ActiveSupport
|
6
6
|
module Tryable #:nodoc:
|
7
|
-
def try(*
|
8
|
-
|
7
|
+
def try(method_name = nil, *args, &b)
|
8
|
+
if method_name.nil? && block_given?
|
9
|
+
if b.arity == 0
|
10
|
+
instance_eval(&b)
|
11
|
+
else
|
12
|
+
yield self
|
13
|
+
end
|
14
|
+
elsif respond_to?(method_name)
|
15
|
+
public_send(method_name, *args, &b)
|
16
|
+
end
|
9
17
|
end
|
10
18
|
|
11
|
-
def try!(*
|
12
|
-
if
|
19
|
+
def try!(method_name = nil, *args, &b)
|
20
|
+
if method_name.nil? && block_given?
|
13
21
|
if b.arity == 0
|
14
22
|
instance_eval(&b)
|
15
23
|
else
|
16
24
|
yield self
|
17
25
|
end
|
18
26
|
else
|
19
|
-
public_send(*
|
27
|
+
public_send(method_name, *args, &b)
|
20
28
|
end
|
21
29
|
end
|
22
30
|
end
|
@@ -135,14 +143,14 @@ class NilClass
|
|
135
143
|
#
|
136
144
|
# With +try+
|
137
145
|
# @person.try(:children).try(:first).try(:name)
|
138
|
-
def try(*args)
|
146
|
+
def try(method_name = nil, *args)
|
139
147
|
nil
|
140
148
|
end
|
141
149
|
|
142
150
|
# Calling +try!+ on +nil+ always returns +nil+.
|
143
151
|
#
|
144
152
|
# nil.try!(:name) # => nil
|
145
|
-
def try!(*args)
|
153
|
+
def try!(method_name = nil, *args)
|
146
154
|
nil
|
147
155
|
end
|
148
156
|
end
|
@@ -68,7 +68,7 @@ class Object
|
|
68
68
|
# You can access these methods using the class name instead:
|
69
69
|
#
|
70
70
|
# class Phone < ActiveRecord::Base
|
71
|
-
# enum phone_number_type:
|
71
|
+
# enum phone_number_type: { home: 0, office: 1, mobile: 2 }
|
72
72
|
#
|
73
73
|
# with_options presence: true do
|
74
74
|
# validates :phone_number_type, inclusion: { in: Phone.phone_number_types.keys }
|
@@ -1,39 +1,41 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module ActiveSupport
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
module ActiveSupport
|
4
|
+
module RangeWithFormat
|
5
|
+
RANGE_FORMATS = {
|
6
|
+
db: -> (start, stop) do
|
7
|
+
case start
|
8
|
+
when String then "BETWEEN '#{start}' AND '#{stop}'"
|
9
|
+
else
|
10
|
+
"BETWEEN '#{start.to_s(:db)}' AND '#{stop.to_s(:db)}'"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
}
|
14
|
+
|
15
|
+
# Convert range to a formatted string. See RANGE_FORMATS for predefined formats.
|
16
|
+
#
|
17
|
+
# range = (1..100) # => 1..100
|
18
|
+
#
|
19
|
+
# range.to_s # => "1..100"
|
20
|
+
# range.to_s(:db) # => "BETWEEN '1' AND '100'"
|
21
|
+
#
|
22
|
+
# == Adding your own range formats to to_s
|
23
|
+
# You can add your own formats to the Range::RANGE_FORMATS hash.
|
24
|
+
# Use the format name as the hash key and a Proc instance.
|
25
|
+
#
|
26
|
+
# # config/initializers/range_formats.rb
|
27
|
+
# Range::RANGE_FORMATS[:short] = ->(start, stop) { "Between #{start.to_s(:db)} and #{stop.to_s(:db)}" }
|
28
|
+
def to_s(format = :default)
|
29
|
+
if formatter = RANGE_FORMATS[format]
|
30
|
+
formatter.call(first, last)
|
8
31
|
else
|
9
|
-
|
32
|
+
super()
|
10
33
|
end
|
11
34
|
end
|
12
|
-
}
|
13
35
|
|
14
|
-
|
15
|
-
|
16
|
-
# range = (1..100) # => 1..100
|
17
|
-
#
|
18
|
-
# range.to_s # => "1..100"
|
19
|
-
# range.to_s(:db) # => "BETWEEN '1' AND '100'"
|
20
|
-
#
|
21
|
-
# == Adding your own range formats to to_s
|
22
|
-
# You can add your own formats to the Range::RANGE_FORMATS hash.
|
23
|
-
# Use the format name as the hash key and a Proc instance.
|
24
|
-
#
|
25
|
-
# # config/initializers/range_formats.rb
|
26
|
-
# Range::RANGE_FORMATS[:short] = ->(start, stop) { "Between #{start.to_s(:db)} and #{stop.to_s(:db)}" }
|
27
|
-
def to_s(format = :default)
|
28
|
-
if formatter = RANGE_FORMATS[format]
|
29
|
-
formatter.call(first, last)
|
30
|
-
else
|
31
|
-
super()
|
32
|
-
end
|
36
|
+
alias_method :to_default_s, :to_s
|
37
|
+
alias_method :to_formatted_s, :to_s
|
33
38
|
end
|
34
|
-
|
35
|
-
alias_method :to_default_s, :to_s
|
36
|
-
alias_method :to_formatted_s, :to_s
|
37
39
|
end
|
38
40
|
|
39
41
|
Range.prepend(ActiveSupport::RangeWithFormat)
|
@@ -1,3 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/deprecation"
|
4
|
+
|
5
|
+
ActiveSupport::Deprecation.warn "You have required `active_support/core_ext/range/include_range`. " \
|
6
|
+
"This file will be removed in Rails 6.1. You should require `active_support/core_ext/range/compare_range` " \
|
7
|
+
"instead."
|
8
|
+
|
3
9
|
require "active_support/core_ext/range/compare_range"
|
@@ -4,17 +4,18 @@ require "securerandom"
|
|
4
4
|
|
5
5
|
module SecureRandom
|
6
6
|
BASE58_ALPHABET = ("0".."9").to_a + ("A".."Z").to_a + ("a".."z").to_a - ["0", "O", "I", "l"]
|
7
|
+
BASE36_ALPHABET = ("0".."9").to_a + ("a".."z").to_a
|
8
|
+
|
7
9
|
# SecureRandom.base58 generates a random base58 string.
|
8
10
|
#
|
9
|
-
# The argument _n_ specifies the length
|
11
|
+
# The argument _n_ specifies the length of the random string to be generated.
|
10
12
|
#
|
11
13
|
# If _n_ is not specified or is +nil+, 16 is assumed. It may be larger in the future.
|
12
14
|
#
|
13
|
-
# The result may contain alphanumeric characters except 0, O, I and l
|
15
|
+
# The result may contain alphanumeric characters except 0, O, I and l.
|
14
16
|
#
|
15
17
|
# p SecureRandom.base58 # => "4kUgL2pdQMSCQtjE"
|
16
18
|
# p SecureRandom.base58(24) # => "77TMHrHJFvFDwodq8w7Ev2m7"
|
17
|
-
#
|
18
19
|
def self.base58(n = 16)
|
19
20
|
SecureRandom.random_bytes(n).unpack("C*").map do |byte|
|
20
21
|
idx = byte % 64
|
@@ -22,4 +23,23 @@ module SecureRandom
|
|
22
23
|
BASE58_ALPHABET[idx]
|
23
24
|
end.join
|
24
25
|
end
|
26
|
+
|
27
|
+
# SecureRandom.base36 generates a random base36 string in lowercase.
|
28
|
+
#
|
29
|
+
# The argument _n_ specifies the length of the random string to be generated.
|
30
|
+
#
|
31
|
+
# If _n_ is not specified or is +nil+, 16 is assumed. It may be larger in the future.
|
32
|
+
# This method can be used over +base58+ if a deterministic case key is necessary.
|
33
|
+
#
|
34
|
+
# The result will contain alphanumeric characters in lowercase.
|
35
|
+
#
|
36
|
+
# p SecureRandom.base36 # => "4kugl2pdqmscqtje"
|
37
|
+
# p SecureRandom.base36(24) # => "77tmhrhjfvfdwodq8w7ev2m7"
|
38
|
+
def self.base36(n = 16)
|
39
|
+
SecureRandom.random_bytes(n).unpack("C*").map do |byte|
|
40
|
+
idx = byte % 64
|
41
|
+
idx = SecureRandom.random_number(36) if idx >= 36
|
42
|
+
BASE36_ALPHABET[idx]
|
43
|
+
end.join
|
44
|
+
end
|
25
45
|
end
|
@@ -75,6 +75,10 @@ class String
|
|
75
75
|
# str.first(0) # => ""
|
76
76
|
# str.first(6) # => "hello"
|
77
77
|
def first(limit = 1)
|
78
|
+
ActiveSupport::Deprecation.warn(
|
79
|
+
"Calling String#first with a negative integer limit " \
|
80
|
+
"will raise an ArgumentError in Rails 6.1."
|
81
|
+
) if limit < 0
|
78
82
|
if limit == 0
|
79
83
|
""
|
80
84
|
elsif limit >= size
|
@@ -95,6 +99,10 @@ class String
|
|
95
99
|
# str.last(0) # => ""
|
96
100
|
# str.last(6) # => "hello"
|
97
101
|
def last(limit = 1)
|
102
|
+
ActiveSupport::Deprecation.warn(
|
103
|
+
"Calling String#last with a negative integer limit " \
|
104
|
+
"will raise an ArgumentError in Rails 6.1."
|
105
|
+
) if limit < 0
|
98
106
|
if limit == 0
|
99
107
|
""
|
100
108
|
elsif limit >= size
|
@@ -78,6 +78,47 @@ class String
|
|
78
78
|
"#{self[0, stop]}#{omission}"
|
79
79
|
end
|
80
80
|
|
81
|
+
# Truncates +text+ to at most <tt>bytesize</tt> bytes in length without
|
82
|
+
# breaking string encoding by splitting multibyte characters or breaking
|
83
|
+
# grapheme clusters ("perceptual characters") by truncating at combining
|
84
|
+
# characters.
|
85
|
+
#
|
86
|
+
# >> "🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪".size
|
87
|
+
# => 20
|
88
|
+
# >> "🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪".bytesize
|
89
|
+
# => 80
|
90
|
+
# >> "🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪".truncate_bytes(20)
|
91
|
+
# => "🔪🔪🔪🔪…"
|
92
|
+
#
|
93
|
+
# The truncated text ends with the <tt>:omission</tt> string, defaulting
|
94
|
+
# to "…", for a total length not exceeding <tt>bytesize</tt>.
|
95
|
+
def truncate_bytes(truncate_at, omission: "…")
|
96
|
+
omission ||= ""
|
97
|
+
|
98
|
+
case
|
99
|
+
when bytesize <= truncate_at
|
100
|
+
dup
|
101
|
+
when omission.bytesize > truncate_at
|
102
|
+
raise ArgumentError, "Omission #{omission.inspect} is #{omission.bytesize}, larger than the truncation length of #{truncate_at} bytes"
|
103
|
+
when omission.bytesize == truncate_at
|
104
|
+
omission.dup
|
105
|
+
else
|
106
|
+
self.class.new.tap do |cut|
|
107
|
+
cut_at = truncate_at - omission.bytesize
|
108
|
+
|
109
|
+
scan(/\X/) do |grapheme|
|
110
|
+
if cut.bytesize + grapheme.bytesize <= cut_at
|
111
|
+
cut << grapheme
|
112
|
+
else
|
113
|
+
break
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
cut << omission
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
81
122
|
# Truncates a given +text+ after a given number of words (<tt>words_count</tt>):
|
82
123
|
#
|
83
124
|
# 'Once upon a time in a world far far away'.truncate_words(4)
|
@@ -11,12 +11,13 @@ class String
|
|
11
11
|
# encapsulates the original string. A Unicode safe version of all the String methods are defined on this proxy
|
12
12
|
# class. If the proxy class doesn't respond to a certain method, it's forwarded to the encapsulated string.
|
13
13
|
#
|
14
|
-
# >> "lj".upcase
|
15
|
-
# => "lj"
|
16
14
|
# >> "lj".mb_chars.upcase.to_s
|
17
15
|
# => "LJ"
|
18
16
|
#
|
19
|
-
# NOTE:
|
17
|
+
# NOTE: Ruby 2.4 and later support native Unicode case mappings:
|
18
|
+
#
|
19
|
+
# >> "lj".upcase
|
20
|
+
# => "LJ"
|
20
21
|
#
|
21
22
|
# == Method chaining
|
22
23
|
#
|
@@ -134,8 +134,9 @@ end
|
|
134
134
|
module ActiveSupport #:nodoc:
|
135
135
|
class SafeBuffer < String
|
136
136
|
UNSAFE_STRING_METHODS = %w(
|
137
|
-
capitalize chomp chop delete
|
138
|
-
|
137
|
+
capitalize chomp chop delete delete_prefix delete_suffix
|
138
|
+
downcase gsub lstrip next reverse rstrip slice squeeze strip
|
139
|
+
sub succ swapcase tr tr_s unicode_normalize upcase
|
139
140
|
)
|
140
141
|
|
141
142
|
alias_method :original_concat, :concat
|
@@ -149,9 +150,7 @@ module ActiveSupport #:nodoc:
|
|
149
150
|
end
|
150
151
|
|
151
152
|
def [](*args)
|
152
|
-
if
|
153
|
-
super
|
154
|
-
elsif html_safe?
|
153
|
+
if html_safe?
|
155
154
|
new_safe_buffer = super
|
156
155
|
|
157
156
|
if new_safe_buffer
|
@@ -188,10 +187,22 @@ module ActiveSupport #:nodoc:
|
|
188
187
|
end
|
189
188
|
alias << concat
|
190
189
|
|
190
|
+
def insert(index, value)
|
191
|
+
super(index, html_escape_interpolated_argument(value))
|
192
|
+
end
|
193
|
+
|
191
194
|
def prepend(value)
|
192
195
|
super(html_escape_interpolated_argument(value))
|
193
196
|
end
|
194
197
|
|
198
|
+
def replace(value)
|
199
|
+
super(html_escape_interpolated_argument(value))
|
200
|
+
end
|
201
|
+
|
202
|
+
def []=(index, value)
|
203
|
+
super(index, html_escape_interpolated_argument(value))
|
204
|
+
end
|
205
|
+
|
195
206
|
def +(other)
|
196
207
|
dup.concat(other)
|
197
208
|
end
|
@@ -20,6 +20,8 @@ class String
|
|
20
20
|
# Technically, it looks for the least indented non-empty line
|
21
21
|
# in the whole string, and removes that amount of leading whitespace.
|
22
22
|
def strip_heredoc
|
23
|
-
gsub(/^#{scan(/^[ \t]*(?=\S)/).min}/, "".
|
23
|
+
gsub(/^#{scan(/^[ \t]*(?=\S)/).min}/, "").tap do |stripped|
|
24
|
+
stripped.freeze if frozen?
|
25
|
+
end
|
24
26
|
end
|
25
27
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/callbacks"
|
4
|
+
|
3
5
|
module ActiveSupport
|
4
6
|
# Abstract super class that provides a thread-isolated attributes singleton, which resets automatically
|
5
7
|
# before and after each request. This allows you to keep all the per-request attributes easily
|
@@ -79,6 +79,12 @@ module ActiveSupport #:nodoc:
|
|
79
79
|
# to allow arbitrary constants to be marked for unloading.
|
80
80
|
mattr_accessor :explicitly_unloadable_constants, default: []
|
81
81
|
|
82
|
+
# The logger used when tracing autoloads.
|
83
|
+
mattr_accessor :logger
|
84
|
+
|
85
|
+
# If true, trace autoloads with +logger.debug+.
|
86
|
+
mattr_accessor :verbose, default: false
|
87
|
+
|
82
88
|
# The WatchStack keeps a stack of the modules being watched as files are
|
83
89
|
# loaded. If a file in the process of being loaded (parent.rb) triggers the
|
84
90
|
# load of another file (child.rb) the stack will ensure that child.rb
|
@@ -140,7 +146,7 @@ module ActiveSupport #:nodoc:
|
|
140
146
|
|
141
147
|
# Normalize the list of new constants, and add them to the list we will return
|
142
148
|
new_constants.each do |suffix|
|
143
|
-
constants << ([namespace, suffix] - ["Object"]).join("::"
|
149
|
+
constants << ([namespace, suffix] - ["Object"]).join("::")
|
144
150
|
end
|
145
151
|
end
|
146
152
|
constants
|
@@ -349,7 +355,7 @@ module ActiveSupport #:nodoc:
|
|
349
355
|
end
|
350
356
|
|
351
357
|
def require_or_load(file_name, const_path = nil)
|
352
|
-
file_name =
|
358
|
+
file_name = file_name.chomp(".rb")
|
353
359
|
expanded = File.expand_path(file_name)
|
354
360
|
return if loaded.include?(expanded)
|
355
361
|
|
@@ -399,7 +405,7 @@ module ActiveSupport #:nodoc:
|
|
399
405
|
# constant paths which would cause Dependencies to attempt to load this
|
400
406
|
# file.
|
401
407
|
def loadable_constants_for_path(path, bases = autoload_paths)
|
402
|
-
path =
|
408
|
+
path = path.chomp(".rb")
|
403
409
|
expanded_path = File.expand_path(path)
|
404
410
|
paths = []
|
405
411
|
|
@@ -408,7 +414,7 @@ module ActiveSupport #:nodoc:
|
|
408
414
|
next unless expanded_path.start_with?(expanded_root)
|
409
415
|
|
410
416
|
root_size = expanded_root.size
|
411
|
-
next if expanded_path[root_size] !=
|
417
|
+
next if expanded_path[root_size] != ?/
|
412
418
|
|
413
419
|
nesting = expanded_path[(root_size + 1)..-1]
|
414
420
|
paths << nesting.camelize unless nesting.blank?
|
@@ -420,7 +426,7 @@ module ActiveSupport #:nodoc:
|
|
420
426
|
|
421
427
|
# Search for a file in autoload_paths matching the provided suffix.
|
422
428
|
def search_for_file(path_suffix)
|
423
|
-
path_suffix
|
429
|
+
path_suffix += ".rb" unless path_suffix.ends_with?(".rb")
|
424
430
|
|
425
431
|
autoload_paths.each do |root|
|
426
432
|
path = File.join(root, path_suffix)
|
@@ -454,6 +460,7 @@ module ActiveSupport #:nodoc:
|
|
454
460
|
return nil unless base_path = autoloadable_module?(path_suffix)
|
455
461
|
mod = Module.new
|
456
462
|
into.const_set const_name, mod
|
463
|
+
log("constant #{qualified_name} autoloaded (module autovivified from #{File.join(base_path, path_suffix)})")
|
457
464
|
autoloaded_constants << qualified_name unless autoload_once_paths.include?(base_path)
|
458
465
|
autoloaded_constants.uniq!
|
459
466
|
mod
|
@@ -495,26 +502,31 @@ module ActiveSupport #:nodoc:
|
|
495
502
|
raise ArgumentError, "A copy of #{from_mod} has been removed from the module tree but is still active!"
|
496
503
|
end
|
497
504
|
|
498
|
-
qualified_name = qualified_name_for
|
505
|
+
qualified_name = qualified_name_for(from_mod, const_name)
|
499
506
|
path_suffix = qualified_name.underscore
|
500
507
|
|
501
508
|
file_path = search_for_file(path_suffix)
|
502
509
|
|
503
510
|
if file_path
|
504
511
|
expanded = File.expand_path(file_path)
|
505
|
-
expanded.sub!(/\.rb\z/, ""
|
512
|
+
expanded.sub!(/\.rb\z/, "")
|
506
513
|
|
507
514
|
if loading.include?(expanded)
|
508
515
|
raise "Circular dependency detected while autoloading constant #{qualified_name}"
|
509
516
|
else
|
510
517
|
require_or_load(expanded, qualified_name)
|
511
|
-
|
512
|
-
|
518
|
+
|
519
|
+
if from_mod.const_defined?(const_name, false)
|
520
|
+
log("constant #{qualified_name} autoloaded from #{expanded}.rb")
|
521
|
+
return from_mod.const_get(const_name)
|
522
|
+
else
|
523
|
+
raise LoadError, "Unable to autoload constant #{qualified_name}, expected #{file_path} to define it"
|
524
|
+
end
|
513
525
|
end
|
514
526
|
elsif mod = autoload_module!(from_mod, const_name, qualified_name, path_suffix)
|
515
527
|
return mod
|
516
|
-
elsif (parent = from_mod.
|
517
|
-
! from_mod.
|
528
|
+
elsif (parent = from_mod.module_parent) && parent != from_mod &&
|
529
|
+
! from_mod.module_parents.any? { |p| p.const_defined?(const_name, false) }
|
518
530
|
# If our parents do not have a constant named +const_name+ then we are free
|
519
531
|
# to attempt to load upwards. If they do have such a constant, then this
|
520
532
|
# const_missing must be due to from_mod::const_name, which should not
|
@@ -558,6 +570,7 @@ module ActiveSupport #:nodoc:
|
|
558
570
|
# as the environment will be in an inconsistent state, e.g. other constants
|
559
571
|
# may have already been unloaded and not accessible.
|
560
572
|
def remove_unloadable_constants!
|
573
|
+
log("removing unloadable constants")
|
561
574
|
autoloaded_constants.each { |const| remove_constant const }
|
562
575
|
autoloaded_constants.clear
|
563
576
|
Reference.clear!
|
@@ -747,6 +760,10 @@ module ActiveSupport #:nodoc:
|
|
747
760
|
# The constant is no longer reachable, just skip it.
|
748
761
|
end
|
749
762
|
end
|
763
|
+
|
764
|
+
def log(message)
|
765
|
+
logger.debug("autoloading: #{message}") if logger && verbose
|
766
|
+
end
|
750
767
|
end
|
751
768
|
end
|
752
769
|
|