activesupport 1.2.4 → 8.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +505 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +40 -0
- data/lib/active_support/actionable_error.rb +50 -0
- data/lib/active_support/all.rb +5 -0
- data/lib/active_support/array_inquirer.rb +50 -0
- data/lib/active_support/backtrace_cleaner.rb +234 -0
- data/lib/active_support/benchmark.rb +21 -0
- data/lib/active_support/benchmarkable.rb +53 -0
- data/lib/active_support/broadcast_logger.rb +238 -0
- data/lib/active_support/builder.rb +8 -0
- data/lib/active_support/cache/coder.rb +153 -0
- data/lib/active_support/cache/entry.rb +134 -0
- data/lib/active_support/cache/file_store.rb +244 -0
- data/lib/active_support/cache/mem_cache_store.rb +288 -0
- data/lib/active_support/cache/memory_store.rb +264 -0
- data/lib/active_support/cache/null_store.rb +62 -0
- data/lib/active_support/cache/redis_cache_store.rb +498 -0
- data/lib/active_support/cache/serializer_with_fallback.rb +152 -0
- data/lib/active_support/cache/strategy/local_cache.rb +246 -0
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +45 -0
- data/lib/active_support/cache.rb +1170 -0
- data/lib/active_support/callbacks.rb +960 -0
- data/lib/active_support/class_attribute.rb +33 -0
- data/lib/active_support/code_generator.rb +79 -0
- data/lib/active_support/concern.rb +217 -0
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +18 -0
- data/lib/active_support/concurrency/null_lock.rb +13 -0
- data/lib/active_support/concurrency/share_lock.rb +225 -0
- data/lib/active_support/concurrency/thread_monitor.rb +55 -0
- data/lib/active_support/configurable.rb +193 -0
- data/lib/active_support/configuration_file.rb +60 -0
- data/lib/active_support/continuous_integration.rb +145 -0
- data/lib/active_support/core_ext/array/access.rb +100 -0
- data/lib/active_support/core_ext/array/conversions.rb +209 -26
- data/lib/active_support/core_ext/array/extract.rb +21 -0
- data/lib/active_support/core_ext/array/extract_options.rb +31 -0
- data/lib/active_support/core_ext/array/grouping.rb +109 -0
- data/lib/active_support/core_ext/array/inquiry.rb +19 -0
- data/lib/active_support/core_ext/array/wrap.rb +48 -0
- data/lib/active_support/core_ext/array.rb +8 -4
- data/lib/active_support/core_ext/benchmark.rb +6 -0
- data/lib/active_support/core_ext/big_decimal/conversions.rb +14 -0
- data/lib/active_support/core_ext/big_decimal.rb +3 -0
- data/lib/active_support/core_ext/class/attribute.rb +137 -0
- data/lib/active_support/core_ext/class/attribute_accessors.rb +6 -0
- data/lib/active_support/core_ext/class/subclasses.rb +24 -0
- data/lib/active_support/core_ext/class.rb +4 -0
- data/lib/active_support/core_ext/date/acts_like.rb +10 -0
- data/lib/active_support/core_ext/date/blank.rb +18 -0
- data/lib/active_support/core_ext/date/calculations.rb +161 -0
- data/lib/active_support/core_ext/date/conversions.rb +95 -28
- data/lib/active_support/core_ext/date/zones.rb +8 -0
- data/lib/active_support/core_ext/date.rb +6 -5
- data/lib/active_support/core_ext/date_and_time/calculations.rb +374 -0
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +23 -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 +16 -0
- data/lib/active_support/core_ext/date_time/blank.rb +18 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +215 -0
- data/lib/active_support/core_ext/date_time/compatibility.rb +16 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +108 -0
- data/lib/active_support/core_ext/date_time.rb +7 -0
- data/lib/active_support/core_ext/digest/uuid.rb +76 -0
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/enumerable.rb +277 -7
- data/lib/active_support/core_ext/erb/util.rb +201 -0
- data/lib/active_support/core_ext/file/atomic.rb +72 -0
- data/lib/active_support/core_ext/file.rb +3 -0
- data/lib/active_support/core_ext/hash/conversions.rb +262 -0
- data/lib/active_support/core_ext/hash/deep_merge.rb +43 -0
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
- data/lib/active_support/core_ext/hash/except.rb +12 -0
- data/lib/active_support/core_ext/hash/indifferent_access.rb +19 -55
- data/lib/active_support/core_ext/hash/keys.rb +134 -44
- data/lib/active_support/core_ext/hash/reverse_merge.rb +22 -22
- data/lib/active_support/core_ext/hash/slice.rb +27 -0
- data/lib/active_support/core_ext/hash.rb +9 -8
- data/lib/active_support/core_ext/integer/inflections.rb +29 -13
- data/lib/active_support/core_ext/integer/multiple.rb +12 -0
- data/lib/active_support/core_ext/integer/time.rb +22 -0
- data/lib/active_support/core_ext/integer.rb +4 -6
- data/lib/active_support/core_ext/kernel/concern.rb +14 -0
- data/lib/active_support/core_ext/kernel/reporting.rb +45 -0
- data/lib/active_support/core_ext/kernel/singleton_class.rb +8 -0
- data/lib/active_support/core_ext/kernel.rb +4 -78
- data/lib/active_support/core_ext/load_error.rb +6 -35
- data/lib/active_support/core_ext/module/aliasing.rb +31 -0
- data/lib/active_support/core_ext/module/anonymous.rb +30 -0
- data/lib/active_support/core_ext/module/attr_internal.rb +48 -0
- data/lib/active_support/core_ext/module/attribute_accessors.rb +214 -0
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +175 -0
- data/lib/active_support/core_ext/module/concerning.rb +140 -0
- data/lib/active_support/core_ext/module/delegation.rb +225 -0
- data/lib/active_support/core_ext/module/deprecation.rb +25 -0
- data/lib/active_support/core_ext/module/introspection.rb +65 -0
- data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
- data/lib/active_support/core_ext/module/remove_method.rb +17 -0
- data/lib/active_support/core_ext/module.rb +13 -0
- data/lib/active_support/core_ext/name_error.rb +59 -0
- data/lib/active_support/core_ext/numeric/bytes.rb +73 -42
- data/lib/active_support/core_ext/numeric/conversions.rb +145 -0
- data/lib/active_support/core_ext/numeric/time.rb +64 -57
- data/lib/active_support/core_ext/numeric.rb +4 -6
- data/lib/active_support/core_ext/object/acts_like.rb +45 -0
- data/lib/active_support/core_ext/object/blank.rb +199 -0
- data/lib/active_support/core_ext/object/conversions.rb +6 -0
- data/lib/active_support/core_ext/object/deep_dup.rb +71 -0
- data/lib/active_support/core_ext/object/duplicable.rb +69 -0
- data/lib/active_support/core_ext/object/inclusion.rb +37 -0
- data/lib/active_support/core_ext/object/instance_variables.rb +32 -0
- data/lib/active_support/core_ext/object/json.rb +267 -0
- data/lib/active_support/core_ext/object/to_param.rb +3 -0
- data/lib/active_support/core_ext/object/to_query.rb +93 -0
- data/lib/active_support/core_ext/object/try.rb +158 -0
- data/lib/active_support/core_ext/object/with.rb +46 -0
- data/lib/active_support/core_ext/object/with_options.rb +101 -0
- data/lib/active_support/core_ext/object.rb +17 -0
- data/lib/active_support/core_ext/pathname/blank.rb +20 -0
- data/lib/active_support/core_ext/pathname/existence.rb +23 -0
- data/lib/active_support/core_ext/pathname.rb +4 -0
- data/lib/active_support/core_ext/range/compare_range.rb +57 -0
- data/lib/active_support/core_ext/range/conversions.rb +58 -17
- data/lib/active_support/core_ext/range/overlap.rb +40 -0
- data/lib/active_support/core_ext/range/sole.rb +17 -0
- data/lib/active_support/core_ext/range.rb +5 -4
- data/lib/active_support/core_ext/regexp.rb +14 -0
- data/lib/active_support/core_ext/securerandom.rb +57 -0
- data/lib/active_support/core_ext/string/access.rb +93 -56
- data/lib/active_support/core_ext/string/behavior.rb +8 -0
- data/lib/active_support/core_ext/string/conversions.rb +57 -16
- data/lib/active_support/core_ext/string/exclude.rb +13 -0
- data/lib/active_support/core_ext/string/filters.rb +151 -0
- data/lib/active_support/core_ext/string/indent.rb +45 -0
- data/lib/active_support/core_ext/string/inflections.rb +297 -54
- data/lib/active_support/core_ext/string/inquiry.rb +16 -0
- data/lib/active_support/core_ext/string/multibyte.rb +67 -0
- data/lib/active_support/core_ext/string/output_safety.rb +235 -0
- data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -18
- data/lib/active_support/core_ext/string/strip.rb +27 -0
- data/lib/active_support/core_ext/string/zones.rb +16 -0
- data/lib/active_support/core_ext/string.rb +14 -10
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +6 -0
- data/lib/active_support/core_ext/symbol.rb +3 -0
- data/lib/active_support/core_ext/thread/backtrace/location.rb +7 -0
- data/lib/active_support/core_ext/time/acts_like.rb +10 -0
- data/lib/active_support/core_ext/time/calculations.rb +358 -153
- data/lib/active_support/core_ext/time/compatibility.rb +15 -0
- data/lib/active_support/core_ext/time/conversions.rb +69 -30
- data/lib/active_support/core_ext/time/zones.rb +97 -0
- data/lib/active_support/core_ext/time.rb +6 -6
- data/lib/active_support/core_ext.rb +5 -1
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/current_attributes.rb +243 -0
- data/lib/active_support/deep_mergeable.rb +53 -0
- data/lib/active_support/delegation.rb +183 -0
- data/lib/active_support/dependencies/autoload.rb +72 -0
- data/lib/active_support/dependencies/interlock.rb +55 -0
- data/lib/active_support/dependencies/require_dependency.rb +28 -0
- data/lib/active_support/dependencies.rb +84 -222
- data/lib/active_support/deprecation/behaviors.rb +148 -0
- data/lib/active_support/deprecation/constant_accessor.rb +74 -0
- data/lib/active_support/deprecation/deprecators.rb +104 -0
- data/lib/active_support/deprecation/disallowed.rb +54 -0
- data/lib/active_support/deprecation/method_wrappers.rb +68 -0
- data/lib/active_support/deprecation/proxy_wrappers.rb +189 -0
- data/lib/active_support/deprecation/reporting.rb +162 -0
- data/lib/active_support/deprecation.rb +81 -0
- data/lib/active_support/deprecator.rb +7 -0
- data/lib/active_support/descendants_tracker.rb +112 -0
- data/lib/active_support/digest.rb +22 -0
- data/lib/active_support/duration/iso8601_parser.rb +123 -0
- data/lib/active_support/duration/iso8601_serializer.rb +64 -0
- data/lib/active_support/duration.rb +524 -0
- data/lib/active_support/editor.rb +70 -0
- data/lib/active_support/encrypted_configuration.rb +126 -0
- data/lib/active_support/encrypted_file.rb +133 -0
- data/lib/active_support/environment_inquirer.rb +40 -0
- data/lib/active_support/error_reporter/test_helper.rb +15 -0
- data/lib/active_support/error_reporter.rb +318 -0
- data/lib/active_support/event_reporter/test_helper.rb +32 -0
- data/lib/active_support/event_reporter.rb +592 -0
- data/lib/active_support/evented_file_update_checker.rb +185 -0
- data/lib/active_support/execution_context/test_helper.rb +13 -0
- data/lib/active_support/execution_context.rb +110 -0
- data/lib/active_support/execution_wrapper.rb +150 -0
- data/lib/active_support/executor/test_helper.rb +7 -0
- data/lib/active_support/executor.rb +8 -0
- data/lib/active_support/file_update_checker.rb +166 -0
- data/lib/active_support/fork_tracker.rb +43 -0
- data/lib/active_support/gem_version.rb +17 -0
- data/lib/active_support/gzip.rb +41 -0
- data/lib/active_support/hash_with_indifferent_access.rb +464 -0
- data/lib/active_support/html_safe_translation.rb +56 -0
- data/lib/active_support/i18n.rb +17 -0
- data/lib/active_support/i18n_railtie.rb +140 -0
- data/lib/active_support/inflections.rb +68 -49
- data/lib/active_support/inflector/inflections.rb +290 -0
- data/lib/active_support/inflector/methods.rb +387 -0
- data/lib/active_support/inflector/transliterate.rb +147 -0
- data/lib/active_support/inflector.rb +7 -164
- data/lib/active_support/isolated_execution_state.rb +76 -0
- data/lib/active_support/json/decoding.rb +78 -0
- data/lib/active_support/json/encoding.rb +256 -0
- data/lib/active_support/json.rb +4 -0
- data/lib/active_support/key_generator.rb +66 -0
- data/lib/active_support/lazy_load_hooks.rb +107 -0
- data/lib/active_support/locale/en.rb +33 -0
- data/lib/active_support/locale/en.yml +141 -0
- data/lib/active_support/log_subscriber/test_helper.rb +106 -0
- data/lib/active_support/log_subscriber.rb +188 -0
- data/lib/active_support/logger.rb +55 -0
- data/lib/active_support/logger_silence.rb +21 -0
- data/lib/active_support/logger_thread_safe_level.rb +50 -0
- data/lib/active_support/message_encryptor.rb +374 -0
- data/lib/active_support/message_encryptors.rb +193 -0
- data/lib/active_support/message_pack/cache_serializer.rb +23 -0
- data/lib/active_support/message_pack/extensions.rb +310 -0
- data/lib/active_support/message_pack/serializer.rb +63 -0
- data/lib/active_support/message_pack.rb +50 -0
- data/lib/active_support/message_verifier.rb +377 -0
- data/lib/active_support/message_verifiers.rb +189 -0
- data/lib/active_support/messages/codec.rb +65 -0
- data/lib/active_support/messages/metadata.rb +146 -0
- data/lib/active_support/messages/rotation_configuration.rb +23 -0
- data/lib/active_support/messages/rotation_coordinator.rb +102 -0
- data/lib/active_support/messages/rotator.rb +69 -0
- data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
- data/lib/active_support/multibyte/chars.rb +188 -0
- data/lib/active_support/multibyte/unicode.rb +42 -0
- data/lib/active_support/multibyte.rb +27 -0
- data/lib/active_support/notifications/fanout.rb +467 -0
- data/lib/active_support/notifications/instrumenter.rb +240 -0
- data/lib/active_support/notifications.rb +281 -0
- data/lib/active_support/number_helper/number_converter.rb +190 -0
- data/lib/active_support/number_helper/number_to_currency_converter.rb +46 -0
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +30 -0
- data/lib/active_support/number_helper/number_to_human_converter.rb +69 -0
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +60 -0
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +16 -0
- data/lib/active_support/number_helper/number_to_phone_converter.rb +60 -0
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +59 -0
- data/lib/active_support/number_helper/rounding_helper.rb +46 -0
- data/lib/active_support/number_helper.rb +479 -0
- data/lib/active_support/option_merger.rb +38 -0
- data/lib/active_support/ordered_hash.rb +50 -0
- data/lib/active_support/ordered_options.rb +141 -25
- data/lib/active_support/parameter_filter.rb +157 -0
- data/lib/active_support/rails.rb +26 -0
- data/lib/active_support/railtie.rb +180 -0
- data/lib/active_support/reloader.rb +138 -0
- data/lib/active_support/rescuable.rb +176 -0
- data/lib/active_support/secure_compare_rotator.rb +58 -0
- data/lib/active_support/security_utils.rb +38 -0
- data/lib/active_support/string_inquirer.rb +35 -0
- data/lib/active_support/structured_event_subscriber.rb +99 -0
- data/lib/active_support/subscriber.rb +141 -0
- data/lib/active_support/syntax_error_proxy.rb +67 -0
- data/lib/active_support/tagged_logging.rb +157 -0
- data/lib/active_support/test_case.rb +365 -0
- data/lib/active_support/testing/assertions.rb +369 -0
- data/lib/active_support/testing/autorun.rb +10 -0
- data/lib/active_support/testing/constant_lookup.rb +51 -0
- data/lib/active_support/testing/constant_stubbing.rb +54 -0
- data/lib/active_support/testing/declarative.rb +28 -0
- data/lib/active_support/testing/deprecation.rb +82 -0
- data/lib/active_support/testing/error_reporter_assertions.rb +124 -0
- data/lib/active_support/testing/event_reporter_assertions.rb +227 -0
- data/lib/active_support/testing/file_fixtures.rb +38 -0
- data/lib/active_support/testing/isolation.rb +121 -0
- data/lib/active_support/testing/method_call_assertions.rb +69 -0
- data/lib/active_support/testing/notification_assertions.rb +92 -0
- data/lib/active_support/testing/parallelization/server.rb +98 -0
- data/lib/active_support/testing/parallelization/worker.rb +107 -0
- data/lib/active_support/testing/parallelization.rb +79 -0
- data/lib/active_support/testing/parallelize_executor.rb +81 -0
- data/lib/active_support/testing/setup_and_teardown.rb +57 -0
- data/lib/active_support/testing/stream.rb +41 -0
- data/lib/active_support/testing/tagged_logging.rb +27 -0
- data/lib/active_support/testing/tests_without_assertions.rb +19 -0
- data/lib/active_support/testing/time_helpers.rb +273 -0
- data/lib/active_support/time.rb +20 -0
- data/lib/active_support/time_with_zone.rb +613 -0
- data/lib/active_support/values/time_zone.rb +599 -158
- data/lib/active_support/version.rb +7 -6
- data/lib/active_support/xml_mini/jdom.rb +175 -0
- data/lib/active_support/xml_mini/libxml.rb +80 -0
- data/lib/active_support/xml_mini/libxmlsax.rb +83 -0
- data/lib/active_support/xml_mini/nokogiri.rb +83 -0
- data/lib/active_support/xml_mini/nokogirisax.rb +86 -0
- data/lib/active_support/xml_mini/rexml.rb +137 -0
- data/lib/active_support/xml_mini.rb +212 -0
- data/lib/active_support.rb +122 -10
- metadata +524 -93
- data/CHANGELOG +0 -283
- data/lib/active_support/binding_of_caller.rb +0 -84
- data/lib/active_support/breakpoint.rb +0 -523
- data/lib/active_support/class_attribute_accessors.rb +0 -57
- data/lib/active_support/class_inheritable_attributes.rb +0 -117
- data/lib/active_support/clean_logger.rb +0 -36
- data/lib/active_support/core_ext/blank.rb +0 -38
- data/lib/active_support/core_ext/cgi/escape_skipping_slashes.rb +0 -14
- data/lib/active_support/core_ext/cgi.rb +0 -5
- data/lib/active_support/core_ext/exception.rb +0 -29
- data/lib/active_support/core_ext/integer/even_odd.rb +0 -24
- data/lib/active_support/core_ext/object_and_class.rb +0 -44
- data/lib/active_support/module_attribute_accessors.rb +0 -57
- data/lib/active_support/whiny_nil.rb +0 -38
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
gem "listen", "~> 3.5"
|
|
4
|
+
require "listen"
|
|
5
|
+
|
|
6
|
+
require "pathname"
|
|
7
|
+
require "concurrent/atomic/atomic_boolean"
|
|
8
|
+
|
|
9
|
+
module ActiveSupport
|
|
10
|
+
# Allows you to "listen" to changes in a file system.
|
|
11
|
+
# The evented file updater does not hit disk when checking for updates.
|
|
12
|
+
# Instead, it uses platform-specific file system events to trigger a change
|
|
13
|
+
# in state.
|
|
14
|
+
#
|
|
15
|
+
# The file checker takes an array of files to watch or a hash specifying directories
|
|
16
|
+
# and file extensions to watch. It also takes a block that is called when
|
|
17
|
+
# EventedFileUpdateChecker#execute is run or when EventedFileUpdateChecker#execute_if_updated
|
|
18
|
+
# is run and there have been changes to the file system.
|
|
19
|
+
#
|
|
20
|
+
# Example:
|
|
21
|
+
#
|
|
22
|
+
# checker = ActiveSupport::EventedFileUpdateChecker.new(["/tmp/foo"]) { puts "changed" }
|
|
23
|
+
# checker.updated?
|
|
24
|
+
# # => false
|
|
25
|
+
# checker.execute_if_updated
|
|
26
|
+
# # => nil
|
|
27
|
+
#
|
|
28
|
+
# FileUtils.touch("/tmp/foo")
|
|
29
|
+
#
|
|
30
|
+
# checker.updated?
|
|
31
|
+
# # => true
|
|
32
|
+
# checker.execute_if_updated
|
|
33
|
+
# # => "changed"
|
|
34
|
+
#
|
|
35
|
+
class EventedFileUpdateChecker # :nodoc: all
|
|
36
|
+
def initialize(files, dirs = {}, &block)
|
|
37
|
+
unless block
|
|
38
|
+
raise ArgumentError, "A block is required to initialize an EventedFileUpdateChecker"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
@block = block
|
|
42
|
+
@core = Core.new(files, dirs)
|
|
43
|
+
ObjectSpace.define_finalizer(self, @core.finalizer)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def inspect
|
|
47
|
+
"#<ActiveSupport::EventedFileUpdateChecker:#{object_id} @files=#{@core.files.to_a.inspect}"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def updated?
|
|
51
|
+
if @core.restart?
|
|
52
|
+
@core.thread_safely(&:restart)
|
|
53
|
+
@core.updated.make_true
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
@core.updated.true?
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def execute
|
|
60
|
+
@core.updated.make_false
|
|
61
|
+
@block.call
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def execute_if_updated
|
|
65
|
+
if updated?
|
|
66
|
+
yield if block_given?
|
|
67
|
+
execute
|
|
68
|
+
true
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
class Core
|
|
73
|
+
attr_reader :updated, :files
|
|
74
|
+
|
|
75
|
+
def initialize(files, dirs)
|
|
76
|
+
gem_paths = Gem.path
|
|
77
|
+
files = files.map { |f| Pathname(f).expand_path }
|
|
78
|
+
files.reject! { |f| f.to_s.start_with?(*gem_paths) }
|
|
79
|
+
@files = files.to_set
|
|
80
|
+
|
|
81
|
+
@dirs = dirs.each_with_object({}) do |(dir, exts), hash|
|
|
82
|
+
next if dir.start_with?(*gem_paths)
|
|
83
|
+
hash[Pathname(dir).expand_path] = Array(exts).map { |ext| ext.to_s.sub(/\A\.?/, ".") }.to_set
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
@common_path = common_path(@dirs.keys)
|
|
87
|
+
|
|
88
|
+
@dtw = directories_to_watch
|
|
89
|
+
@missing = []
|
|
90
|
+
|
|
91
|
+
@updated = Concurrent::AtomicBoolean.new(false)
|
|
92
|
+
@mutex = Mutex.new
|
|
93
|
+
|
|
94
|
+
start
|
|
95
|
+
# inotify / FSEvents file descriptors are inherited on fork, so
|
|
96
|
+
# we need to reopen them otherwise only the parent or the child
|
|
97
|
+
# will be notified.
|
|
98
|
+
# FIXME: this callback is keeping a reference on the instance
|
|
99
|
+
@after_fork = ActiveSupport::ForkTracker.after_fork { start }
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def finalizer
|
|
103
|
+
proc do
|
|
104
|
+
stop
|
|
105
|
+
ActiveSupport::ForkTracker.unregister(@after_fork)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def thread_safely
|
|
110
|
+
@mutex.synchronize do
|
|
111
|
+
yield self
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def start
|
|
116
|
+
normalize_dirs!
|
|
117
|
+
@dtw, @missing = [*@dtw, *@missing].partition(&:exist?)
|
|
118
|
+
@listener = @dtw.any? ? Listen.to(*@dtw, &method(:changed)) : nil
|
|
119
|
+
@listener&.start
|
|
120
|
+
|
|
121
|
+
# Wait for the listener to be ready to avoid race conditions
|
|
122
|
+
# Unfortunately this isn't quite enough on macOS because the Darwin backend
|
|
123
|
+
# has an extra private thread we can't wait on.
|
|
124
|
+
@listener&.wait_for_state(:processing_events)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def stop
|
|
128
|
+
@listener&.stop
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def restart
|
|
132
|
+
stop
|
|
133
|
+
start
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def restart?
|
|
137
|
+
@missing.any?(&:exist?)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def normalize_dirs!
|
|
141
|
+
@dirs.transform_keys! do |dir|
|
|
142
|
+
dir.exist? ? dir.realpath : dir
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def changed(modified, added, removed)
|
|
147
|
+
unless @updated.true?
|
|
148
|
+
@updated.make_true if (modified + added + removed).any? { |f| watching?(f) }
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def watching?(file)
|
|
153
|
+
file = Pathname(file)
|
|
154
|
+
|
|
155
|
+
if @files.member?(file)
|
|
156
|
+
true
|
|
157
|
+
elsif file.directory?
|
|
158
|
+
false
|
|
159
|
+
else
|
|
160
|
+
ext = file.extname
|
|
161
|
+
|
|
162
|
+
file.dirname.ascend do |dir|
|
|
163
|
+
matching = @dirs[dir]
|
|
164
|
+
|
|
165
|
+
if matching && (matching.empty? || matching.include?(ext))
|
|
166
|
+
break true
|
|
167
|
+
elsif dir == @common_path || dir.root?
|
|
168
|
+
break false
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def directories_to_watch
|
|
175
|
+
dtw = @dirs.keys | @files.map(&:dirname)
|
|
176
|
+
accounted_for = dtw.to_set + Gem.path.map { |path| Pathname(path) }
|
|
177
|
+
dtw.reject { |dir| dir.ascend.drop(1).any? { |parent| accounted_for.include?(parent) } }
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def common_path(paths)
|
|
181
|
+
paths.map { |path| path.ascend.to_a }.reduce(&:&)&.first
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveSupport
|
|
4
|
+
module ExecutionContext # :nodoc:
|
|
5
|
+
class Record
|
|
6
|
+
attr_reader :store, :current_attributes_instances
|
|
7
|
+
|
|
8
|
+
def initialize
|
|
9
|
+
@store = {}
|
|
10
|
+
@current_attributes_instances = {}
|
|
11
|
+
@stack = []
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def push
|
|
15
|
+
@stack << @store << @current_attributes_instances
|
|
16
|
+
@store = {}
|
|
17
|
+
@current_attributes_instances = {}
|
|
18
|
+
self
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def pop
|
|
22
|
+
@current_attributes_instances = @stack.pop
|
|
23
|
+
@store = @stack.pop
|
|
24
|
+
self
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
@after_change_callbacks = []
|
|
29
|
+
|
|
30
|
+
# Execution context nesting should only legitimately happen during test
|
|
31
|
+
# because the test case itself is wrapped in an executor, and it might call
|
|
32
|
+
# into a controller or job which should be executed with their own fresh context.
|
|
33
|
+
# However in production this should never happen, and for extra safety we make sure to
|
|
34
|
+
# fully clear the state at the end of the request or job cycle.
|
|
35
|
+
@nestable = false
|
|
36
|
+
|
|
37
|
+
class << self
|
|
38
|
+
attr_accessor :nestable
|
|
39
|
+
|
|
40
|
+
def after_change(&block)
|
|
41
|
+
@after_change_callbacks << block
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Updates the execution context. If a block is given, it resets the provided keys to their
|
|
45
|
+
# previous value once the block exits.
|
|
46
|
+
def set(**options)
|
|
47
|
+
options.symbolize_keys!
|
|
48
|
+
keys = options.keys
|
|
49
|
+
|
|
50
|
+
store = record.store
|
|
51
|
+
|
|
52
|
+
previous_context = if block_given?
|
|
53
|
+
keys.zip(store.values_at(*keys)).to_h
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
store.merge!(options)
|
|
57
|
+
@after_change_callbacks.each(&:call)
|
|
58
|
+
|
|
59
|
+
if block_given?
|
|
60
|
+
begin
|
|
61
|
+
yield
|
|
62
|
+
ensure
|
|
63
|
+
store.merge!(previous_context)
|
|
64
|
+
@after_change_callbacks.each(&:call)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def []=(key, value)
|
|
70
|
+
record.store[key.to_sym] = value
|
|
71
|
+
@after_change_callbacks.each(&:call)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def to_h
|
|
75
|
+
record.store.dup
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def push
|
|
79
|
+
if @nestable
|
|
80
|
+
record.push
|
|
81
|
+
else
|
|
82
|
+
clear
|
|
83
|
+
end
|
|
84
|
+
self
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def pop
|
|
88
|
+
if @nestable
|
|
89
|
+
record.pop
|
|
90
|
+
else
|
|
91
|
+
clear
|
|
92
|
+
end
|
|
93
|
+
self
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def clear
|
|
97
|
+
IsolatedExecutionState[:active_support_execution_context] = nil
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def current_attributes_instances
|
|
101
|
+
record.current_attributes_instances
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
private
|
|
105
|
+
def record
|
|
106
|
+
IsolatedExecutionState[:active_support_execution_context] ||= Record.new
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_support/error_reporter"
|
|
4
|
+
require "active_support/callbacks"
|
|
5
|
+
|
|
6
|
+
module ActiveSupport
|
|
7
|
+
class ExecutionWrapper
|
|
8
|
+
include ActiveSupport::Callbacks
|
|
9
|
+
|
|
10
|
+
Null = Object.new # :nodoc:
|
|
11
|
+
def Null.complete! # :nodoc:
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
define_callbacks :run
|
|
15
|
+
define_callbacks :complete
|
|
16
|
+
|
|
17
|
+
def self.to_run(*args, &block)
|
|
18
|
+
set_callback(:run, *args, &block)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.to_complete(*args, &block)
|
|
22
|
+
set_callback(:complete, *args, &block)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
RunHook = Struct.new(:hook) do # :nodoc:
|
|
26
|
+
def before(target)
|
|
27
|
+
hook_state = target.send(:hook_state)
|
|
28
|
+
hook_state[hook] = hook.run
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
CompleteHook = Struct.new(:hook) do # :nodoc:
|
|
33
|
+
def before(target)
|
|
34
|
+
hook_state = target.send(:hook_state)
|
|
35
|
+
if hook_state.key?(hook)
|
|
36
|
+
hook.complete hook_state[hook]
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
alias after before
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Register an object to be invoked during both the +run+ and
|
|
43
|
+
# +complete+ steps.
|
|
44
|
+
#
|
|
45
|
+
# +hook.complete+ will be passed the value returned from +hook.run+,
|
|
46
|
+
# and will only be invoked if +run+ has previously been called.
|
|
47
|
+
# (Mostly, this means it won't be invoked if an exception occurs in
|
|
48
|
+
# a preceding +to_run+ block; all ordinary +to_complete+ blocks are
|
|
49
|
+
# invoked in that situation.)
|
|
50
|
+
def self.register_hook(hook, outer: false)
|
|
51
|
+
if outer
|
|
52
|
+
to_run RunHook.new(hook), prepend: true
|
|
53
|
+
to_complete :after, CompleteHook.new(hook)
|
|
54
|
+
else
|
|
55
|
+
to_run RunHook.new(hook)
|
|
56
|
+
to_complete CompleteHook.new(hook)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Run this execution.
|
|
61
|
+
#
|
|
62
|
+
# Returns an instance, whose +complete!+ method *must* be invoked
|
|
63
|
+
# after the work has been performed.
|
|
64
|
+
#
|
|
65
|
+
# Where possible, prefer +wrap+.
|
|
66
|
+
def self.run!(reset: false)
|
|
67
|
+
if reset
|
|
68
|
+
lost_instance = IsolatedExecutionState.delete(active_key)
|
|
69
|
+
lost_instance&.complete!
|
|
70
|
+
else
|
|
71
|
+
return Null if active?
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
new.tap do |instance|
|
|
75
|
+
success = nil
|
|
76
|
+
begin
|
|
77
|
+
instance.run!
|
|
78
|
+
success = true
|
|
79
|
+
ensure
|
|
80
|
+
instance.complete! unless success
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Perform the work in the supplied block as an execution.
|
|
86
|
+
def self.wrap(source: "application.active_support")
|
|
87
|
+
return yield if active?
|
|
88
|
+
|
|
89
|
+
instance = run!
|
|
90
|
+
begin
|
|
91
|
+
yield
|
|
92
|
+
rescue Exception => error
|
|
93
|
+
error_reporter&.report(error, handled: false, source: source)
|
|
94
|
+
raise
|
|
95
|
+
ensure
|
|
96
|
+
instance.complete!
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def self.perform # :nodoc:
|
|
101
|
+
instance = new
|
|
102
|
+
instance.run
|
|
103
|
+
begin
|
|
104
|
+
yield
|
|
105
|
+
ensure
|
|
106
|
+
instance.complete
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def self.error_reporter # :nodoc:
|
|
111
|
+
ActiveSupport.error_reporter
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def self.active_key # :nodoc:
|
|
115
|
+
@active_key ||= :"active_execution_wrapper_#{object_id}"
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def self.active? # :nodoc:
|
|
119
|
+
IsolatedExecutionState.key?(active_key)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def run! # :nodoc:
|
|
123
|
+
IsolatedExecutionState[self.class.active_key] = self
|
|
124
|
+
run
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def run # :nodoc:
|
|
128
|
+
run_callbacks(:run)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Complete this in-flight execution. This method *must* be called
|
|
132
|
+
# exactly once on the result of any call to +run!+.
|
|
133
|
+
#
|
|
134
|
+
# Where possible, prefer +wrap+.
|
|
135
|
+
def complete!
|
|
136
|
+
complete
|
|
137
|
+
ensure
|
|
138
|
+
IsolatedExecutionState.delete(self.class.active_key)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def complete # :nodoc:
|
|
142
|
+
run_callbacks(:complete)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
private
|
|
146
|
+
def hook_state
|
|
147
|
+
@_hook_state ||= {}
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_support/core_ext/time/calculations"
|
|
4
|
+
|
|
5
|
+
module ActiveSupport
|
|
6
|
+
# = \File Update Checker
|
|
7
|
+
#
|
|
8
|
+
# FileUpdateChecker specifies the API used by \Rails to watch files
|
|
9
|
+
# and control reloading. The API depends on four methods:
|
|
10
|
+
#
|
|
11
|
+
# * +initialize+ which expects two parameters and one block as
|
|
12
|
+
# described below.
|
|
13
|
+
#
|
|
14
|
+
# * +updated?+ which returns a boolean if there were updates in
|
|
15
|
+
# the filesystem or not.
|
|
16
|
+
#
|
|
17
|
+
# * +execute+ which executes the given block on initialization
|
|
18
|
+
# and updates the latest watched files and timestamp.
|
|
19
|
+
#
|
|
20
|
+
# * +execute_if_updated+ which just executes the block if it was updated.
|
|
21
|
+
#
|
|
22
|
+
# After initialization, a call to +execute_if_updated+ must execute
|
|
23
|
+
# the block only if there was really a change in the filesystem.
|
|
24
|
+
#
|
|
25
|
+
# This class is used by \Rails to reload the I18n framework whenever
|
|
26
|
+
# they are changed upon a new request.
|
|
27
|
+
#
|
|
28
|
+
# i18n_reloader = ActiveSupport::FileUpdateChecker.new(paths) do
|
|
29
|
+
# I18n.reload!
|
|
30
|
+
# end
|
|
31
|
+
#
|
|
32
|
+
# ActiveSupport::Reloader.to_prepare do
|
|
33
|
+
# i18n_reloader.execute_if_updated
|
|
34
|
+
# end
|
|
35
|
+
class FileUpdateChecker
|
|
36
|
+
# It accepts two parameters on initialization. The first is an array
|
|
37
|
+
# of files and the second is an optional hash of directories. The hash must
|
|
38
|
+
# have directories as keys and the value is an array of extensions to be
|
|
39
|
+
# watched under that directory.
|
|
40
|
+
#
|
|
41
|
+
# This method must also receive a block that will be called once a path
|
|
42
|
+
# changes. The array of files and list of directories cannot be changed
|
|
43
|
+
# after FileUpdateChecker has been initialized.
|
|
44
|
+
def initialize(files, dirs = {}, &block)
|
|
45
|
+
unless block
|
|
46
|
+
raise ArgumentError, "A block is required to initialize a FileUpdateChecker"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
gem_paths = Gem.path
|
|
50
|
+
@files = files.reject { |file| File.expand_path(file).start_with?(*gem_paths) }.freeze
|
|
51
|
+
|
|
52
|
+
@globs = compile_glob(dirs)&.reject { |dir| dir.start_with?(*gem_paths) }
|
|
53
|
+
|
|
54
|
+
@block = block
|
|
55
|
+
|
|
56
|
+
@watched = nil
|
|
57
|
+
@updated_at = nil
|
|
58
|
+
|
|
59
|
+
@last_watched = watched
|
|
60
|
+
@last_update_at = updated_at(@last_watched)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Check if any of the entries were updated. If so, the watched and/or
|
|
64
|
+
# updated_at values are cached until the block is executed via +execute+
|
|
65
|
+
# or +execute_if_updated+.
|
|
66
|
+
def updated?
|
|
67
|
+
current_watched = watched
|
|
68
|
+
if @last_watched.size != current_watched.size
|
|
69
|
+
@watched = current_watched
|
|
70
|
+
true
|
|
71
|
+
else
|
|
72
|
+
current_updated_at = updated_at(current_watched)
|
|
73
|
+
if @last_update_at < current_updated_at
|
|
74
|
+
@watched = current_watched
|
|
75
|
+
@updated_at = current_updated_at
|
|
76
|
+
true
|
|
77
|
+
else
|
|
78
|
+
false
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Executes the given block and updates the latest watched files and
|
|
84
|
+
# timestamp.
|
|
85
|
+
def execute
|
|
86
|
+
@last_watched = watched
|
|
87
|
+
@last_update_at = updated_at(@last_watched)
|
|
88
|
+
@block.call
|
|
89
|
+
ensure
|
|
90
|
+
@watched = nil
|
|
91
|
+
@updated_at = nil
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Execute the block given if updated.
|
|
95
|
+
def execute_if_updated
|
|
96
|
+
if updated?
|
|
97
|
+
yield if block_given?
|
|
98
|
+
execute
|
|
99
|
+
true
|
|
100
|
+
else
|
|
101
|
+
false
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
private
|
|
106
|
+
def watched
|
|
107
|
+
@watched || begin
|
|
108
|
+
all = @files.select { |f| File.exist?(f) }
|
|
109
|
+
all.concat(Dir[*@globs]) if @globs
|
|
110
|
+
all.tap(&:uniq!)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def updated_at(paths)
|
|
115
|
+
@updated_at || max_mtime(paths) || Time.at(0)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# This method returns the maximum mtime of the files in +paths+, or +nil+
|
|
119
|
+
# if the array is empty.
|
|
120
|
+
#
|
|
121
|
+
# Files with a mtime in the future are ignored. Such abnormal situation
|
|
122
|
+
# can happen for example if the user changes the clock by hand. It is
|
|
123
|
+
# healthy to consider this edge case because with mtimes in the future
|
|
124
|
+
# reloading is not triggered.
|
|
125
|
+
def max_mtime(paths)
|
|
126
|
+
time_now = Time.at(0, Process.clock_gettime(Process::CLOCK_REALTIME, :nanosecond), :nanosecond)
|
|
127
|
+
max_mtime = nil
|
|
128
|
+
|
|
129
|
+
# Time comparisons are performed with #compare_without_coercion because
|
|
130
|
+
# AS redefines these operators in a way that is much slower and does not
|
|
131
|
+
# bring any benefit in this particular code.
|
|
132
|
+
#
|
|
133
|
+
# Read t1.compare_without_coercion(t2) < 0 as t1 < t2.
|
|
134
|
+
paths.each do |path|
|
|
135
|
+
mtime = File.mtime(path)
|
|
136
|
+
|
|
137
|
+
next if time_now.compare_without_coercion(mtime) < 0
|
|
138
|
+
|
|
139
|
+
if max_mtime.nil? || max_mtime.compare_without_coercion(mtime) < 0
|
|
140
|
+
max_mtime = mtime
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
max_mtime
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def compile_glob(hash)
|
|
148
|
+
hash.freeze # Freeze so changes aren't accidentally pushed
|
|
149
|
+
return if hash.empty?
|
|
150
|
+
|
|
151
|
+
hash.map do |key, value|
|
|
152
|
+
"#{escape(key)}/**/*#{compile_ext(value)}"
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def escape(key)
|
|
157
|
+
key.gsub(",", '\,')
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def compile_ext(array)
|
|
161
|
+
array = Array(array)
|
|
162
|
+
return if array.empty?
|
|
163
|
+
".{#{array.join(",")}}"
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveSupport
|
|
4
|
+
module ForkTracker # :nodoc:
|
|
5
|
+
module CoreExt
|
|
6
|
+
def _fork
|
|
7
|
+
pid = super
|
|
8
|
+
if pid == 0
|
|
9
|
+
ForkTracker.after_fork_callback
|
|
10
|
+
end
|
|
11
|
+
pid
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
@pid = Process.pid
|
|
16
|
+
@callbacks = []
|
|
17
|
+
|
|
18
|
+
class << self
|
|
19
|
+
def after_fork_callback
|
|
20
|
+
new_pid = Process.pid
|
|
21
|
+
if @pid != new_pid
|
|
22
|
+
@callbacks.each(&:call)
|
|
23
|
+
@pid = new_pid
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def hook!
|
|
28
|
+
::Process.singleton_class.prepend(CoreExt)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def after_fork(&block)
|
|
32
|
+
@callbacks << block
|
|
33
|
+
block
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def unregister(callback)
|
|
37
|
+
@callbacks.delete(callback)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
ActiveSupport::ForkTracker.hook!
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveSupport
|
|
4
|
+
# Returns the currently loaded version of Active Support as a +Gem::Version+.
|
|
5
|
+
def self.gem_version
|
|
6
|
+
Gem::Version.new VERSION::STRING
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
module VERSION
|
|
10
|
+
MAJOR = 8
|
|
11
|
+
MINOR = 1
|
|
12
|
+
TINY = 2
|
|
13
|
+
PRE = nil
|
|
14
|
+
|
|
15
|
+
STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
|
|
16
|
+
end
|
|
17
|
+
end
|