activesupport 3.1.0 → 5.0.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 +7 -0
- data/CHANGELOG.md +798 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +13 -7
- data/lib/active_support/array_inquirer.rb +44 -0
- data/lib/active_support/backtrace_cleaner.rb +38 -34
- data/lib/active_support/benchmarkable.rb +17 -28
- data/lib/active_support/cache/file_store.rb +85 -70
- data/lib/active_support/cache/mem_cache_store.rb +75 -66
- data/lib/active_support/cache/memory_store.rb +31 -23
- data/lib/active_support/cache/null_store.rb +41 -0
- data/lib/active_support/cache/strategy/local_cache.rb +73 -70
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +44 -0
- data/lib/active_support/cache.rb +360 -294
- data/lib/active_support/callbacks.rb +563 -393
- data/lib/active_support/concern.rb +42 -34
- data/lib/active_support/concurrency/latch.rb +19 -0
- data/lib/active_support/concurrency/share_lock.rb +186 -0
- data/lib/active_support/configurable.rb +70 -12
- data/lib/active_support/core_ext/array/access.rb +53 -9
- data/lib/active_support/core_ext/array/conversions.rb +109 -62
- data/lib/active_support/core_ext/array/extract_options.rb +2 -2
- data/lib/active_support/core_ext/array/grouping.rb +39 -32
- data/lib/active_support/core_ext/array/inquiry.rb +17 -0
- data/lib/active_support/core_ext/array/prepend_and_append.rb +7 -0
- data/lib/active_support/core_ext/array/wrap.rb +16 -18
- data/lib/active_support/core_ext/array.rb +2 -2
- data/lib/active_support/core_ext/benchmark.rb +7 -0
- data/lib/active_support/core_ext/big_decimal/conversions.rb +8 -36
- data/lib/active_support/core_ext/class/attribute.rb +47 -34
- data/lib/active_support/core_ext/class/attribute_accessors.rb +4 -79
- data/lib/active_support/core_ext/class/subclasses.rb +12 -7
- data/lib/active_support/core_ext/class.rb +0 -3
- data/lib/active_support/core_ext/date/blank.rb +12 -0
- data/lib/active_support/core_ext/date/calculations.rb +57 -167
- data/lib/active_support/core_ext/date/conversions.rb +31 -42
- data/lib/active_support/core_ext/date/zones.rb +2 -10
- data/lib/active_support/core_ext/date.rb +5 -0
- data/lib/active_support/core_ext/date_and_time/calculations.rb +335 -0
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +18 -0
- data/lib/active_support/core_ext/date_and_time/zones.rb +40 -0
- data/lib/active_support/core_ext/date_time/acts_like.rb +1 -0
- data/lib/active_support/core_ext/date_time/blank.rb +12 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +132 -65
- data/lib/active_support/core_ext/date_time/compatibility.rb +5 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +36 -34
- data/lib/active_support/core_ext/date_time.rb +5 -0
- data/lib/active_support/core_ext/digest/uuid.rb +51 -0
- data/lib/active_support/core_ext/enumerable.rb +81 -74
- data/lib/active_support/core_ext/file/atomic.rb +53 -26
- data/lib/active_support/core_ext/file.rb +0 -1
- data/lib/active_support/core_ext/hash/compact.rb +20 -0
- data/lib/active_support/core_ext/hash/conversions.rb +175 -70
- data/lib/active_support/core_ext/hash/deep_merge.rb +30 -8
- data/lib/active_support/core_ext/hash/except.rb +11 -12
- data/lib/active_support/core_ext/hash/indifferent_access.rb +7 -8
- data/lib/active_support/core_ext/hash/keys.rb +147 -24
- data/lib/active_support/core_ext/hash/reverse_merge.rb +2 -3
- data/lib/active_support/core_ext/hash/slice.rb +22 -14
- data/lib/active_support/core_ext/hash/transform_values.rb +29 -0
- data/lib/active_support/core_ext/hash.rb +2 -2
- data/lib/active_support/core_ext/integer/inflections.rb +13 -1
- data/lib/active_support/core_ext/integer/multiple.rb +4 -0
- data/lib/active_support/core_ext/integer/time.rb +12 -22
- data/lib/active_support/core_ext/kernel/agnostics.rb +2 -2
- data/lib/active_support/core_ext/kernel/concern.rb +12 -0
- data/lib/active_support/core_ext/kernel/debugger.rb +2 -15
- data/lib/active_support/core_ext/kernel/reporting.rb +12 -62
- data/lib/active_support/core_ext/kernel/singleton_class.rb +0 -7
- data/lib/active_support/core_ext/kernel.rb +2 -3
- data/lib/active_support/core_ext/load_error.rb +14 -7
- data/lib/active_support/core_ext/marshal.rb +22 -0
- data/lib/active_support/core_ext/module/aliasing.rb +16 -12
- data/lib/active_support/core_ext/module/anonymous.rb +12 -8
- data/lib/active_support/core_ext/module/attr_internal.rb +2 -5
- data/lib/active_support/core_ext/module/attribute_accessors.rb +165 -13
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +141 -0
- data/lib/active_support/core_ext/module/concerning.rb +135 -0
- data/lib/active_support/core_ext/module/delegation.rb +141 -68
- data/lib/active_support/core_ext/module/deprecation.rb +17 -3
- data/lib/active_support/core_ext/module/introspection.rb +9 -31
- data/lib/active_support/core_ext/module/method_transplanting.rb +3 -0
- data/lib/active_support/core_ext/module/qualified_const.rb +70 -0
- data/lib/active_support/core_ext/module/reachable.rb +1 -3
- data/lib/active_support/core_ext/module/remove_method.rb +24 -5
- data/lib/active_support/core_ext/module.rb +3 -3
- data/lib/active_support/core_ext/name_error.rb +15 -2
- data/lib/active_support/core_ext/numeric/bytes.rb +20 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +145 -0
- data/lib/active_support/core_ext/numeric/inquiry.rb +26 -0
- data/lib/active_support/core_ext/numeric/time.rb +31 -36
- data/lib/active_support/core_ext/numeric.rb +2 -0
- data/lib/active_support/core_ext/object/acts_like.rb +4 -4
- data/lib/active_support/core_ext/object/blank.rb +52 -18
- data/lib/active_support/core_ext/object/deep_dup.rb +53 -0
- data/lib/active_support/core_ext/object/duplicable.rb +12 -20
- data/lib/active_support/core_ext/object/inclusion.rb +13 -1
- data/lib/active_support/core_ext/object/instance_variables.rb +7 -12
- data/lib/active_support/core_ext/object/json.rb +205 -0
- data/lib/active_support/core_ext/object/to_param.rb +1 -55
- data/lib/active_support/core_ext/object/to_query.rb +66 -9
- data/lib/active_support/core_ext/object/try.rb +124 -33
- data/lib/active_support/core_ext/object/with_options.rb +37 -11
- data/lib/active_support/core_ext/object.rb +2 -1
- data/lib/active_support/core_ext/range/conversions.rb +17 -7
- data/lib/active_support/core_ext/range/each.rb +21 -0
- data/lib/active_support/core_ext/range/include_range.rb +20 -18
- data/lib/active_support/core_ext/range/overlaps.rb +1 -1
- data/lib/active_support/core_ext/range.rb +1 -2
- data/lib/active_support/core_ext/securerandom.rb +23 -0
- data/lib/active_support/core_ext/string/access.rb +95 -90
- data/lib/active_support/core_ext/string/behavior.rb +1 -1
- data/lib/active_support/core_ext/string/conversions.rb +41 -38
- data/lib/active_support/core_ext/string/exclude.rb +6 -1
- data/lib/active_support/core_ext/string/filters.rb +70 -17
- data/lib/active_support/core_ext/string/indent.rb +43 -0
- data/lib/active_support/core_ext/string/inflections.rb +139 -59
- data/lib/active_support/core_ext/string/inquiry.rb +2 -2
- data/lib/active_support/core_ext/string/multibyte.rb +46 -65
- data/lib/active_support/core_ext/string/output_safety.rb +153 -56
- data/lib/active_support/core_ext/string/strip.rb +3 -6
- data/lib/active_support/core_ext/string/zones.rb +14 -0
- data/lib/active_support/core_ext/string.rb +2 -3
- data/lib/active_support/core_ext/struct.rb +3 -0
- data/lib/active_support/core_ext/time/calculations.rb +173 -173
- data/lib/active_support/core_ext/time/compatibility.rb +5 -0
- data/lib/active_support/core_ext/time/conversions.rb +33 -29
- data/lib/active_support/core_ext/time/marshal.rb +2 -56
- data/lib/active_support/core_ext/time/zones.rb +57 -32
- data/lib/active_support/core_ext/time.rb +5 -0
- data/lib/active_support/core_ext/uri.rb +13 -19
- data/lib/active_support/core_ext.rb +3 -2
- data/lib/active_support/dependencies/autoload.rb +47 -20
- data/lib/active_support/dependencies/interlock.rb +51 -0
- data/lib/active_support/dependencies.rb +315 -265
- data/lib/active_support/deprecation/behaviors.rb +71 -30
- data/lib/active_support/deprecation/instance_delegator.rb +24 -0
- data/lib/active_support/deprecation/method_wrappers.rb +59 -18
- data/lib/active_support/deprecation/proxy_wrappers.rb +82 -14
- data/lib/active_support/deprecation/reporting.rb +61 -14
- data/lib/active_support/deprecation.rb +38 -13
- data/lib/active_support/descendants_tracker.rb +34 -19
- data/lib/active_support/duration/iso8601_parser.rb +122 -0
- data/lib/active_support/duration/iso8601_serializer.rb +51 -0
- data/lib/active_support/duration.rb +85 -14
- data/lib/active_support/evented_file_update_checker.rb +194 -0
- data/lib/active_support/execution_wrapper.rb +117 -0
- data/lib/active_support/executor.rb +6 -0
- data/lib/active_support/file_update_checker.rb +138 -17
- data/lib/active_support/gem_version.rb +15 -0
- data/lib/active_support/gzip.rb +11 -5
- data/lib/active_support/hash_with_indifferent_access.rb +199 -49
- data/lib/active_support/i18n.rb +6 -2
- data/lib/active_support/i18n_railtie.rb +40 -21
- data/lib/active_support/inflections.rb +22 -13
- data/lib/active_support/inflector/inflections.rb +175 -144
- data/lib/active_support/inflector/methods.rb +328 -91
- data/lib/active_support/inflector/transliterate.rb +51 -37
- data/lib/active_support/json/decoding.rb +31 -22
- data/lib/active_support/json/encoding.rb +88 -248
- data/lib/active_support/key_generator.rb +71 -0
- data/lib/active_support/lazy_load_hooks.rb +27 -25
- data/lib/active_support/locale/en.yml +102 -3
- data/lib/active_support/log_subscriber/test_helper.rb +24 -21
- data/lib/active_support/log_subscriber.rb +36 -49
- data/lib/active_support/logger.rb +106 -0
- data/lib/active_support/logger_silence.rb +28 -0
- data/lib/active_support/logger_thread_safe_level.rb +31 -0
- data/lib/active_support/message_encryptor.rb +72 -36
- data/lib/active_support/message_verifier.rb +96 -24
- data/lib/active_support/multibyte/chars.rb +88 -333
- data/lib/active_support/multibyte/unicode.rb +156 -136
- data/lib/active_support/multibyte.rb +5 -28
- data/lib/active_support/notifications/fanout.rb +115 -19
- data/lib/active_support/notifications/instrumenter.rb +52 -15
- data/lib/active_support/notifications.rb +168 -33
- data/lib/active_support/number_helper/number_converter.rb +182 -0
- data/lib/active_support/number_helper/number_to_currency_converter.rb +44 -0
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +28 -0
- data/lib/active_support/number_helper/number_to_human_converter.rb +68 -0
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +62 -0
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +12 -0
- data/lib/active_support/number_helper/number_to_phone_converter.rb +58 -0
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +92 -0
- data/lib/active_support/number_helper.rb +368 -0
- data/lib/active_support/option_merger.rb +1 -1
- data/lib/active_support/ordered_hash.rb +18 -183
- data/lib/active_support/ordered_options.rb +44 -24
- data/lib/active_support/per_thread_registry.rb +58 -0
- data/lib/active_support/proxy_object.rb +13 -0
- data/lib/active_support/rails.rb +27 -0
- data/lib/active_support/railtie.rb +25 -34
- data/lib/active_support/reloader.rb +129 -0
- data/lib/active_support/rescuable.rb +98 -48
- data/lib/active_support/security_utils.rb +27 -0
- data/lib/active_support/string_inquirer.rb +14 -9
- data/lib/active_support/subscriber.rb +120 -0
- data/lib/active_support/tagged_logging.rb +78 -0
- data/lib/active_support/test_case.rb +69 -17
- data/lib/active_support/testing/assertions.rb +43 -41
- data/lib/active_support/testing/autorun.rb +12 -0
- data/lib/active_support/testing/constant_lookup.rb +50 -0
- data/lib/active_support/testing/declarative.rb +7 -21
- data/lib/active_support/testing/deprecation.rb +14 -33
- data/lib/active_support/testing/file_fixtures.rb +34 -0
- data/lib/active_support/testing/isolation.rb +53 -95
- data/lib/active_support/testing/method_call_assertions.rb +41 -0
- data/lib/active_support/testing/setup_and_teardown.rb +21 -82
- data/lib/active_support/testing/stream.rb +42 -0
- data/lib/active_support/testing/tagged_logging.rb +25 -0
- data/lib/active_support/testing/time_helpers.rb +134 -0
- data/lib/active_support/time.rb +6 -23
- data/lib/active_support/time_with_zone.rb +239 -92
- data/lib/active_support/values/time_zone.rb +236 -160
- data/lib/active_support/values/unicode_tables.dat +0 -0
- data/lib/active_support/version.rb +5 -7
- data/lib/active_support/xml_mini/jdom.rb +19 -13
- data/lib/active_support/xml_mini/libxml.rb +3 -4
- data/lib/active_support/xml_mini/libxmlsax.rb +2 -3
- data/lib/active_support/xml_mini/nokogiri.rb +3 -4
- data/lib/active_support/xml_mini/nokogirisax.rb +2 -3
- data/lib/active_support/xml_mini/rexml.rb +8 -10
- data/lib/active_support/xml_mini.rb +66 -34
- data/lib/active_support.rb +40 -23
- metadata +185 -134
- data/CHANGELOG +0 -1534
- data/lib/active_support/base64.rb +0 -42
- data/lib/active_support/basic_object.rb +0 -21
- data/lib/active_support/buffered_logger.rb +0 -137
- data/lib/active_support/cache/compressed_mem_cache_store.rb +0 -13
- data/lib/active_support/cache/synchronized_memory_store.rb +0 -11
- data/lib/active_support/core_ext/array/random_access.rb +0 -30
- data/lib/active_support/core_ext/array/uniq_by.rb +0 -16
- data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -44
- data/lib/active_support/core_ext/class/inheritable_attributes.rb +0 -178
- data/lib/active_support/core_ext/date/freeze.rb +0 -31
- data/lib/active_support/core_ext/date_time/zones.rb +0 -21
- data/lib/active_support/core_ext/exception.rb +0 -3
- data/lib/active_support/core_ext/file/path.rb +0 -5
- data/lib/active_support/core_ext/float/rounding.rb +0 -19
- data/lib/active_support/core_ext/float.rb +0 -1
- data/lib/active_support/core_ext/hash/deep_dup.rb +0 -11
- data/lib/active_support/core_ext/hash/diff.rb +0 -13
- data/lib/active_support/core_ext/kernel/requires.rb +0 -28
- data/lib/active_support/core_ext/logger.rb +0 -81
- data/lib/active_support/core_ext/module/attr_accessor_with_default.rb +0 -31
- data/lib/active_support/core_ext/module/method_names.rb +0 -14
- data/lib/active_support/core_ext/module/synchronization.rb +0 -43
- data/lib/active_support/core_ext/object/to_json.rb +0 -19
- data/lib/active_support/core_ext/proc.rb +0 -14
- data/lib/active_support/core_ext/process/daemon.rb +0 -23
- data/lib/active_support/core_ext/process.rb +0 -1
- data/lib/active_support/core_ext/range/blockless_step.rb +0 -29
- data/lib/active_support/core_ext/range/cover.rb +0 -3
- data/lib/active_support/core_ext/rexml.rb +0 -46
- data/lib/active_support/core_ext/string/encoding.rb +0 -11
- data/lib/active_support/core_ext/string/interpolation.rb +0 -2
- data/lib/active_support/core_ext/string/xchar.rb +0 -18
- data/lib/active_support/core_ext/time/publicize_conversion_methods.rb +0 -10
- data/lib/active_support/file_watcher.rb +0 -36
- data/lib/active_support/json/variable.rb +0 -9
- data/lib/active_support/memoizable.rb +0 -105
- data/lib/active_support/multibyte/exceptions.rb +0 -8
- data/lib/active_support/multibyte/utils.rb +0 -60
- data/lib/active_support/ruby/shim.rb +0 -22
- data/lib/active_support/secure_random.rb +0 -6
- data/lib/active_support/testing/mochaing.rb +0 -7
- data/lib/active_support/testing/pending.rb +0 -52
- data/lib/active_support/testing/performance/jruby.rb +0 -115
- data/lib/active_support/testing/performance/rubinius.rb +0 -113
- data/lib/active_support/testing/performance/ruby/mri.rb +0 -57
- data/lib/active_support/testing/performance/ruby/yarv.rb +0 -57
- data/lib/active_support/testing/performance/ruby.rb +0 -152
- data/lib/active_support/testing/performance.rb +0 -317
- data/lib/active_support/time/autoload.rb +0 -5
- data/lib/active_support/whiny_nil.rb +0 -60
@@ -4,20 +4,18 @@ module ActiveSupport
|
|
4
4
|
# module M
|
5
5
|
# def self.included(base)
|
6
6
|
# base.extend ClassMethods
|
7
|
-
# base.
|
8
|
-
#
|
7
|
+
# base.class_eval do
|
8
|
+
# scope :disabled, -> { where(disabled: true) }
|
9
|
+
# end
|
9
10
|
# end
|
10
11
|
#
|
11
12
|
# module ClassMethods
|
12
13
|
# ...
|
13
14
|
# end
|
14
|
-
#
|
15
|
-
# module InstanceMethods
|
16
|
-
# ...
|
17
|
-
# end
|
18
15
|
# end
|
19
16
|
#
|
20
|
-
# By using <tt>ActiveSupport::Concern</tt> the above module could instead be
|
17
|
+
# By using <tt>ActiveSupport::Concern</tt> the above module could instead be
|
18
|
+
# written as:
|
21
19
|
#
|
22
20
|
# require 'active_support/concern'
|
23
21
|
#
|
@@ -25,20 +23,17 @@ module ActiveSupport
|
|
25
23
|
# extend ActiveSupport::Concern
|
26
24
|
#
|
27
25
|
# included do
|
28
|
-
# scope :disabled, where(:
|
26
|
+
# scope :disabled, -> { where(disabled: true) }
|
29
27
|
# end
|
30
28
|
#
|
31
|
-
#
|
32
|
-
# ...
|
33
|
-
# end
|
34
|
-
#
|
35
|
-
# module InstanceMethods
|
29
|
+
# class_methods do
|
36
30
|
# ...
|
37
31
|
# end
|
38
32
|
# end
|
39
33
|
#
|
40
|
-
# Moreover, it gracefully handles module dependencies. Given a +Foo+ module
|
41
|
-
# module which depends on the former, we would typically write the
|
34
|
+
# Moreover, it gracefully handles module dependencies. Given a +Foo+ module
|
35
|
+
# and a +Bar+ module which depends on the former, we would typically write the
|
36
|
+
# following:
|
42
37
|
#
|
43
38
|
# module Foo
|
44
39
|
# def self.included(base)
|
@@ -61,11 +56,11 @@ module ActiveSupport
|
|
61
56
|
# include Bar # Bar is the module that Host really needs
|
62
57
|
# end
|
63
58
|
#
|
64
|
-
# But why should +Host+ care about +Bar+'s dependencies, namely +Foo+? We
|
65
|
-
# these from +Host+ directly including +Foo+ in +Bar+:
|
59
|
+
# But why should +Host+ care about +Bar+'s dependencies, namely +Foo+? We
|
60
|
+
# could try to hide these from +Host+ directly including +Foo+ in +Bar+:
|
66
61
|
#
|
67
62
|
# module Bar
|
68
|
-
# include Foo
|
63
|
+
# include Foo
|
69
64
|
# def self.included(base)
|
70
65
|
# base.method_injected_by_foo
|
71
66
|
# end
|
@@ -75,18 +70,17 @@ module ActiveSupport
|
|
75
70
|
# include Bar
|
76
71
|
# end
|
77
72
|
#
|
78
|
-
# Unfortunately this won't work, since when +Foo+ is included, its <tt>base</tt>
|
79
|
-
# not the +Host+ class. With <tt>ActiveSupport::Concern</tt>,
|
73
|
+
# Unfortunately this won't work, since when +Foo+ is included, its <tt>base</tt>
|
74
|
+
# is the +Bar+ module, not the +Host+ class. With <tt>ActiveSupport::Concern</tt>,
|
75
|
+
# module dependencies are properly resolved:
|
80
76
|
#
|
81
77
|
# require 'active_support/concern'
|
82
78
|
#
|
83
79
|
# module Foo
|
84
80
|
# extend ActiveSupport::Concern
|
85
81
|
# included do
|
86
|
-
#
|
87
|
-
#
|
88
|
-
# ...
|
89
|
-
# end
|
82
|
+
# def self.method_injected_by_foo
|
83
|
+
# ...
|
90
84
|
# end
|
91
85
|
# end
|
92
86
|
# end
|
@@ -101,34 +95,48 @@ module ActiveSupport
|
|
101
95
|
# end
|
102
96
|
#
|
103
97
|
# class Host
|
104
|
-
# include Bar # works, Bar takes care
|
98
|
+
# include Bar # It works, now Bar takes care of its dependencies
|
105
99
|
# end
|
106
|
-
#
|
107
100
|
module Concern
|
108
|
-
|
109
|
-
|
101
|
+
class MultipleIncludedBlocks < StandardError #:nodoc:
|
102
|
+
def initialize
|
103
|
+
super "Cannot define multiple 'included' blocks for a Concern"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def self.extended(base) #:nodoc:
|
108
|
+
base.instance_variable_set(:@_dependencies, [])
|
110
109
|
end
|
111
110
|
|
112
111
|
def append_features(base)
|
113
|
-
if base.instance_variable_defined?(
|
114
|
-
base.instance_variable_get(
|
112
|
+
if base.instance_variable_defined?(:@_dependencies)
|
113
|
+
base.instance_variable_get(:@_dependencies) << self
|
115
114
|
return false
|
116
115
|
else
|
117
116
|
return false if base < self
|
118
|
-
@_dependencies.each { |dep| base.
|
117
|
+
@_dependencies.each { |dep| base.include(dep) }
|
119
118
|
super
|
120
|
-
base.extend const_get(
|
121
|
-
base.
|
122
|
-
base.class_eval(&@_included_block) if instance_variable_defined?("@_included_block")
|
119
|
+
base.extend const_get(:ClassMethods) if const_defined?(:ClassMethods)
|
120
|
+
base.class_eval(&@_included_block) if instance_variable_defined?(:@_included_block)
|
123
121
|
end
|
124
122
|
end
|
125
123
|
|
126
124
|
def included(base = nil, &block)
|
127
125
|
if base.nil?
|
126
|
+
raise MultipleIncludedBlocks if instance_variable_defined?(:@_included_block)
|
127
|
+
|
128
128
|
@_included_block = block
|
129
129
|
else
|
130
130
|
super
|
131
131
|
end
|
132
132
|
end
|
133
|
+
|
134
|
+
def class_methods(&class_methods_module_definition)
|
135
|
+
mod = const_defined?(:ClassMethods, false) ?
|
136
|
+
const_get(:ClassMethods) :
|
137
|
+
const_set(:ClassMethods, Module.new)
|
138
|
+
|
139
|
+
mod.module_eval(&class_methods_module_definition)
|
140
|
+
end
|
133
141
|
end
|
134
142
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'concurrent/atomic/count_down_latch'
|
2
|
+
|
3
|
+
module ActiveSupport
|
4
|
+
module Concurrency
|
5
|
+
class Latch < Concurrent::CountDownLatch
|
6
|
+
|
7
|
+
def initialize(count = 1)
|
8
|
+
ActiveSupport::Deprecation.warn("ActiveSupport::Concurrency::Latch is deprecated. Please use Concurrent::CountDownLatch instead.")
|
9
|
+
super(count)
|
10
|
+
end
|
11
|
+
|
12
|
+
alias_method :release, :count_down
|
13
|
+
|
14
|
+
def await
|
15
|
+
wait(nil)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
require 'thread'
|
2
|
+
require 'monitor'
|
3
|
+
|
4
|
+
module ActiveSupport
|
5
|
+
module Concurrency
|
6
|
+
# A share/exclusive lock, otherwise known as a read/write lock.
|
7
|
+
#
|
8
|
+
# https://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock
|
9
|
+
class ShareLock
|
10
|
+
include MonitorMixin
|
11
|
+
|
12
|
+
# We track Thread objects, instead of just using counters, because
|
13
|
+
# we need exclusive locks to be reentrant, and we need to be able
|
14
|
+
# to upgrade share locks to exclusive.
|
15
|
+
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
super()
|
19
|
+
|
20
|
+
@cv = new_cond
|
21
|
+
|
22
|
+
@sharing = Hash.new(0)
|
23
|
+
@waiting = {}
|
24
|
+
@exclusive_thread = nil
|
25
|
+
@exclusive_depth = 0
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns false if +no_wait+ is set and the lock is not
|
29
|
+
# immediately available. Otherwise, returns true after the lock
|
30
|
+
# has been acquired.
|
31
|
+
#
|
32
|
+
# +purpose+ and +compatible+ work together; while this thread is
|
33
|
+
# waiting for the exclusive lock, it will yield its share (if any)
|
34
|
+
# to any other attempt whose +purpose+ appears in this attempt's
|
35
|
+
# +compatible+ list. This allows a "loose" upgrade, which, being
|
36
|
+
# less strict, prevents some classes of deadlocks.
|
37
|
+
#
|
38
|
+
# For many resources, loose upgrades are sufficient: if a thread
|
39
|
+
# is awaiting a lock, it is not running any other code. With
|
40
|
+
# +purpose+ matching, it is possible to yield only to other
|
41
|
+
# threads whose activity will not interfere.
|
42
|
+
def start_exclusive(purpose: nil, compatible: [], no_wait: false)
|
43
|
+
synchronize do
|
44
|
+
unless @exclusive_thread == Thread.current
|
45
|
+
if busy_for_exclusive?(purpose)
|
46
|
+
return false if no_wait
|
47
|
+
|
48
|
+
yield_shares(purpose: purpose, compatible: compatible, block_share: true) do
|
49
|
+
@cv.wait_while { busy_for_exclusive?(purpose) }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
@exclusive_thread = Thread.current
|
53
|
+
end
|
54
|
+
@exclusive_depth += 1
|
55
|
+
|
56
|
+
true
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Relinquish the exclusive lock. Must only be called by the thread
|
61
|
+
# that called start_exclusive (and currently holds the lock).
|
62
|
+
def stop_exclusive(compatible: [])
|
63
|
+
synchronize do
|
64
|
+
raise "invalid unlock" if @exclusive_thread != Thread.current
|
65
|
+
|
66
|
+
@exclusive_depth -= 1
|
67
|
+
if @exclusive_depth == 0
|
68
|
+
@exclusive_thread = nil
|
69
|
+
|
70
|
+
if eligible_waiters?(compatible)
|
71
|
+
yield_shares(compatible: compatible, block_share: true) do
|
72
|
+
@cv.wait_while { @exclusive_thread || eligible_waiters?(compatible) }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
@cv.broadcast
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def start_sharing
|
81
|
+
synchronize do
|
82
|
+
if @sharing[Thread.current] > 0 || @exclusive_thread == Thread.current
|
83
|
+
# We already hold a lock; nothing to wait for
|
84
|
+
elsif @waiting[Thread.current]
|
85
|
+
# We're nested inside a +yield_shares+ call: we'll resume as
|
86
|
+
# soon as there isn't an exclusive lock in our way
|
87
|
+
@cv.wait_while { @exclusive_thread }
|
88
|
+
else
|
89
|
+
# This is an initial / outermost share call: any outstanding
|
90
|
+
# requests for an exclusive lock get to go first
|
91
|
+
@cv.wait_while { busy_for_sharing?(false) }
|
92
|
+
end
|
93
|
+
@sharing[Thread.current] += 1
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def stop_sharing
|
98
|
+
synchronize do
|
99
|
+
if @sharing[Thread.current] > 1
|
100
|
+
@sharing[Thread.current] -= 1
|
101
|
+
else
|
102
|
+
@sharing.delete Thread.current
|
103
|
+
@cv.broadcast
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# Execute the supplied block while holding the Exclusive lock. If
|
109
|
+
# +no_wait+ is set and the lock is not immediately available,
|
110
|
+
# returns +nil+ without yielding. Otherwise, returns the result of
|
111
|
+
# the block.
|
112
|
+
#
|
113
|
+
# See +start_exclusive+ for other options.
|
114
|
+
def exclusive(purpose: nil, compatible: [], after_compatible: [], no_wait: false)
|
115
|
+
if start_exclusive(purpose: purpose, compatible: compatible, no_wait: no_wait)
|
116
|
+
begin
|
117
|
+
yield
|
118
|
+
ensure
|
119
|
+
stop_exclusive(compatible: after_compatible)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# Execute the supplied block while holding the Share lock.
|
125
|
+
def sharing
|
126
|
+
start_sharing
|
127
|
+
begin
|
128
|
+
yield
|
129
|
+
ensure
|
130
|
+
stop_sharing
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# Temporarily give up all held Share locks while executing the
|
135
|
+
# supplied block, allowing any +compatible+ exclusive lock request
|
136
|
+
# to proceed.
|
137
|
+
def yield_shares(purpose: nil, compatible: [], block_share: false)
|
138
|
+
loose_shares = previous_wait = nil
|
139
|
+
synchronize do
|
140
|
+
if loose_shares = @sharing.delete(Thread.current)
|
141
|
+
if previous_wait = @waiting[Thread.current]
|
142
|
+
purpose = nil unless purpose == previous_wait[0]
|
143
|
+
compatible &= previous_wait[1]
|
144
|
+
end
|
145
|
+
compatible |= [false] unless block_share
|
146
|
+
@waiting[Thread.current] = [purpose, compatible]
|
147
|
+
end
|
148
|
+
|
149
|
+
@cv.broadcast
|
150
|
+
end
|
151
|
+
|
152
|
+
begin
|
153
|
+
yield
|
154
|
+
ensure
|
155
|
+
synchronize do
|
156
|
+
@cv.wait_while { @exclusive_thread && @exclusive_thread != Thread.current }
|
157
|
+
|
158
|
+
if previous_wait
|
159
|
+
@waiting[Thread.current] = previous_wait
|
160
|
+
else
|
161
|
+
@waiting.delete Thread.current
|
162
|
+
end
|
163
|
+
@sharing[Thread.current] = loose_shares if loose_shares
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
private
|
169
|
+
|
170
|
+
# Must be called within synchronize
|
171
|
+
def busy_for_exclusive?(purpose)
|
172
|
+
busy_for_sharing?(purpose) ||
|
173
|
+
@sharing.size > (@sharing[Thread.current] > 0 ? 1 : 0)
|
174
|
+
end
|
175
|
+
|
176
|
+
def busy_for_sharing?(purpose)
|
177
|
+
(@exclusive_thread && @exclusive_thread != Thread.current) ||
|
178
|
+
@waiting.any? { |t, (_, c)| t != Thread.current && !c.include?(purpose) }
|
179
|
+
end
|
180
|
+
|
181
|
+
def eligible_waiters?(compatible)
|
182
|
+
@waiting.any? { |t, (p, _)| compatible.include?(p) && @waiting.all? { |t2, (_, c2)| t == t2 || c2.include?(p) } }
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
require 'active_support/concern'
|
2
2
|
require 'active_support/ordered_options'
|
3
|
-
require 'active_support/core_ext/kernel/singleton_class'
|
4
|
-
require 'active_support/core_ext/module/delegation'
|
5
3
|
require 'active_support/core_ext/array/extract_options'
|
6
4
|
|
7
5
|
module ActiveSupport
|
@@ -15,7 +13,7 @@ module ActiveSupport
|
|
15
13
|
self.class.compile_methods!(keys)
|
16
14
|
end
|
17
15
|
|
18
|
-
#
|
16
|
+
# Compiles reader methods so we don't have to go through method_missing.
|
19
17
|
def self.compile_methods!(keys)
|
20
18
|
keys.reject { |m| method_defined?(m) }.each do |key|
|
21
19
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
@@ -39,31 +37,92 @@ module ActiveSupport
|
|
39
37
|
yield config
|
40
38
|
end
|
41
39
|
|
42
|
-
# Allows you to add shortcut so that you don't have to refer to attribute
|
43
|
-
# Also look at the example for config to contrast.
|
40
|
+
# Allows you to add shortcut so that you don't have to refer to attribute
|
41
|
+
# through config. Also look at the example for config to contrast.
|
42
|
+
#
|
43
|
+
# Defines both class and instance config accessors.
|
44
44
|
#
|
45
45
|
# class User
|
46
46
|
# include ActiveSupport::Configurable
|
47
47
|
# config_accessor :allowed_access
|
48
48
|
# end
|
49
49
|
#
|
50
|
+
# User.allowed_access # => nil
|
51
|
+
# User.allowed_access = false
|
52
|
+
# User.allowed_access # => false
|
53
|
+
#
|
50
54
|
# user = User.new
|
55
|
+
# user.allowed_access # => false
|
51
56
|
# user.allowed_access = true
|
52
57
|
# user.allowed_access # => true
|
53
58
|
#
|
59
|
+
# User.allowed_access # => false
|
60
|
+
#
|
61
|
+
# The attribute name must be a valid method name in Ruby.
|
62
|
+
#
|
63
|
+
# class User
|
64
|
+
# include ActiveSupport::Configurable
|
65
|
+
# config_accessor :"1_Badname"
|
66
|
+
# end
|
67
|
+
# # => NameError: invalid config attribute name
|
68
|
+
#
|
69
|
+
# To opt out of the instance writer method, pass <tt>instance_writer: false</tt>.
|
70
|
+
# To opt out of the instance reader method, pass <tt>instance_reader: false</tt>.
|
71
|
+
#
|
72
|
+
# class User
|
73
|
+
# include ActiveSupport::Configurable
|
74
|
+
# config_accessor :allowed_access, instance_reader: false, instance_writer: false
|
75
|
+
# end
|
76
|
+
#
|
77
|
+
# User.allowed_access = false
|
78
|
+
# User.allowed_access # => false
|
79
|
+
#
|
80
|
+
# User.new.allowed_access = true # => NoMethodError
|
81
|
+
# User.new.allowed_access # => NoMethodError
|
82
|
+
#
|
83
|
+
# Or pass <tt>instance_accessor: false</tt>, to opt out both instance methods.
|
84
|
+
#
|
85
|
+
# class User
|
86
|
+
# include ActiveSupport::Configurable
|
87
|
+
# config_accessor :allowed_access, instance_accessor: false
|
88
|
+
# end
|
89
|
+
#
|
90
|
+
# User.allowed_access = false
|
91
|
+
# User.allowed_access # => false
|
92
|
+
#
|
93
|
+
# User.new.allowed_access = true # => NoMethodError
|
94
|
+
# User.new.allowed_access # => NoMethodError
|
95
|
+
#
|
96
|
+
# Also you can pass a block to set up the attribute with a default value.
|
97
|
+
#
|
98
|
+
# class User
|
99
|
+
# include ActiveSupport::Configurable
|
100
|
+
# config_accessor :hair_colors do
|
101
|
+
# [:brown, :black, :blonde, :red]
|
102
|
+
# end
|
103
|
+
# end
|
104
|
+
#
|
105
|
+
# User.hair_colors # => [:brown, :black, :blonde, :red]
|
54
106
|
def config_accessor(*names)
|
55
107
|
options = names.extract_options!
|
56
108
|
|
57
109
|
names.each do |name|
|
58
|
-
|
59
|
-
writer, line = "def #{name}=(value); config.#{name} = value; end", __LINE__
|
110
|
+
raise NameError.new('invalid config attribute name') unless name =~ /\A[_A-Za-z]\w*\z/
|
60
111
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
class_eval
|
112
|
+
reader, reader_line = "def #{name}; config.#{name}; end", __LINE__
|
113
|
+
writer, writer_line = "def #{name}=(value); config.#{name} = value; end", __LINE__
|
114
|
+
|
115
|
+
singleton_class.class_eval reader, __FILE__, reader_line
|
116
|
+
singleton_class.class_eval writer, __FILE__, writer_line
|
117
|
+
|
118
|
+
unless options[:instance_accessor] == false
|
119
|
+
class_eval reader, __FILE__, reader_line unless options[:instance_reader] == false
|
120
|
+
class_eval writer, __FILE__, writer_line unless options[:instance_writer] == false
|
121
|
+
end
|
122
|
+
send("#{name}=", yield) if block_given?
|
65
123
|
end
|
66
124
|
end
|
125
|
+
private :config_accessor
|
67
126
|
end
|
68
127
|
|
69
128
|
# Reads and writes attributes from a configuration <tt>OrderedHash</tt>.
|
@@ -81,7 +140,6 @@ module ActiveSupport
|
|
81
140
|
#
|
82
141
|
# user.config.allowed_access # => true
|
83
142
|
# user.config.level # => 1
|
84
|
-
#
|
85
143
|
def config
|
86
144
|
@_config ||= self.class.config.inheritable_copy
|
87
145
|
end
|
@@ -1,46 +1,90 @@
|
|
1
1
|
class Array
|
2
2
|
# Returns the tail of the array from +position+.
|
3
3
|
#
|
4
|
-
# %w( a b c d ).from(0) # =>
|
5
|
-
# %w( a b c d ).from(2) # =>
|
6
|
-
# %w( a b c d ).from(10) # =>
|
7
|
-
# %w().from(0) # =>
|
4
|
+
# %w( a b c d ).from(0) # => ["a", "b", "c", "d"]
|
5
|
+
# %w( a b c d ).from(2) # => ["c", "d"]
|
6
|
+
# %w( a b c d ).from(10) # => []
|
7
|
+
# %w().from(0) # => []
|
8
|
+
# %w( a b c d ).from(-2) # => ["c", "d"]
|
9
|
+
# %w( a b c ).from(-10) # => []
|
8
10
|
def from(position)
|
9
11
|
self[position, length] || []
|
10
12
|
end
|
11
13
|
|
12
14
|
# Returns the beginning of the array up to +position+.
|
13
15
|
#
|
14
|
-
# %w( a b c d ).to(0) # =>
|
15
|
-
# %w( a b c d ).to(2) # =>
|
16
|
-
# %w( a b c d ).to(10) # =>
|
17
|
-
# %w().to(0) # =>
|
16
|
+
# %w( a b c d ).to(0) # => ["a"]
|
17
|
+
# %w( a b c d ).to(2) # => ["a", "b", "c"]
|
18
|
+
# %w( a b c d ).to(10) # => ["a", "b", "c", "d"]
|
19
|
+
# %w().to(0) # => []
|
20
|
+
# %w( a b c d ).to(-2) # => ["a", "b", "c"]
|
21
|
+
# %w( a b c ).to(-10) # => []
|
18
22
|
def to(position)
|
19
|
-
|
23
|
+
if position >= 0
|
24
|
+
take position + 1
|
25
|
+
else
|
26
|
+
self[0..position]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns a copy of the Array without the specified elements.
|
31
|
+
#
|
32
|
+
# people = ["David", "Rafael", "Aaron", "Todd"]
|
33
|
+
# people.without "Aaron", "Todd"
|
34
|
+
# => ["David", "Rafael"]
|
35
|
+
#
|
36
|
+
# Note: This is an optimization of `Enumerable#without` that uses `Array#-`
|
37
|
+
# instead of `Array#reject` for performance reasons.
|
38
|
+
def without(*elements)
|
39
|
+
self - elements
|
20
40
|
end
|
21
41
|
|
22
42
|
# Equal to <tt>self[1]</tt>.
|
43
|
+
#
|
44
|
+
# %w( a b c d e ).second # => "b"
|
23
45
|
def second
|
24
46
|
self[1]
|
25
47
|
end
|
26
48
|
|
27
49
|
# Equal to <tt>self[2]</tt>.
|
50
|
+
#
|
51
|
+
# %w( a b c d e ).third # => "c"
|
28
52
|
def third
|
29
53
|
self[2]
|
30
54
|
end
|
31
55
|
|
32
56
|
# Equal to <tt>self[3]</tt>.
|
57
|
+
#
|
58
|
+
# %w( a b c d e ).fourth # => "d"
|
33
59
|
def fourth
|
34
60
|
self[3]
|
35
61
|
end
|
36
62
|
|
37
63
|
# Equal to <tt>self[4]</tt>.
|
64
|
+
#
|
65
|
+
# %w( a b c d e ).fifth # => "e"
|
38
66
|
def fifth
|
39
67
|
self[4]
|
40
68
|
end
|
41
69
|
|
42
70
|
# Equal to <tt>self[41]</tt>. Also known as accessing "the reddit".
|
71
|
+
#
|
72
|
+
# (1..42).to_a.forty_two # => 42
|
43
73
|
def forty_two
|
44
74
|
self[41]
|
45
75
|
end
|
76
|
+
|
77
|
+
# Equal to <tt>self[-3]</tt>.
|
78
|
+
#
|
79
|
+
# %w( a b c d e ).third_to_last # => "c"
|
80
|
+
def third_to_last
|
81
|
+
self[-3]
|
82
|
+
end
|
83
|
+
|
84
|
+
# Equal to <tt>self[-2]</tt>.
|
85
|
+
#
|
86
|
+
# %w( a b c d e ).second_to_last # => "d"
|
87
|
+
def second_to_last
|
88
|
+
self[-2]
|
89
|
+
end
|
46
90
|
end
|