activesupport 5.0.0 → 6.1.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 +343 -590
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -4
- data/lib/active_support/actionable_error.rb +48 -0
- data/lib/active_support/all.rb +5 -3
- data/lib/active_support/array_inquirer.rb +11 -5
- data/lib/active_support/backtrace_cleaner.rb +33 -5
- data/lib/active_support/benchmarkable.rb +5 -3
- data/lib/active_support/builder.rb +3 -1
- data/lib/active_support/cache/file_store.rb +45 -53
- data/lib/active_support/cache/mem_cache_store.rb +81 -79
- data/lib/active_support/cache/memory_store.rb +69 -41
- data/lib/active_support/cache/null_store.rb +11 -4
- data/lib/active_support/cache/redis_cache_store.rb +493 -0
- data/lib/active_support/cache/strategy/local_cache.rb +74 -37
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
- data/lib/active_support/cache.rb +332 -161
- data/lib/active_support/callbacks.rb +657 -586
- data/lib/active_support/concern.rb +79 -6
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +35 -0
- data/lib/active_support/concurrency/share_lock.rb +59 -19
- data/lib/active_support/configurable.rb +15 -17
- data/lib/active_support/configuration_file.rb +46 -0
- data/lib/active_support/core_ext/array/access.rb +21 -7
- data/lib/active_support/core_ext/array/conversions.rb +20 -18
- data/lib/active_support/core_ext/array/extract.rb +21 -0
- data/lib/active_support/core_ext/array/extract_options.rb +2 -0
- data/lib/active_support/core_ext/array/grouping.rb +3 -1
- data/lib/active_support/core_ext/array/inquiry.rb +3 -1
- data/lib/active_support/core_ext/array/wrap.rb +2 -0
- data/lib/active_support/core_ext/array.rb +9 -7
- data/lib/active_support/core_ext/benchmark.rb +5 -3
- data/lib/active_support/core_ext/big_decimal/conversions.rb +6 -6
- data/lib/active_support/core_ext/big_decimal.rb +3 -1
- data/lib/active_support/core_ext/class/attribute.rb +52 -49
- data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
- data/lib/active_support/core_ext/class/subclasses.rb +18 -26
- data/lib/active_support/core_ext/class.rb +4 -2
- data/lib/active_support/core_ext/date/acts_like.rb +3 -1
- data/lib/active_support/core_ext/date/blank.rb +3 -1
- data/lib/active_support/core_ext/date/calculations.rb +16 -13
- data/lib/active_support/core_ext/date/conversions.rb +23 -21
- data/lib/active_support/core_ext/date/zones.rb +4 -2
- data/lib/active_support/core_ext/date.rb +7 -5
- data/lib/active_support/core_ext/date_and_time/calculations.rb +82 -53
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +18 -5
- data/lib/active_support/core_ext/date_and_time/zones.rb +9 -9
- data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
- data/lib/active_support/core_ext/date_time/blank.rb +3 -1
- data/lib/active_support/core_ext/date_time/calculations.rb +23 -11
- data/lib/active_support/core_ext/date_time/compatibility.rb +15 -2
- data/lib/active_support/core_ext/date_time/conversions.rb +14 -13
- data/lib/active_support/core_ext/date_time.rb +7 -5
- data/lib/active_support/core_ext/digest/uuid.rb +7 -5
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/enumerable.rb +165 -29
- data/lib/active_support/core_ext/file/atomic.rb +7 -5
- data/lib/active_support/core_ext/file.rb +3 -1
- data/lib/active_support/core_ext/hash/conversions.rb +40 -39
- data/lib/active_support/core_ext/hash/deep_merge.rb +8 -12
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
- data/lib/active_support/core_ext/hash/except.rb +4 -2
- data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -2
- data/lib/active_support/core_ext/hash/keys.rb +9 -36
- data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
- data/lib/active_support/core_ext/hash/slice.rb +8 -29
- data/lib/active_support/core_ext/hash.rb +10 -9
- data/lib/active_support/core_ext/integer/inflections.rb +3 -1
- data/lib/active_support/core_ext/integer/multiple.rb +3 -1
- data/lib/active_support/core_ext/integer/time.rb +11 -18
- data/lib/active_support/core_ext/integer.rb +5 -3
- data/lib/active_support/core_ext/kernel/concern.rb +3 -1
- data/lib/active_support/core_ext/kernel/reporting.rb +3 -1
- data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
- data/lib/active_support/core_ext/kernel.rb +5 -4
- data/lib/active_support/core_ext/load_error.rb +2 -23
- data/lib/active_support/core_ext/marshal.rb +6 -2
- data/lib/active_support/core_ext/module/aliasing.rb +5 -48
- data/lib/active_support/core_ext/module/anonymous.rb +2 -0
- data/lib/active_support/core_ext/module/attr_internal.rb +7 -5
- data/lib/active_support/core_ext/module/attribute_accessors.rb +53 -59
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +31 -24
- data/lib/active_support/core_ext/module/concerning.rb +16 -11
- data/lib/active_support/core_ext/module/delegation.rb +159 -44
- data/lib/active_support/core_ext/module/deprecation.rb +2 -0
- data/lib/active_support/core_ext/module/introspection.rb +23 -26
- data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
- data/lib/active_support/core_ext/module/remove_method.rb +5 -23
- data/lib/active_support/core_ext/module.rb +13 -12
- data/lib/active_support/core_ext/name_error.rb +36 -2
- data/lib/active_support/core_ext/numeric/bytes.rb +2 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +129 -134
- data/lib/active_support/core_ext/numeric/time.rb +18 -26
- data/lib/active_support/core_ext/numeric.rb +5 -4
- data/lib/active_support/core_ext/object/acts_like.rb +12 -1
- data/lib/active_support/core_ext/object/blank.rb +14 -2
- data/lib/active_support/core_ext/object/conversions.rb +6 -4
- data/lib/active_support/core_ext/object/deep_dup.rb +4 -2
- data/lib/active_support/core_ext/object/duplicable.rb +13 -62
- data/lib/active_support/core_ext/object/inclusion.rb +3 -1
- data/lib/active_support/core_ext/object/instance_variables.rb +2 -0
- data/lib/active_support/core_ext/object/json.rb +42 -15
- data/lib/active_support/core_ext/object/to_param.rb +3 -1
- data/lib/active_support/core_ext/object/to_query.rb +10 -5
- data/lib/active_support/core_ext/object/try.rb +20 -8
- data/lib/active_support/core_ext/object/with_options.rb +15 -2
- data/lib/active_support/core_ext/object.rb +14 -12
- data/lib/active_support/core_ext/range/compare_range.rb +82 -0
- data/lib/active_support/core_ext/range/conversions.rb +35 -25
- data/lib/active_support/core_ext/range/each.rb +5 -2
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +28 -0
- data/lib/active_support/core_ext/range/overlaps.rb +2 -0
- data/lib/active_support/core_ext/range.rb +7 -4
- data/lib/active_support/core_ext/regexp.rb +10 -1
- data/lib/active_support/core_ext/securerandom.rb +28 -6
- data/lib/active_support/core_ext/string/access.rb +9 -18
- data/lib/active_support/core_ext/string/behavior.rb +2 -0
- data/lib/active_support/core_ext/string/conversions.rb +5 -2
- data/lib/active_support/core_ext/string/exclude.rb +2 -0
- data/lib/active_support/core_ext/string/filters.rb +47 -4
- data/lib/active_support/core_ext/string/indent.rb +6 -4
- data/lib/active_support/core_ext/string/inflections.rb +78 -29
- data/lib/active_support/core_ext/string/inquiry.rb +4 -1
- data/lib/active_support/core_ext/string/multibyte.rb +10 -5
- data/lib/active_support/core_ext/string/output_safety.rb +86 -31
- data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
- data/lib/active_support/core_ext/string/strip.rb +5 -1
- data/lib/active_support/core_ext/string/zones.rb +4 -2
- data/lib/active_support/core_ext/string.rb +15 -13
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
- data/lib/active_support/core_ext/symbol.rb +3 -0
- data/lib/active_support/core_ext/time/acts_like.rb +3 -1
- data/lib/active_support/core_ext/time/calculations.rb +117 -45
- data/lib/active_support/core_ext/time/compatibility.rb +13 -2
- data/lib/active_support/core_ext/time/conversions.rb +18 -12
- data/lib/active_support/core_ext/time/zones.rb +9 -7
- data/lib/active_support/core_ext/time.rb +7 -5
- data/lib/active_support/core_ext/uri.rb +12 -7
- data/lib/active_support/core_ext.rb +3 -2
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/current_attributes.rb +208 -0
- data/lib/active_support/dependencies/autoload.rb +2 -0
- data/lib/active_support/dependencies/interlock.rb +7 -1
- data/lib/active_support/dependencies/zeitwerk_integration.rb +117 -0
- data/lib/active_support/dependencies.rb +172 -98
- data/lib/active_support/deprecation/behaviors.rb +45 -13
- data/lib/active_support/deprecation/constant_accessor.rb +52 -0
- data/lib/active_support/deprecation/disallowed.rb +56 -0
- data/lib/active_support/deprecation/instance_delegator.rb +16 -2
- data/lib/active_support/deprecation/method_wrappers.rb +32 -17
- data/lib/active_support/deprecation/proxy_wrappers.rb +35 -7
- data/lib/active_support/deprecation/reporting.rb +61 -16
- data/lib/active_support/deprecation.rb +17 -9
- data/lib/active_support/descendants_tracker.rb +61 -9
- data/lib/active_support/digest.rb +20 -0
- data/lib/active_support/duration/iso8601_parser.rb +67 -66
- data/lib/active_support/duration/iso8601_serializer.rb +25 -17
- data/lib/active_support/duration.rb +349 -46
- data/lib/active_support/encrypted_configuration.rb +45 -0
- data/lib/active_support/encrypted_file.rb +117 -0
- data/lib/active_support/environment_inquirer.rb +20 -0
- data/lib/active_support/evented_file_update_checker.rb +88 -112
- data/lib/active_support/execution_wrapper.rb +25 -13
- data/lib/active_support/executor.rb +3 -1
- data/lib/active_support/file_update_checker.rb +56 -51
- data/lib/active_support/fork_tracker.rb +62 -0
- 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 +153 -49
- data/lib/active_support/i18n.rb +9 -6
- data/lib/active_support/i18n_railtie.rb +30 -20
- data/lib/active_support/inflections.rb +13 -11
- data/lib/active_support/inflector/inflections.rb +28 -15
- data/lib/active_support/inflector/methods.rb +120 -109
- data/lib/active_support/inflector/transliterate.rb +60 -25
- data/lib/active_support/inflector.rb +7 -5
- data/lib/active_support/json/decoding.rb +30 -29
- data/lib/active_support/json/encoding.rb +22 -11
- data/lib/active_support/json.rb +4 -2
- data/lib/active_support/key_generator.rb +6 -36
- data/lib/active_support/lazy_load_hooks.rb +53 -20
- data/lib/active_support/locale/en.rb +33 -0
- data/lib/active_support/locale/en.yml +7 -3
- data/lib/active_support/log_subscriber/test_helper.rb +11 -9
- data/lib/active_support/log_subscriber.rb +51 -18
- data/lib/active_support/logger.rb +9 -22
- data/lib/active_support/logger_silence.rb +14 -21
- data/lib/active_support/logger_thread_safe_level.rb +55 -8
- data/lib/active_support/message_encryptor.rb +170 -53
- data/lib/active_support/message_verifier.rb +91 -20
- data/lib/active_support/messages/metadata.rb +80 -0
- data/lib/active_support/messages/rotation_configuration.rb +23 -0
- data/lib/active_support/messages/rotator.rb +57 -0
- data/lib/active_support/multibyte/chars.rb +24 -78
- data/lib/active_support/multibyte/unicode.rb +21 -352
- data/lib/active_support/multibyte.rb +4 -2
- data/lib/active_support/notifications/fanout.rb +121 -19
- data/lib/active_support/notifications/instrumenter.rb +78 -14
- data/lib/active_support/notifications.rb +80 -12
- data/lib/active_support/number_helper/number_converter.rb +17 -16
- data/lib/active_support/number_helper/number_to_currency_converter.rb +6 -9
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +5 -3
- data/lib/active_support/number_helper/number_to_human_converter.rb +13 -12
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +11 -13
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +5 -4
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +18 -55
- data/lib/active_support/number_helper/rounding_helper.rb +50 -0
- data/lib/active_support/number_helper.rb +45 -16
- data/lib/active_support/option_merger.rb +25 -4
- data/lib/active_support/ordered_hash.rb +6 -4
- data/lib/active_support/ordered_options.rb +23 -9
- data/lib/active_support/parameter_filter.rb +133 -0
- data/lib/active_support/per_thread_registry.rb +7 -5
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/rails.rb +8 -9
- data/lib/active_support/railtie.rb +62 -11
- data/lib/active_support/reloader.rb +12 -11
- data/lib/active_support/rescuable.rb +20 -11
- data/lib/active_support/secure_compare_rotator.rb +51 -0
- data/lib/active_support/security_utils.rb +26 -15
- data/lib/active_support/string_inquirer.rb +12 -3
- data/lib/active_support/subscriber.rb +77 -23
- data/lib/active_support/tagged_logging.rb +52 -17
- data/lib/active_support/test_case.rb +106 -29
- data/lib/active_support/testing/assertions.rb +144 -8
- data/lib/active_support/testing/autorun.rb +5 -10
- 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 +4 -2
- data/lib/active_support/testing/file_fixtures.rb +4 -0
- data/lib/active_support/testing/isolation.rb +19 -24
- data/lib/active_support/testing/method_call_assertions.rb +31 -2
- data/lib/active_support/testing/parallelization/server.rb +78 -0
- data/lib/active_support/testing/parallelization/worker.rb +100 -0
- data/lib/active_support/testing/parallelization.rb +51 -0
- data/lib/active_support/testing/setup_and_teardown.rb +13 -8
- data/lib/active_support/testing/stream.rb +30 -29
- data/lib/active_support/testing/tagged_logging.rb +3 -1
- data/lib/active_support/testing/time_helpers.rb +125 -24
- data/lib/active_support/time.rb +14 -12
- data/lib/active_support/time_with_zone.rb +142 -55
- data/lib/active_support/values/time_zone.rb +160 -53
- data/lib/active_support/version.rb +3 -1
- data/lib/active_support/xml_mini/jdom.rb +115 -114
- data/lib/active_support/xml_mini/libxml.rb +15 -14
- data/lib/active_support/xml_mini/libxmlsax.rb +16 -18
- data/lib/active_support/xml_mini/nokogiri.rb +13 -13
- data/lib/active_support/xml_mini/nokogirisax.rb +15 -16
- data/lib/active_support/xml_mini/rexml.rb +18 -9
- data/lib/active_support/xml_mini.rb +44 -42
- data/lib/active_support.rb +19 -10
- metadata +79 -37
- data/lib/active_support/concurrency/latch.rb +0 -19
- data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
- data/lib/active_support/core_ext/hash/compact.rb +0 -20
- data/lib/active_support/core_ext/hash/transform_values.rb +0 -29
- data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
- data/lib/active_support/core_ext/kernel/debugger.rb +0 -3
- data/lib/active_support/core_ext/module/method_transplanting.rb +0 -3
- data/lib/active_support/core_ext/module/qualified_const.rb +0 -70
- data/lib/active_support/core_ext/module/reachable.rb +0 -8
- data/lib/active_support/core_ext/numeric/inquiry.rb +0 -26
- data/lib/active_support/core_ext/range/include_range.rb +0 -23
- data/lib/active_support/core_ext/struct.rb +0 -3
- data/lib/active_support/core_ext/time/marshal.rb +0 -3
- data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveSupport
|
2
4
|
# A typical module looks like this:
|
3
5
|
#
|
@@ -17,7 +19,7 @@ module ActiveSupport
|
|
17
19
|
# By using <tt>ActiveSupport::Concern</tt> the above module could instead be
|
18
20
|
# written as:
|
19
21
|
#
|
20
|
-
# require
|
22
|
+
# require "active_support/concern"
|
21
23
|
#
|
22
24
|
# module M
|
23
25
|
# extend ActiveSupport::Concern
|
@@ -74,7 +76,7 @@ module ActiveSupport
|
|
74
76
|
# is the +Bar+ module, not the +Host+ class. With <tt>ActiveSupport::Concern</tt>,
|
75
77
|
# module dependencies are properly resolved:
|
76
78
|
#
|
77
|
-
# require
|
79
|
+
# require "active_support/concern"
|
78
80
|
#
|
79
81
|
# module Foo
|
80
82
|
# extend ActiveSupport::Concern
|
@@ -97,6 +99,14 @@ module ActiveSupport
|
|
97
99
|
# class Host
|
98
100
|
# include Bar # It works, now Bar takes care of its dependencies
|
99
101
|
# end
|
102
|
+
#
|
103
|
+
# === Prepending concerns
|
104
|
+
#
|
105
|
+
# Just like <tt>include</tt>, concerns also support <tt>prepend</tt> with a corresponding
|
106
|
+
# <tt>prepended do</tt> callback. <tt>module ClassMethods</tt> or <tt>class_methods do</tt> are
|
107
|
+
# prepended as well.
|
108
|
+
#
|
109
|
+
# <tt>prepend</tt> is also used for any dependencies.
|
100
110
|
module Concern
|
101
111
|
class MultipleIncludedBlocks < StandardError #:nodoc:
|
102
112
|
def initialize
|
@@ -104,14 +114,20 @@ module ActiveSupport
|
|
104
114
|
end
|
105
115
|
end
|
106
116
|
|
117
|
+
class MultiplePrependBlocks < StandardError #:nodoc:
|
118
|
+
def initialize
|
119
|
+
super "Cannot define multiple 'prepended' blocks for a Concern"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
107
123
|
def self.extended(base) #:nodoc:
|
108
124
|
base.instance_variable_set(:@_dependencies, [])
|
109
125
|
end
|
110
126
|
|
111
|
-
def append_features(base)
|
127
|
+
def append_features(base) #:nodoc:
|
112
128
|
if base.instance_variable_defined?(:@_dependencies)
|
113
129
|
base.instance_variable_get(:@_dependencies) << self
|
114
|
-
|
130
|
+
false
|
115
131
|
else
|
116
132
|
return false if base < self
|
117
133
|
@_dependencies.each { |dep| base.include(dep) }
|
@@ -121,16 +137,73 @@ module ActiveSupport
|
|
121
137
|
end
|
122
138
|
end
|
123
139
|
|
140
|
+
def prepend_features(base) #:nodoc:
|
141
|
+
if base.instance_variable_defined?(:@_dependencies)
|
142
|
+
base.instance_variable_get(:@_dependencies).unshift self
|
143
|
+
false
|
144
|
+
else
|
145
|
+
return false if base < self
|
146
|
+
@_dependencies.each { |dep| base.prepend(dep) }
|
147
|
+
super
|
148
|
+
base.singleton_class.prepend const_get(:ClassMethods) if const_defined?(:ClassMethods)
|
149
|
+
base.class_eval(&@_prepended_block) if instance_variable_defined?(:@_prepended_block)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# Evaluate given block in context of base class,
|
154
|
+
# so that you can write class macros here.
|
155
|
+
# When you define more than one +included+ block, it raises an exception.
|
124
156
|
def included(base = nil, &block)
|
125
157
|
if base.nil?
|
126
|
-
|
158
|
+
if instance_variable_defined?(:@_included_block)
|
159
|
+
if @_included_block.source_location != block.source_location
|
160
|
+
raise MultipleIncludedBlocks
|
161
|
+
end
|
162
|
+
else
|
163
|
+
@_included_block = block
|
164
|
+
end
|
165
|
+
else
|
166
|
+
super
|
167
|
+
end
|
168
|
+
end
|
127
169
|
|
128
|
-
|
170
|
+
# Evaluate given block in context of base class,
|
171
|
+
# so that you can write class macros here.
|
172
|
+
# When you define more than one +prepended+ block, it raises an exception.
|
173
|
+
def prepended(base = nil, &block)
|
174
|
+
if base.nil?
|
175
|
+
if instance_variable_defined?(:@_prepended_block)
|
176
|
+
if @_prepended_block.source_location != block.source_location
|
177
|
+
raise MultiplePrependBlocks
|
178
|
+
end
|
179
|
+
else
|
180
|
+
@_prepended_block = block
|
181
|
+
end
|
129
182
|
else
|
130
183
|
super
|
131
184
|
end
|
132
185
|
end
|
133
186
|
|
187
|
+
# Define class methods from given block.
|
188
|
+
# You can define private class methods as well.
|
189
|
+
#
|
190
|
+
# module Example
|
191
|
+
# extend ActiveSupport::Concern
|
192
|
+
#
|
193
|
+
# class_methods do
|
194
|
+
# def foo; puts 'foo'; end
|
195
|
+
#
|
196
|
+
# private
|
197
|
+
# def bar; puts 'bar'; end
|
198
|
+
# end
|
199
|
+
# end
|
200
|
+
#
|
201
|
+
# class Buzz
|
202
|
+
# include Example
|
203
|
+
# end
|
204
|
+
#
|
205
|
+
# Buzz.foo # => "foo"
|
206
|
+
# Buzz.bar # => private method 'bar' called for Buzz:Class(NoMethodError)
|
134
207
|
def class_methods(&class_methods_module_definition)
|
135
208
|
mod = const_defined?(:ClassMethods, false) ?
|
136
209
|
const_get(:ClassMethods) :
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "monitor"
|
4
|
+
|
5
|
+
module ActiveSupport
|
6
|
+
module Concurrency
|
7
|
+
# A monitor that will permit dependency loading while blocked waiting for
|
8
|
+
# the lock.
|
9
|
+
class LoadInterlockAwareMonitor < Monitor
|
10
|
+
EXCEPTION_NEVER = { Exception => :never }.freeze
|
11
|
+
EXCEPTION_IMMEDIATE = { Exception => :immediate }.freeze
|
12
|
+
private_constant :EXCEPTION_NEVER, :EXCEPTION_IMMEDIATE
|
13
|
+
|
14
|
+
# Enters an exclusive section, but allows dependency loading while blocked
|
15
|
+
def mon_enter
|
16
|
+
mon_try_enter ||
|
17
|
+
ActiveSupport::Dependencies.interlock.permit_concurrent_loads { super }
|
18
|
+
end
|
19
|
+
|
20
|
+
def synchronize
|
21
|
+
Thread.handle_interrupt(EXCEPTION_NEVER) do
|
22
|
+
mon_enter
|
23
|
+
|
24
|
+
begin
|
25
|
+
Thread.handle_interrupt(EXCEPTION_IMMEDIATE) do
|
26
|
+
yield
|
27
|
+
end
|
28
|
+
ensure
|
29
|
+
mon_exit
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -1,5 +1,7 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "thread"
|
4
|
+
require "monitor"
|
3
5
|
|
4
6
|
module ActiveSupport
|
5
7
|
module Concurrency
|
@@ -13,6 +15,37 @@ module ActiveSupport
|
|
13
15
|
# we need exclusive locks to be reentrant, and we need to be able
|
14
16
|
# to upgrade share locks to exclusive.
|
15
17
|
|
18
|
+
def raw_state # :nodoc:
|
19
|
+
synchronize do
|
20
|
+
threads = @sleeping.keys | @sharing.keys | @waiting.keys
|
21
|
+
threads |= [@exclusive_thread] if @exclusive_thread
|
22
|
+
|
23
|
+
data = {}
|
24
|
+
|
25
|
+
threads.each do |thread|
|
26
|
+
purpose, compatible = @waiting[thread]
|
27
|
+
|
28
|
+
data[thread] = {
|
29
|
+
thread: thread,
|
30
|
+
sharing: @sharing[thread],
|
31
|
+
exclusive: @exclusive_thread == thread,
|
32
|
+
purpose: purpose,
|
33
|
+
compatible: compatible,
|
34
|
+
waiting: !!@waiting[thread],
|
35
|
+
sleeper: @sleeping[thread],
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
# NB: Yields while holding our *internal* synchronize lock,
|
40
|
+
# which is supposed to be used only for a few instructions at
|
41
|
+
# a time. This allows the caller to inspect additional state
|
42
|
+
# without things changing out from underneath, but would have
|
43
|
+
# disastrous effects upon normal operation. Fortunately, this
|
44
|
+
# method is only intended to be called when things have
|
45
|
+
# already gone wrong.
|
46
|
+
yield data
|
47
|
+
end
|
48
|
+
end
|
16
49
|
|
17
50
|
def initialize
|
18
51
|
super()
|
@@ -21,6 +54,7 @@ module ActiveSupport
|
|
21
54
|
|
22
55
|
@sharing = Hash.new(0)
|
23
56
|
@waiting = {}
|
57
|
+
@sleeping = {}
|
24
58
|
@exclusive_thread = nil
|
25
59
|
@exclusive_depth = 0
|
26
60
|
end
|
@@ -46,7 +80,7 @@ module ActiveSupport
|
|
46
80
|
return false if no_wait
|
47
81
|
|
48
82
|
yield_shares(purpose: purpose, compatible: compatible, block_share: true) do
|
49
|
-
|
83
|
+
wait_for(:start_exclusive) { busy_for_exclusive?(purpose) }
|
50
84
|
end
|
51
85
|
end
|
52
86
|
@exclusive_thread = Thread.current
|
@@ -69,7 +103,7 @@ module ActiveSupport
|
|
69
103
|
|
70
104
|
if eligible_waiters?(compatible)
|
71
105
|
yield_shares(compatible: compatible, block_share: true) do
|
72
|
-
|
106
|
+
wait_for(:stop_exclusive) { @exclusive_thread || eligible_waiters?(compatible) }
|
73
107
|
end
|
74
108
|
end
|
75
109
|
@cv.broadcast
|
@@ -84,11 +118,11 @@ module ActiveSupport
|
|
84
118
|
elsif @waiting[Thread.current]
|
85
119
|
# We're nested inside a +yield_shares+ call: we'll resume as
|
86
120
|
# soon as there isn't an exclusive lock in our way
|
87
|
-
|
121
|
+
wait_for(:start_sharing) { @exclusive_thread }
|
88
122
|
else
|
89
123
|
# This is an initial / outermost share call: any outstanding
|
90
124
|
# requests for an exclusive lock get to go first
|
91
|
-
|
125
|
+
wait_for(:start_sharing) { busy_for_sharing?(false) }
|
92
126
|
end
|
93
127
|
@sharing[Thread.current] += 1
|
94
128
|
end
|
@@ -153,7 +187,7 @@ module ActiveSupport
|
|
153
187
|
yield
|
154
188
|
ensure
|
155
189
|
synchronize do
|
156
|
-
|
190
|
+
wait_for(:yield_shares) { @exclusive_thread && @exclusive_thread != Thread.current }
|
157
191
|
|
158
192
|
if previous_wait
|
159
193
|
@waiting[Thread.current] = previous_wait
|
@@ -166,21 +200,27 @@ module ActiveSupport
|
|
166
200
|
end
|
167
201
|
|
168
202
|
private
|
203
|
+
# Must be called within synchronize
|
204
|
+
def busy_for_exclusive?(purpose)
|
205
|
+
busy_for_sharing?(purpose) ||
|
206
|
+
@sharing.size > (@sharing[Thread.current] > 0 ? 1 : 0)
|
207
|
+
end
|
169
208
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
end
|
209
|
+
def busy_for_sharing?(purpose)
|
210
|
+
(@exclusive_thread && @exclusive_thread != Thread.current) ||
|
211
|
+
@waiting.any? { |t, (_, c)| t != Thread.current && !c.include?(purpose) }
|
212
|
+
end
|
175
213
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
end
|
214
|
+
def eligible_waiters?(compatible)
|
215
|
+
@waiting.any? { |t, (p, _)| compatible.include?(p) && @waiting.all? { |t2, (_, c2)| t == t2 || c2.include?(p) } }
|
216
|
+
end
|
180
217
|
|
181
|
-
|
182
|
-
|
183
|
-
|
218
|
+
def wait_for(method)
|
219
|
+
@sleeping[Thread.current] = method
|
220
|
+
@cv.wait_while { yield }
|
221
|
+
ensure
|
222
|
+
@sleeping.delete Thread.current
|
223
|
+
end
|
184
224
|
end
|
185
225
|
end
|
186
226
|
end
|
@@ -1,10 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/concern"
|
4
|
+
require "active_support/ordered_options"
|
4
5
|
|
5
6
|
module ActiveSupport
|
6
7
|
# Configurable provides a <tt>config</tt> method to store and retrieve
|
7
|
-
# configuration options as an <tt>
|
8
|
+
# configuration options as an <tt>OrderedOptions</tt>.
|
8
9
|
module Configurable
|
9
10
|
extend ActiveSupport::Concern
|
10
11
|
|
@@ -66,8 +67,8 @@ module ActiveSupport
|
|
66
67
|
# end
|
67
68
|
# # => NameError: invalid config attribute name
|
68
69
|
#
|
69
|
-
# To
|
70
|
-
# To
|
70
|
+
# To omit the instance writer method, pass <tt>instance_writer: false</tt>.
|
71
|
+
# To omit the instance reader method, pass <tt>instance_reader: false</tt>.
|
71
72
|
#
|
72
73
|
# class User
|
73
74
|
# include ActiveSupport::Configurable
|
@@ -80,7 +81,7 @@ module ActiveSupport
|
|
80
81
|
# User.new.allowed_access = true # => NoMethodError
|
81
82
|
# User.new.allowed_access # => NoMethodError
|
82
83
|
#
|
83
|
-
# Or pass <tt>instance_accessor: false</tt>, to
|
84
|
+
# Or pass <tt>instance_accessor: false</tt>, to omit both instance methods.
|
84
85
|
#
|
85
86
|
# class User
|
86
87
|
# include ActiveSupport::Configurable
|
@@ -103,11 +104,9 @@ module ActiveSupport
|
|
103
104
|
# end
|
104
105
|
#
|
105
106
|
# User.hair_colors # => [:brown, :black, :blonde, :red]
|
106
|
-
def config_accessor(*names)
|
107
|
-
options = names.extract_options!
|
108
|
-
|
107
|
+
def config_accessor(*names, instance_reader: true, instance_writer: true, instance_accessor: true) # :doc:
|
109
108
|
names.each do |name|
|
110
|
-
raise NameError.new(
|
109
|
+
raise NameError.new("invalid config attribute name") unless /\A[_A-Za-z]\w*\z/.match?(name)
|
111
110
|
|
112
111
|
reader, reader_line = "def #{name}; config.#{name}; end", __LINE__
|
113
112
|
writer, writer_line = "def #{name}=(value); config.#{name} = value; end", __LINE__
|
@@ -115,9 +114,9 @@ module ActiveSupport
|
|
115
114
|
singleton_class.class_eval reader, __FILE__, reader_line
|
116
115
|
singleton_class.class_eval writer, __FILE__, writer_line
|
117
116
|
|
118
|
-
|
119
|
-
class_eval reader, __FILE__, reader_line
|
120
|
-
class_eval writer, __FILE__, writer_line
|
117
|
+
if instance_accessor
|
118
|
+
class_eval reader, __FILE__, reader_line if instance_reader
|
119
|
+
class_eval writer, __FILE__, writer_line if instance_writer
|
121
120
|
end
|
122
121
|
send("#{name}=", yield) if block_given?
|
123
122
|
end
|
@@ -125,9 +124,9 @@ module ActiveSupport
|
|
125
124
|
private :config_accessor
|
126
125
|
end
|
127
126
|
|
128
|
-
# Reads and writes attributes from a configuration <tt>
|
127
|
+
# Reads and writes attributes from a configuration <tt>OrderedOptions</tt>.
|
129
128
|
#
|
130
|
-
# require
|
129
|
+
# require "active_support/configurable"
|
131
130
|
#
|
132
131
|
# class User
|
133
132
|
# include ActiveSupport::Configurable
|
@@ -145,4 +144,3 @@ module ActiveSupport
|
|
145
144
|
end
|
146
145
|
end
|
147
146
|
end
|
148
|
-
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveSupport
|
4
|
+
# Reads a YAML configuration file, evaluating any ERB, then
|
5
|
+
# parsing the resulting YAML.
|
6
|
+
#
|
7
|
+
# Warns in case of YAML confusing characters, like invisible
|
8
|
+
# non-breaking spaces.
|
9
|
+
class ConfigurationFile # :nodoc:
|
10
|
+
class FormatError < StandardError; end
|
11
|
+
|
12
|
+
def initialize(content_path)
|
13
|
+
@content_path = content_path.to_s
|
14
|
+
@content = read content_path
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.parse(content_path, **options)
|
18
|
+
new(content_path).parse(**options)
|
19
|
+
end
|
20
|
+
|
21
|
+
def parse(context: nil, **options)
|
22
|
+
YAML.load(render(context), **options) || {}
|
23
|
+
rescue Psych::SyntaxError => error
|
24
|
+
raise "YAML syntax error occurred while parsing #{@content_path}. " \
|
25
|
+
"Please note that YAML must be consistently indented using spaces. Tabs are not allowed. " \
|
26
|
+
"Error: #{error.message}"
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
def read(content_path)
|
31
|
+
require "yaml"
|
32
|
+
require "erb"
|
33
|
+
|
34
|
+
File.read(content_path).tap do |content|
|
35
|
+
if content.include?("\u00A0")
|
36
|
+
warn "File contains invisible non-breaking spaces, you may want to remove those"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def render(context)
|
42
|
+
erb = ERB.new(@content).tap { |e| e.filename = @content_path }
|
43
|
+
context ? erb.result(context) : erb.result
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Array
|
2
4
|
# Returns the tail of the array from +position+.
|
3
5
|
#
|
@@ -27,16 +29,28 @@ class Array
|
|
27
29
|
end
|
28
30
|
end
|
29
31
|
|
30
|
-
# Returns a
|
32
|
+
# Returns a new array that includes the passed elements.
|
33
|
+
#
|
34
|
+
# [ 1, 2, 3 ].including(4, 5) # => [ 1, 2, 3, 4, 5 ]
|
35
|
+
# [ [ 0, 1 ] ].including([ [ 1, 0 ] ]) # => [ [ 0, 1 ], [ 1, 0 ] ]
|
36
|
+
def including(*elements)
|
37
|
+
self + elements.flatten(1)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns a copy of the Array excluding the specified elements.
|
31
41
|
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
# => ["David", "Rafael"]
|
42
|
+
# ["David", "Rafael", "Aaron", "Todd"].excluding("Aaron", "Todd") # => ["David", "Rafael"]
|
43
|
+
# [ [ 0, 1 ], [ 1, 0 ] ].excluding([ [ 1, 0 ] ]) # => [ [ 0, 1 ] ]
|
35
44
|
#
|
36
|
-
# Note: This is an optimization of
|
37
|
-
# instead of
|
45
|
+
# Note: This is an optimization of <tt>Enumerable#excluding</tt> that uses <tt>Array#-</tt>
|
46
|
+
# instead of <tt>Array#reject</tt> for performance reasons.
|
47
|
+
def excluding(*elements)
|
48
|
+
self - elements.flatten(1)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Alias for #excluding.
|
38
52
|
def without(*elements)
|
39
|
-
|
53
|
+
excluding(*elements)
|
40
54
|
end
|
41
55
|
|
42
56
|
# Equal to <tt>self[1]</tt>.
|
@@ -1,8 +1,10 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/xml_mini"
|
4
|
+
require "active_support/core_ext/hash/keys"
|
5
|
+
require "active_support/core_ext/string/inflections"
|
6
|
+
require "active_support/core_ext/object/to_param"
|
7
|
+
require "active_support/core_ext/object/to_query"
|
6
8
|
|
7
9
|
class Array
|
8
10
|
# Converts the array to a comma-separated sentence where the last element is
|
@@ -60,9 +62,9 @@ class Array
|
|
60
62
|
options.assert_valid_keys(:words_connector, :two_words_connector, :last_word_connector, :locale)
|
61
63
|
|
62
64
|
default_connectors = {
|
63
|
-
:
|
64
|
-
:
|
65
|
-
:
|
65
|
+
words_connector: ", ",
|
66
|
+
two_words_connector: " and ",
|
67
|
+
last_word_connector: ", and "
|
66
68
|
}
|
67
69
|
if defined?(I18n)
|
68
70
|
i18n_connectors = I18n.translate(:'support.array', locale: options[:locale], default: {})
|
@@ -72,13 +74,13 @@ class Array
|
|
72
74
|
|
73
75
|
case length
|
74
76
|
when 0
|
75
|
-
|
77
|
+
+""
|
76
78
|
when 1
|
77
|
-
"#{self[0]}"
|
79
|
+
+"#{self[0]}"
|
78
80
|
when 2
|
79
|
-
"#{self[0]}#{options[:two_words_connector]}#{self[1]}"
|
81
|
+
+"#{self[0]}#{options[:two_words_connector]}#{self[1]}"
|
80
82
|
else
|
81
|
-
"#{self[0...-1].join(options[:words_connector])}#{options[:last_word_connector]}#{self[-1]}"
|
83
|
+
+"#{self[0...-1].join(options[:words_connector])}#{options[:last_word_connector]}#{self[-1]}"
|
82
84
|
end
|
83
85
|
end
|
84
86
|
|
@@ -92,9 +94,9 @@ class Array
|
|
92
94
|
case format
|
93
95
|
when :db
|
94
96
|
if empty?
|
95
|
-
|
97
|
+
"null"
|
96
98
|
else
|
97
|
-
collect(&:id).join(
|
99
|
+
collect(&:id).join(",")
|
98
100
|
end
|
99
101
|
else
|
100
102
|
to_default_s
|
@@ -179,7 +181,7 @@ class Array
|
|
179
181
|
# </messages>
|
180
182
|
#
|
181
183
|
def to_xml(options = {})
|
182
|
-
require
|
184
|
+
require "active_support/builder" unless defined?(Builder::XmlMarkup)
|
183
185
|
|
184
186
|
options = options.dup
|
185
187
|
options[:indent] ||= 2
|
@@ -187,9 +189,9 @@ class Array
|
|
187
189
|
options[:root] ||= \
|
188
190
|
if first.class != Hash && all? { |e| e.is_a?(first.class) }
|
189
191
|
underscored = ActiveSupport::Inflector.underscore(first.class.name)
|
190
|
-
ActiveSupport::Inflector.pluralize(underscored).tr(
|
192
|
+
ActiveSupport::Inflector.pluralize(underscored).tr("/", "_")
|
191
193
|
else
|
192
|
-
|
194
|
+
"objects"
|
193
195
|
end
|
194
196
|
|
195
197
|
builder = options[:builder]
|
@@ -197,7 +199,7 @@ class Array
|
|
197
199
|
|
198
200
|
root = ActiveSupport::XmlMini.rename_key(options[:root].to_s, options)
|
199
201
|
children = options.delete(:children) || root.singularize
|
200
|
-
attributes = options[:skip_types] ? {} : { type:
|
202
|
+
attributes = options[:skip_types] ? {} : { type: "array" }
|
201
203
|
|
202
204
|
if empty?
|
203
205
|
builder.tag!(root, attributes)
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Array
|
4
|
+
# Removes and returns the elements for which the block returns a true value.
|
5
|
+
# If no block is given, an Enumerator is returned instead.
|
6
|
+
#
|
7
|
+
# numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
8
|
+
# odd_numbers = numbers.extract! { |number| number.odd? } # => [1, 3, 5, 7, 9]
|
9
|
+
# numbers # => [0, 2, 4, 6, 8]
|
10
|
+
def extract!
|
11
|
+
return to_enum(:extract!) { size } unless block_given?
|
12
|
+
|
13
|
+
extracted_elements = []
|
14
|
+
|
15
|
+
reject! do |element|
|
16
|
+
extracted_elements << element if yield(element)
|
17
|
+
end
|
18
|
+
|
19
|
+
extracted_elements
|
20
|
+
end
|
21
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Array
|
2
4
|
# Splits or iterates over the array in groups of size +number+,
|
3
5
|
# padding any remaining slots with +fill_with+ unless it is +false+.
|
@@ -89,7 +91,7 @@ class Array
|
|
89
91
|
# [1, 2, 3, 4, 5].split(3) # => [[1, 2], [4, 5]]
|
90
92
|
# (1..10).to_a.split { |i| i % 3 == 0 } # => [[1, 2], [4, 5], [7, 8], [10]]
|
91
93
|
def split(value = nil)
|
92
|
-
arr =
|
94
|
+
arr = dup
|
93
95
|
result = []
|
94
96
|
if block_given?
|
95
97
|
while (idx = arr.index { |i| yield i })
|
@@ -1,7 +1,9 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/array/wrap"
|
4
|
+
require "active_support/core_ext/array/access"
|
5
|
+
require "active_support/core_ext/array/conversions"
|
6
|
+
require "active_support/core_ext/array/extract"
|
7
|
+
require "active_support/core_ext/array/extract_options"
|
8
|
+
require "active_support/core_ext/array/grouping"
|
9
|
+
require "active_support/core_ext/array/inquiry"
|
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "benchmark"
|
2
4
|
|
3
5
|
class << Benchmark
|
4
6
|
# Benchmark realtime in milliseconds.
|
@@ -8,7 +10,7 @@ class << Benchmark
|
|
8
10
|
#
|
9
11
|
# Benchmark.ms { User.all }
|
10
12
|
# # => 0.074
|
11
|
-
def ms
|
12
|
-
1000 * realtime
|
13
|
+
def ms(&block)
|
14
|
+
1000 * realtime(&block)
|
13
15
|
end
|
14
16
|
end
|