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,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveSupport
|
2
4
|
# A typical module looks like this:
|
3
5
|
#
|
@@ -111,10 +113,10 @@ module ActiveSupport
|
|
111
113
|
def append_features(base)
|
112
114
|
if base.instance_variable_defined?(:@_dependencies)
|
113
115
|
base.instance_variable_get(:@_dependencies) << self
|
114
|
-
|
116
|
+
false
|
115
117
|
else
|
116
118
|
return false if base < self
|
117
|
-
@_dependencies.each { |dep| base.
|
119
|
+
@_dependencies.each { |dep| base.include(dep) }
|
118
120
|
super
|
119
121
|
base.extend const_get(:ClassMethods) if const_defined?(:ClassMethods)
|
120
122
|
base.class_eval(&@_included_block) if instance_variable_defined?(:@_included_block)
|
@@ -132,7 +134,7 @@ module ActiveSupport
|
|
132
134
|
end
|
133
135
|
|
134
136
|
def class_methods(&class_methods_module_definition)
|
135
|
-
mod = const_defined?(:ClassMethods) ?
|
137
|
+
mod = const_defined?(:ClassMethods, false) ?
|
136
138
|
const_get(:ClassMethods) :
|
137
139
|
const_set(:ClassMethods, Module.new)
|
138
140
|
|
@@ -0,0 +1,17 @@
|
|
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
|
+
# Enters an exclusive section, but allows dependency loading while blocked
|
11
|
+
def mon_enter
|
12
|
+
mon_try_enter ||
|
13
|
+
ActiveSupport::Dependencies.interlock.permit_concurrent_loads { super }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,227 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "thread"
|
4
|
+
require "monitor"
|
5
|
+
|
6
|
+
module ActiveSupport
|
7
|
+
module Concurrency
|
8
|
+
# A share/exclusive lock, otherwise known as a read/write lock.
|
9
|
+
#
|
10
|
+
# https://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock
|
11
|
+
class ShareLock
|
12
|
+
include MonitorMixin
|
13
|
+
|
14
|
+
# We track Thread objects, instead of just using counters, because
|
15
|
+
# we need exclusive locks to be reentrant, and we need to be able
|
16
|
+
# to upgrade share locks to exclusive.
|
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
|
49
|
+
|
50
|
+
def initialize
|
51
|
+
super()
|
52
|
+
|
53
|
+
@cv = new_cond
|
54
|
+
|
55
|
+
@sharing = Hash.new(0)
|
56
|
+
@waiting = {}
|
57
|
+
@sleeping = {}
|
58
|
+
@exclusive_thread = nil
|
59
|
+
@exclusive_depth = 0
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns false if +no_wait+ is set and the lock is not
|
63
|
+
# immediately available. Otherwise, returns true after the lock
|
64
|
+
# has been acquired.
|
65
|
+
#
|
66
|
+
# +purpose+ and +compatible+ work together; while this thread is
|
67
|
+
# waiting for the exclusive lock, it will yield its share (if any)
|
68
|
+
# to any other attempt whose +purpose+ appears in this attempt's
|
69
|
+
# +compatible+ list. This allows a "loose" upgrade, which, being
|
70
|
+
# less strict, prevents some classes of deadlocks.
|
71
|
+
#
|
72
|
+
# For many resources, loose upgrades are sufficient: if a thread
|
73
|
+
# is awaiting a lock, it is not running any other code. With
|
74
|
+
# +purpose+ matching, it is possible to yield only to other
|
75
|
+
# threads whose activity will not interfere.
|
76
|
+
def start_exclusive(purpose: nil, compatible: [], no_wait: false)
|
77
|
+
synchronize do
|
78
|
+
unless @exclusive_thread == Thread.current
|
79
|
+
if busy_for_exclusive?(purpose)
|
80
|
+
return false if no_wait
|
81
|
+
|
82
|
+
yield_shares(purpose: purpose, compatible: compatible, block_share: true) do
|
83
|
+
wait_for(:start_exclusive) { busy_for_exclusive?(purpose) }
|
84
|
+
end
|
85
|
+
end
|
86
|
+
@exclusive_thread = Thread.current
|
87
|
+
end
|
88
|
+
@exclusive_depth += 1
|
89
|
+
|
90
|
+
true
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# Relinquish the exclusive lock. Must only be called by the thread
|
95
|
+
# that called start_exclusive (and currently holds the lock).
|
96
|
+
def stop_exclusive(compatible: [])
|
97
|
+
synchronize do
|
98
|
+
raise "invalid unlock" if @exclusive_thread != Thread.current
|
99
|
+
|
100
|
+
@exclusive_depth -= 1
|
101
|
+
if @exclusive_depth == 0
|
102
|
+
@exclusive_thread = nil
|
103
|
+
|
104
|
+
if eligible_waiters?(compatible)
|
105
|
+
yield_shares(compatible: compatible, block_share: true) do
|
106
|
+
wait_for(:stop_exclusive) { @exclusive_thread || eligible_waiters?(compatible) }
|
107
|
+
end
|
108
|
+
end
|
109
|
+
@cv.broadcast
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def start_sharing
|
115
|
+
synchronize do
|
116
|
+
if @sharing[Thread.current] > 0 || @exclusive_thread == Thread.current
|
117
|
+
# We already hold a lock; nothing to wait for
|
118
|
+
elsif @waiting[Thread.current]
|
119
|
+
# We're nested inside a +yield_shares+ call: we'll resume as
|
120
|
+
# soon as there isn't an exclusive lock in our way
|
121
|
+
wait_for(:start_sharing) { @exclusive_thread }
|
122
|
+
else
|
123
|
+
# This is an initial / outermost share call: any outstanding
|
124
|
+
# requests for an exclusive lock get to go first
|
125
|
+
wait_for(:start_sharing) { busy_for_sharing?(false) }
|
126
|
+
end
|
127
|
+
@sharing[Thread.current] += 1
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def stop_sharing
|
132
|
+
synchronize do
|
133
|
+
if @sharing[Thread.current] > 1
|
134
|
+
@sharing[Thread.current] -= 1
|
135
|
+
else
|
136
|
+
@sharing.delete Thread.current
|
137
|
+
@cv.broadcast
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# Execute the supplied block while holding the Exclusive lock. If
|
143
|
+
# +no_wait+ is set and the lock is not immediately available,
|
144
|
+
# returns +nil+ without yielding. Otherwise, returns the result of
|
145
|
+
# the block.
|
146
|
+
#
|
147
|
+
# See +start_exclusive+ for other options.
|
148
|
+
def exclusive(purpose: nil, compatible: [], after_compatible: [], no_wait: false)
|
149
|
+
if start_exclusive(purpose: purpose, compatible: compatible, no_wait: no_wait)
|
150
|
+
begin
|
151
|
+
yield
|
152
|
+
ensure
|
153
|
+
stop_exclusive(compatible: after_compatible)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# Execute the supplied block while holding the Share lock.
|
159
|
+
def sharing
|
160
|
+
start_sharing
|
161
|
+
begin
|
162
|
+
yield
|
163
|
+
ensure
|
164
|
+
stop_sharing
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
# Temporarily give up all held Share locks while executing the
|
169
|
+
# supplied block, allowing any +compatible+ exclusive lock request
|
170
|
+
# to proceed.
|
171
|
+
def yield_shares(purpose: nil, compatible: [], block_share: false)
|
172
|
+
loose_shares = previous_wait = nil
|
173
|
+
synchronize do
|
174
|
+
if loose_shares = @sharing.delete(Thread.current)
|
175
|
+
if previous_wait = @waiting[Thread.current]
|
176
|
+
purpose = nil unless purpose == previous_wait[0]
|
177
|
+
compatible &= previous_wait[1]
|
178
|
+
end
|
179
|
+
compatible |= [false] unless block_share
|
180
|
+
@waiting[Thread.current] = [purpose, compatible]
|
181
|
+
end
|
182
|
+
|
183
|
+
@cv.broadcast
|
184
|
+
end
|
185
|
+
|
186
|
+
begin
|
187
|
+
yield
|
188
|
+
ensure
|
189
|
+
synchronize do
|
190
|
+
wait_for(:yield_shares) { @exclusive_thread && @exclusive_thread != Thread.current }
|
191
|
+
|
192
|
+
if previous_wait
|
193
|
+
@waiting[Thread.current] = previous_wait
|
194
|
+
else
|
195
|
+
@waiting.delete Thread.current
|
196
|
+
end
|
197
|
+
@sharing[Thread.current] = loose_shares if loose_shares
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
private
|
203
|
+
|
204
|
+
# Must be called within synchronize
|
205
|
+
def busy_for_exclusive?(purpose)
|
206
|
+
busy_for_sharing?(purpose) ||
|
207
|
+
@sharing.size > (@sharing[Thread.current] > 0 ? 1 : 0)
|
208
|
+
end
|
209
|
+
|
210
|
+
def busy_for_sharing?(purpose)
|
211
|
+
(@exclusive_thread && @exclusive_thread != Thread.current) ||
|
212
|
+
@waiting.any? { |t, (_, c)| t != Thread.current && !c.include?(purpose) }
|
213
|
+
end
|
214
|
+
|
215
|
+
def eligible_waiters?(compatible)
|
216
|
+
@waiting.any? { |t, (p, _)| compatible.include?(p) && @waiting.all? { |t2, (_, c2)| t == t2 || c2.include?(p) } }
|
217
|
+
end
|
218
|
+
|
219
|
+
def wait_for(method)
|
220
|
+
@sleeping[Thread.current] = method
|
221
|
+
@cv.wait_while { yield }
|
222
|
+
ensure
|
223
|
+
@sleeping.delete Thread.current
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
@@ -1,6 +1,9 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/concern"
|
4
|
+
require "active_support/ordered_options"
|
5
|
+
require "active_support/core_ext/array/extract_options"
|
6
|
+
require "active_support/core_ext/regexp"
|
4
7
|
|
5
8
|
module ActiveSupport
|
6
9
|
# Configurable provides a <tt>config</tt> method to store and retrieve
|
@@ -107,7 +110,7 @@ module ActiveSupport
|
|
107
110
|
options = names.extract_options!
|
108
111
|
|
109
112
|
names.each do |name|
|
110
|
-
raise NameError.new(
|
113
|
+
raise NameError.new("invalid config attribute name") unless /\A[_A-Za-z]\w*\z/.match?(name)
|
111
114
|
|
112
115
|
reader, reader_line = "def #{name}; config.#{name}; end", __LINE__
|
113
116
|
writer, writer_line = "def #{name}=(value); config.#{name} = value; end", __LINE__
|
@@ -122,6 +125,7 @@ module ActiveSupport
|
|
122
125
|
send("#{name}=", yield) if block_given?
|
123
126
|
end
|
124
127
|
end
|
128
|
+
private :config_accessor
|
125
129
|
end
|
126
130
|
|
127
131
|
# Reads and writes attributes from a configuration <tt>OrderedHash</tt>.
|
@@ -144,4 +148,3 @@ module ActiveSupport
|
|
144
148
|
end
|
145
149
|
end
|
146
150
|
end
|
147
|
-
|
@@ -1,6 +1,9 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
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_options"
|
7
|
+
require "active_support/core_ext/array/grouping"
|
8
|
+
require "active_support/core_ext/array/prepend_and_append"
|
9
|
+
require "active_support/core_ext/array/inquiry"
|
@@ -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
|
#
|
@@ -21,12 +23,24 @@ class Array
|
|
21
23
|
# %w( a b c ).to(-10) # => []
|
22
24
|
def to(position)
|
23
25
|
if position >= 0
|
24
|
-
|
26
|
+
take position + 1
|
25
27
|
else
|
26
28
|
self[0..position]
|
27
29
|
end
|
28
30
|
end
|
29
31
|
|
32
|
+
# Returns a copy of the Array without the specified elements.
|
33
|
+
#
|
34
|
+
# people = ["David", "Rafael", "Aaron", "Todd"]
|
35
|
+
# people.without "Aaron", "Todd"
|
36
|
+
# # => ["David", "Rafael"]
|
37
|
+
#
|
38
|
+
# Note: This is an optimization of <tt>Enumerable#without</tt> that uses <tt>Array#-</tt>
|
39
|
+
# instead of <tt>Array#reject</tt> for performance reasons.
|
40
|
+
def without(*elements)
|
41
|
+
self - elements
|
42
|
+
end
|
43
|
+
|
30
44
|
# Equal to <tt>self[1]</tt>.
|
31
45
|
#
|
32
46
|
# %w( a b c d e ).second # => "b"
|
@@ -61,4 +75,18 @@ class Array
|
|
61
75
|
def forty_two
|
62
76
|
self[41]
|
63
77
|
end
|
78
|
+
|
79
|
+
# Equal to <tt>self[-3]</tt>.
|
80
|
+
#
|
81
|
+
# %w( a b c d e ).third_to_last # => "c"
|
82
|
+
def third_to_last
|
83
|
+
self[-3]
|
84
|
+
end
|
85
|
+
|
86
|
+
# Equal to <tt>self[-2]</tt>.
|
87
|
+
#
|
88
|
+
# %w( a b c d e ).second_to_last # => "d"
|
89
|
+
def second_to_last
|
90
|
+
self[-2]
|
91
|
+
end
|
64
92
|
end
|
@@ -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
|
@@ -32,7 +34,7 @@ class Array
|
|
32
34
|
# ['one', 'two', 'three'].to_sentence # => "one, two, and three"
|
33
35
|
#
|
34
36
|
# ['one', 'two'].to_sentence(passing: 'invalid option')
|
35
|
-
# # => ArgumentError: Unknown key :passing
|
37
|
+
# # => ArgumentError: Unknown key: :passing. Valid keys are: :words_connector, :two_words_connector, :last_word_connector, :locale
|
36
38
|
#
|
37
39
|
# ['one', 'two'].to_sentence(two_words_connector: '-')
|
38
40
|
# # => "one-two"
|
@@ -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,9 +74,9 @@ 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
81
|
"#{self[0]}#{options[:two_words_connector]}#{self[1]}"
|
80
82
|
else
|
@@ -85,14 +87,16 @@ class Array
|
|
85
87
|
# Extends <tt>Array#to_s</tt> to convert a collection of elements into a
|
86
88
|
# comma separated id list if <tt>:db</tt> argument is given as the format.
|
87
89
|
#
|
88
|
-
# Blog.all.to_formatted_s(:db)
|
90
|
+
# Blog.all.to_formatted_s(:db) # => "1,2,3"
|
91
|
+
# Blog.none.to_formatted_s(:db) # => "null"
|
92
|
+
# [1,2].to_formatted_s # => "[1, 2]"
|
89
93
|
def to_formatted_s(format = :default)
|
90
94
|
case format
|
91
95
|
when :db
|
92
96
|
if empty?
|
93
|
-
|
97
|
+
"null"
|
94
98
|
else
|
95
|
-
collect
|
99
|
+
collect(&:id).join(",")
|
96
100
|
end
|
97
101
|
else
|
98
102
|
to_default_s
|
@@ -177,7 +181,7 @@ class Array
|
|
177
181
|
# </messages>
|
178
182
|
#
|
179
183
|
def to_xml(options = {})
|
180
|
-
require
|
184
|
+
require "active_support/builder" unless defined?(Builder)
|
181
185
|
|
182
186
|
options = options.dup
|
183
187
|
options[:indent] ||= 2
|
@@ -185,9 +189,9 @@ class Array
|
|
185
189
|
options[:root] ||= \
|
186
190
|
if first.class != Hash && all? { |e| e.is_a?(first.class) }
|
187
191
|
underscored = ActiveSupport::Inflector.underscore(first.class.name)
|
188
|
-
ActiveSupport::Inflector.pluralize(underscored).tr(
|
192
|
+
ActiveSupport::Inflector.pluralize(underscored).tr("/", "_")
|
189
193
|
else
|
190
|
-
|
194
|
+
"objects"
|
191
195
|
end
|
192
196
|
|
193
197
|
builder = options[:builder]
|
@@ -195,7 +199,7 @@ class Array
|
|
195
199
|
|
196
200
|
root = ActiveSupport::XmlMini.rename_key(options[:root].to_s, options)
|
197
201
|
children = options.delete(:children) || root.singularize
|
198
|
-
attributes = options[:skip_types] ? {} : { type:
|
202
|
+
attributes = options[:skip_types] ? {} : { type: "array" }
|
199
203
|
|
200
204
|
if empty?
|
201
205
|
builder.tag!(root, attributes)
|