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,97 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_support/time_with_zone"
|
|
4
|
+
require "active_support/core_ext/time/acts_like"
|
|
5
|
+
require "active_support/core_ext/date_and_time/zones"
|
|
6
|
+
|
|
7
|
+
class Time
|
|
8
|
+
include DateAndTime::Zones
|
|
9
|
+
class << self
|
|
10
|
+
attr_accessor :zone_default
|
|
11
|
+
|
|
12
|
+
# Returns the TimeZone for the current request, if this has been set (via Time.zone=).
|
|
13
|
+
# If <tt>Time.zone</tt> has not been set for the current request, returns the TimeZone specified in <tt>config.time_zone</tt>.
|
|
14
|
+
def zone
|
|
15
|
+
::ActiveSupport::IsolatedExecutionState[:time_zone] || zone_default
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Sets <tt>Time.zone</tt> to a TimeZone object for the current request/thread.
|
|
19
|
+
#
|
|
20
|
+
# This method accepts any of the following:
|
|
21
|
+
#
|
|
22
|
+
# * A \Rails TimeZone object.
|
|
23
|
+
# * An identifier for a \Rails TimeZone object (e.g., "Eastern \Time (US & Canada)", <tt>-5.hours</tt>).
|
|
24
|
+
# * A +TZInfo::Timezone+ object.
|
|
25
|
+
# * An identifier for a +TZInfo::Timezone+ object (e.g., "America/New_York").
|
|
26
|
+
#
|
|
27
|
+
# Here's an example of how you might set <tt>Time.zone</tt> on a per request basis and reset it when the request is done.
|
|
28
|
+
# <tt>current_user.time_zone</tt> just needs to return a string identifying the user's preferred time zone:
|
|
29
|
+
#
|
|
30
|
+
# class ApplicationController < ActionController::Base
|
|
31
|
+
# around_action :set_time_zone
|
|
32
|
+
#
|
|
33
|
+
# def set_time_zone
|
|
34
|
+
# if logged_in?
|
|
35
|
+
# Time.use_zone(current_user.time_zone) { yield }
|
|
36
|
+
# else
|
|
37
|
+
# yield
|
|
38
|
+
# end
|
|
39
|
+
# end
|
|
40
|
+
# end
|
|
41
|
+
def zone=(time_zone)
|
|
42
|
+
::ActiveSupport::IsolatedExecutionState[:time_zone] = find_zone!(time_zone)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Allows override of <tt>Time.zone</tt> locally inside supplied block;
|
|
46
|
+
# resets <tt>Time.zone</tt> to existing value when done.
|
|
47
|
+
#
|
|
48
|
+
# class ApplicationController < ActionController::Base
|
|
49
|
+
# around_action :set_time_zone
|
|
50
|
+
#
|
|
51
|
+
# private
|
|
52
|
+
# def set_time_zone
|
|
53
|
+
# Time.use_zone(current_user.timezone) { yield }
|
|
54
|
+
# end
|
|
55
|
+
# end
|
|
56
|
+
#
|
|
57
|
+
# NOTE: This won't affect any ActiveSupport::TimeWithZone
|
|
58
|
+
# objects that have already been created, e.g. any model timestamp
|
|
59
|
+
# attributes that have been read before the block will remain in
|
|
60
|
+
# the application's default timezone.
|
|
61
|
+
def use_zone(time_zone)
|
|
62
|
+
new_zone = find_zone!(time_zone)
|
|
63
|
+
begin
|
|
64
|
+
old_zone, ::Time.zone = ::Time.zone, new_zone
|
|
65
|
+
yield
|
|
66
|
+
ensure
|
|
67
|
+
::Time.zone = old_zone
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Returns a TimeZone instance matching the time zone provided.
|
|
72
|
+
# Accepts the time zone in any format supported by <tt>Time.zone=</tt>.
|
|
73
|
+
# Raises an +ArgumentError+ for invalid time zones.
|
|
74
|
+
#
|
|
75
|
+
# Time.find_zone! "America/New_York" # => #<ActiveSupport::TimeZone @name="America/New_York" ...>
|
|
76
|
+
# Time.find_zone! "EST" # => #<ActiveSupport::TimeZone @name="EST" ...>
|
|
77
|
+
# Time.find_zone! -5.hours # => #<ActiveSupport::TimeZone @name="Bogota" ...>
|
|
78
|
+
# Time.find_zone! nil # => nil
|
|
79
|
+
# Time.find_zone! false # => false
|
|
80
|
+
# Time.find_zone! "NOT-A-TIMEZONE" # => ArgumentError: Invalid Timezone: NOT-A-TIMEZONE
|
|
81
|
+
def find_zone!(time_zone)
|
|
82
|
+
return time_zone unless time_zone
|
|
83
|
+
|
|
84
|
+
ActiveSupport::TimeZone[time_zone] || raise(ArgumentError, "Invalid Timezone: #{time_zone}")
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Returns a TimeZone instance matching the time zone provided.
|
|
88
|
+
# Accepts the time zone in any format supported by <tt>Time.zone=</tt>.
|
|
89
|
+
# Returns +nil+ for invalid time zones.
|
|
90
|
+
#
|
|
91
|
+
# Time.find_zone "America/New_York" # => #<ActiveSupport::TimeZone @name="America/New_York" ...>
|
|
92
|
+
# Time.find_zone "NOT-A-TIMEZONE" # => nil
|
|
93
|
+
def find_zone(time_zone)
|
|
94
|
+
find_zone!(time_zone) rescue nil
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
require File.dirname(__FILE__) + '/time/conversions'
|
|
1
|
+
# frozen_string_literal: true
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
require_relative "time/acts_like"
|
|
4
|
+
require_relative "time/calculations"
|
|
5
|
+
require_relative "time/compatibility"
|
|
6
|
+
require_relative "time/conversions"
|
|
7
|
+
require_relative "time/zones"
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveSupport::CurrentAttributes::TestHelper # :nodoc:
|
|
4
|
+
def before_setup
|
|
5
|
+
ActiveSupport::CurrentAttributes.clear_all
|
|
6
|
+
super
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def after_teardown
|
|
10
|
+
super
|
|
11
|
+
ActiveSupport::CurrentAttributes.clear_all
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_support/callbacks"
|
|
4
|
+
require "active_support/execution_context"
|
|
5
|
+
require "active_support/core_ext/object/with"
|
|
6
|
+
require "active_support/core_ext/enumerable"
|
|
7
|
+
require "active_support/core_ext/module/delegation"
|
|
8
|
+
|
|
9
|
+
module ActiveSupport
|
|
10
|
+
# = Current Attributes
|
|
11
|
+
#
|
|
12
|
+
# Abstract super class that provides a thread-isolated attributes singleton, which resets automatically
|
|
13
|
+
# before and after each request. This allows you to keep all the per-request attributes easily
|
|
14
|
+
# available to the whole system.
|
|
15
|
+
#
|
|
16
|
+
# The following full app-like example demonstrates how to use a Current class to
|
|
17
|
+
# facilitate easy access to the global, per-request attributes without passing them deeply
|
|
18
|
+
# around everywhere:
|
|
19
|
+
#
|
|
20
|
+
# # app/models/current.rb
|
|
21
|
+
# class Current < ActiveSupport::CurrentAttributes
|
|
22
|
+
# attribute :account, :user
|
|
23
|
+
# attribute :request_id, :user_agent, :ip_address
|
|
24
|
+
#
|
|
25
|
+
# resets { Time.zone = nil }
|
|
26
|
+
#
|
|
27
|
+
# def user=(user)
|
|
28
|
+
# super
|
|
29
|
+
# self.account = user.account
|
|
30
|
+
# Time.zone = user.time_zone
|
|
31
|
+
# end
|
|
32
|
+
# end
|
|
33
|
+
#
|
|
34
|
+
# # app/controllers/concerns/authentication.rb
|
|
35
|
+
# module Authentication
|
|
36
|
+
# extend ActiveSupport::Concern
|
|
37
|
+
#
|
|
38
|
+
# included do
|
|
39
|
+
# before_action :authenticate
|
|
40
|
+
# end
|
|
41
|
+
#
|
|
42
|
+
# private
|
|
43
|
+
# def authenticate
|
|
44
|
+
# if authenticated_user = User.find_by(id: cookies.encrypted[:user_id])
|
|
45
|
+
# Current.user = authenticated_user
|
|
46
|
+
# else
|
|
47
|
+
# redirect_to new_session_url
|
|
48
|
+
# end
|
|
49
|
+
# end
|
|
50
|
+
# end
|
|
51
|
+
#
|
|
52
|
+
# # app/controllers/concerns/set_current_request_details.rb
|
|
53
|
+
# module SetCurrentRequestDetails
|
|
54
|
+
# extend ActiveSupport::Concern
|
|
55
|
+
#
|
|
56
|
+
# included do
|
|
57
|
+
# before_action do
|
|
58
|
+
# Current.request_id = request.uuid
|
|
59
|
+
# Current.user_agent = request.user_agent
|
|
60
|
+
# Current.ip_address = request.ip
|
|
61
|
+
# end
|
|
62
|
+
# end
|
|
63
|
+
# end
|
|
64
|
+
#
|
|
65
|
+
# class ApplicationController < ActionController::Base
|
|
66
|
+
# include Authentication
|
|
67
|
+
# include SetCurrentRequestDetails
|
|
68
|
+
# end
|
|
69
|
+
#
|
|
70
|
+
# class MessagesController < ApplicationController
|
|
71
|
+
# def create
|
|
72
|
+
# Current.account.messages.create(message_params)
|
|
73
|
+
# end
|
|
74
|
+
# end
|
|
75
|
+
#
|
|
76
|
+
# class Message < ApplicationRecord
|
|
77
|
+
# belongs_to :creator, default: -> { Current.user }
|
|
78
|
+
# after_create { |message| Event.create(record: message) }
|
|
79
|
+
# end
|
|
80
|
+
#
|
|
81
|
+
# class Event < ApplicationRecord
|
|
82
|
+
# before_create do
|
|
83
|
+
# self.request_id = Current.request_id
|
|
84
|
+
# self.user_agent = Current.user_agent
|
|
85
|
+
# self.ip_address = Current.ip_address
|
|
86
|
+
# end
|
|
87
|
+
# end
|
|
88
|
+
#
|
|
89
|
+
# A word of caution: It's easy to overdo a global singleton like Current and tangle your model as a result.
|
|
90
|
+
# Current should only be used for a few, top-level globals, like account, user, and request details.
|
|
91
|
+
# The attributes stuck in Current should be used by more or less all actions on all requests. If you start
|
|
92
|
+
# sticking controller-specific attributes in there, you're going to create a mess.
|
|
93
|
+
class CurrentAttributes
|
|
94
|
+
include ActiveSupport::Callbacks
|
|
95
|
+
define_callbacks :reset
|
|
96
|
+
|
|
97
|
+
INVALID_ATTRIBUTE_NAMES = [:set, :reset, :resets, :instance, :before_reset, :after_reset, :reset_all, :clear_all] # :nodoc:
|
|
98
|
+
|
|
99
|
+
NOT_SET = Object.new.freeze # :nodoc:
|
|
100
|
+
|
|
101
|
+
class << self
|
|
102
|
+
# Returns singleton instance for this class in this thread. If none exists, one is created.
|
|
103
|
+
def instance
|
|
104
|
+
current_instances[current_instances_key] ||= new
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Declares one or more attributes that will be given both class and instance accessor methods.
|
|
108
|
+
#
|
|
109
|
+
# ==== Options
|
|
110
|
+
#
|
|
111
|
+
# * <tt>:default</tt> - The default value for the attributes. If the value
|
|
112
|
+
# is a proc or lambda, it will be called whenever an instance is
|
|
113
|
+
# constructed. Otherwise, the value will be duplicated with +#dup+.
|
|
114
|
+
# Default values are re-assigned when the attributes are reset.
|
|
115
|
+
def attribute(*names, default: NOT_SET)
|
|
116
|
+
invalid_attribute_names = names.map(&:to_sym) & INVALID_ATTRIBUTE_NAMES
|
|
117
|
+
if invalid_attribute_names.any?
|
|
118
|
+
raise ArgumentError, "Restricted attribute names: #{invalid_attribute_names.join(", ")}"
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
Delegation.generate(singleton_class, names, to: :instance, nilable: false, signature: "")
|
|
122
|
+
Delegation.generate(singleton_class, names.map { |n| "#{n}=" }, to: :instance, nilable: false, signature: "value")
|
|
123
|
+
|
|
124
|
+
ActiveSupport::CodeGenerator.batch(generated_attribute_methods, __FILE__, __LINE__) do |owner|
|
|
125
|
+
names.each do |name|
|
|
126
|
+
owner.define_cached_method(name, namespace: :current_attributes) do |batch|
|
|
127
|
+
batch <<
|
|
128
|
+
"def #{name}" <<
|
|
129
|
+
"@attributes[:#{name}]" <<
|
|
130
|
+
"end"
|
|
131
|
+
end
|
|
132
|
+
owner.define_cached_method("#{name}=", namespace: :current_attributes) do |batch|
|
|
133
|
+
batch <<
|
|
134
|
+
"def #{name}=(value)" <<
|
|
135
|
+
"@attributes[:#{name}] = value" <<
|
|
136
|
+
"end"
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
self.defaults = defaults.merge(names.index_with { default })
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Calls this callback before #reset is called on the instance. Used for resetting external collaborators that depend on current values.
|
|
145
|
+
def before_reset(*methods, &block)
|
|
146
|
+
set_callback :reset, :before, *methods, &block
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# Calls this callback after #reset is called on the instance. Used for resetting external collaborators, like Time.zone.
|
|
150
|
+
def resets(*methods, &block)
|
|
151
|
+
set_callback :reset, :after, *methods, &block
|
|
152
|
+
end
|
|
153
|
+
alias_method :after_reset, :resets
|
|
154
|
+
|
|
155
|
+
delegate :set, :reset, to: :instance
|
|
156
|
+
|
|
157
|
+
def clear_all # :nodoc:
|
|
158
|
+
if instances = current_instances
|
|
159
|
+
instances.values.each(&:reset)
|
|
160
|
+
instances.clear
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
private
|
|
165
|
+
def generated_attribute_methods
|
|
166
|
+
@generated_attribute_methods ||= Module.new.tap { |mod| include mod }
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def current_instances
|
|
170
|
+
ExecutionContext.current_attributes_instances
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def current_instances_key
|
|
174
|
+
@current_instances_key ||= name.to_sym
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def method_missing(name, ...)
|
|
178
|
+
instance.public_send(name, ...)
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def respond_to_missing?(name, _)
|
|
182
|
+
instance.respond_to?(name) || super
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def method_added(name)
|
|
186
|
+
super
|
|
187
|
+
|
|
188
|
+
# We try to generate instance delegators early to not rely on method_missing.
|
|
189
|
+
return if name == :initialize
|
|
190
|
+
|
|
191
|
+
# If the added method isn't public, we don't delegate it.
|
|
192
|
+
return unless public_method_defined?(name)
|
|
193
|
+
|
|
194
|
+
# If we already have a class method by that name, we don't override it.
|
|
195
|
+
return if singleton_class.method_defined?(name) || singleton_class.private_method_defined?(name)
|
|
196
|
+
|
|
197
|
+
Delegation.generate(singleton_class, [name], to: :instance, as: self, nilable: false)
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
class_attribute :defaults, instance_writer: false, default: {}.freeze
|
|
202
|
+
|
|
203
|
+
attr_writer :attributes
|
|
204
|
+
|
|
205
|
+
def initialize
|
|
206
|
+
@attributes = resolve_defaults
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def attributes
|
|
210
|
+
@attributes.dup
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
# Expose one or more attributes within a block. Old values are returned after the block concludes.
|
|
214
|
+
# Example demonstrating the common use of needing to set Current attributes outside the request-cycle:
|
|
215
|
+
#
|
|
216
|
+
# class Chat::PublicationJob < ApplicationJob
|
|
217
|
+
# def perform(attributes, room_number, creator)
|
|
218
|
+
# Current.set(person: creator) do
|
|
219
|
+
# Chat::Publisher.publish(attributes: attributes, room_number: room_number)
|
|
220
|
+
# end
|
|
221
|
+
# end
|
|
222
|
+
# end
|
|
223
|
+
def set(attributes, &block)
|
|
224
|
+
with(**attributes, &block)
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
# Reset all attributes. Should be called before and after actions, when used as a per-request singleton.
|
|
228
|
+
def reset
|
|
229
|
+
run_callbacks :reset do
|
|
230
|
+
self.attributes = resolve_defaults
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
private
|
|
235
|
+
def resolve_defaults
|
|
236
|
+
defaults.each_with_object({}) do |(key, value), result|
|
|
237
|
+
if value != NOT_SET
|
|
238
|
+
result[key] = Proc === value ? value.call : value.dup
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveSupport
|
|
4
|
+
# Provides +deep_merge+ and +deep_merge!+ methods. Expects the including class
|
|
5
|
+
# to provide a <tt>merge!(other, &block)</tt> method.
|
|
6
|
+
module DeepMergeable # :nodoc:
|
|
7
|
+
# Returns a new instance with the values from +other+ merged recursively.
|
|
8
|
+
#
|
|
9
|
+
# class Hash
|
|
10
|
+
# include ActiveSupport::DeepMergeable
|
|
11
|
+
# end
|
|
12
|
+
#
|
|
13
|
+
# hash_1 = { a: true, b: { c: [1, 2, 3] } }
|
|
14
|
+
# hash_2 = { a: false, b: { x: [3, 4, 5] } }
|
|
15
|
+
#
|
|
16
|
+
# hash_1.deep_merge(hash_2)
|
|
17
|
+
# # => { a: false, b: { c: [1, 2, 3], x: [3, 4, 5] } }
|
|
18
|
+
#
|
|
19
|
+
# A block can be provided to merge non-<tt>DeepMergeable</tt> values:
|
|
20
|
+
#
|
|
21
|
+
# hash_1 = { a: 100, b: 200, c: { c1: 100 } }
|
|
22
|
+
# hash_2 = { b: 250, c: { c1: 200 } }
|
|
23
|
+
#
|
|
24
|
+
# hash_1.deep_merge(hash_2) do |key, this_val, other_val|
|
|
25
|
+
# this_val + other_val
|
|
26
|
+
# end
|
|
27
|
+
# # => { a: 100, b: 450, c: { c1: 300 } }
|
|
28
|
+
#
|
|
29
|
+
def deep_merge(other, &block)
|
|
30
|
+
dup.deep_merge!(other, &block)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Same as #deep_merge, but modifies +self+.
|
|
34
|
+
def deep_merge!(other, &block)
|
|
35
|
+
merge!(other) do |key, this_val, other_val|
|
|
36
|
+
if this_val.is_a?(DeepMergeable) && this_val.deep_merge?(other_val)
|
|
37
|
+
this_val.deep_merge(other_val, &block)
|
|
38
|
+
elsif block_given?
|
|
39
|
+
block.call(key, this_val, other_val)
|
|
40
|
+
else
|
|
41
|
+
other_val
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Returns true if +other+ can be deep merged into +self+. Classes may
|
|
47
|
+
# override this method to restrict or expand the domain of deep mergeable
|
|
48
|
+
# values. Defaults to checking that +other+ is of type +self.class+.
|
|
49
|
+
def deep_merge?(other)
|
|
50
|
+
other.is_a?(self.class)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveSupport
|
|
4
|
+
# Error generated by +delegate+ when a method is called on +nil+ and +allow_nil+
|
|
5
|
+
# option is not used.
|
|
6
|
+
class DelegationError < NoMethodError
|
|
7
|
+
class << self
|
|
8
|
+
def nil_target(method_name, target) # :nodoc:
|
|
9
|
+
new("#{method_name} delegated to #{target}, but #{target} is nil")
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
module Delegation # :nodoc:
|
|
15
|
+
RUBY_RESERVED_KEYWORDS = %w(__ENCODING__ __LINE__ __FILE__ alias and BEGIN begin break
|
|
16
|
+
case class def defined? do else elsif END end ensure false for if in module next nil
|
|
17
|
+
not or redo rescue retry return self super then true undef unless until when while yield)
|
|
18
|
+
RESERVED_METHOD_NAMES = (RUBY_RESERVED_KEYWORDS + %w(_ arg args block)).to_set.freeze
|
|
19
|
+
|
|
20
|
+
class << self
|
|
21
|
+
def generate(owner, methods, location: nil, to: nil, prefix: nil, allow_nil: nil, nilable: true, private: nil, as: nil, signature: nil)
|
|
22
|
+
unless to
|
|
23
|
+
raise ArgumentError, "Delegation needs a target. Supply a keyword argument 'to' (e.g. delegate :hello, to: :greeter)."
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
if prefix == true && /^[^a-z_]/.match?(to)
|
|
27
|
+
raise ArgumentError, "Can only automatically set the delegation prefix when delegating to a method."
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
method_prefix = \
|
|
31
|
+
if prefix
|
|
32
|
+
"#{prefix == true ? to : prefix}_"
|
|
33
|
+
else
|
|
34
|
+
""
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
location ||= caller_locations(1, 1).first
|
|
38
|
+
file, line = location.path, location.lineno
|
|
39
|
+
|
|
40
|
+
receiver = if to.is_a?(Module)
|
|
41
|
+
if to.name.nil?
|
|
42
|
+
raise ArgumentError, "Can't delegate to anonymous class or module: #{to}"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
unless Inflector.safe_constantize(to.name).equal?(to)
|
|
46
|
+
raise ArgumentError, "Can't delegate to detached class or module: #{to.name}"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
"::#{to.name}"
|
|
50
|
+
else
|
|
51
|
+
to.to_s
|
|
52
|
+
end
|
|
53
|
+
receiver = "self.#{receiver}" if RESERVED_METHOD_NAMES.include?(receiver)
|
|
54
|
+
|
|
55
|
+
explicit_receiver = false
|
|
56
|
+
receiver_class = if as
|
|
57
|
+
explicit_receiver = true
|
|
58
|
+
as
|
|
59
|
+
elsif to.is_a?(Module)
|
|
60
|
+
to.singleton_class
|
|
61
|
+
elsif receiver == "self.class"
|
|
62
|
+
nilable = false # self.class can't possibly be nil
|
|
63
|
+
owner.singleton_class
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
method_def = []
|
|
67
|
+
method_names = []
|
|
68
|
+
|
|
69
|
+
method_def << "self.private" if private
|
|
70
|
+
|
|
71
|
+
methods.each do |method|
|
|
72
|
+
method_name = prefix ? "#{method_prefix}#{method}" : method
|
|
73
|
+
method_names << method_name.to_sym
|
|
74
|
+
|
|
75
|
+
# Attribute writer methods only accept one argument. Makes sure []=
|
|
76
|
+
# methods still accept two arguments.
|
|
77
|
+
definition = \
|
|
78
|
+
if signature
|
|
79
|
+
signature
|
|
80
|
+
elsif /[^\]]=\z/.match?(method)
|
|
81
|
+
"arg"
|
|
82
|
+
else
|
|
83
|
+
method_object = if receiver_class
|
|
84
|
+
begin
|
|
85
|
+
receiver_class.public_instance_method(method)
|
|
86
|
+
rescue NameError
|
|
87
|
+
raise if explicit_receiver
|
|
88
|
+
# Do nothing. Fall back to `"..."`
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
if method_object
|
|
93
|
+
parameters = method_object.parameters
|
|
94
|
+
|
|
95
|
+
if parameters.map(&:first).intersect?([:opt, :rest, :keyreq, :key, :keyrest])
|
|
96
|
+
"..."
|
|
97
|
+
else
|
|
98
|
+
defn = parameters.filter_map { |type, arg| arg if type == :req }
|
|
99
|
+
defn << "&"
|
|
100
|
+
defn.join(", ")
|
|
101
|
+
end
|
|
102
|
+
else
|
|
103
|
+
"..."
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# The following generated method calls the target exactly once, storing
|
|
108
|
+
# the returned value in a dummy variable.
|
|
109
|
+
#
|
|
110
|
+
# Reason is twofold: On one hand doing less calls is in general better.
|
|
111
|
+
# On the other hand it could be that the target has side-effects,
|
|
112
|
+
# whereas conceptually, from the user point of view, the delegator should
|
|
113
|
+
# be doing one call.
|
|
114
|
+
if nilable == false
|
|
115
|
+
method_def <<
|
|
116
|
+
"def #{method_name}(#{definition})" <<
|
|
117
|
+
" (#{receiver}).#{method}(#{definition})" <<
|
|
118
|
+
"end"
|
|
119
|
+
elsif allow_nil
|
|
120
|
+
method = method.to_s
|
|
121
|
+
|
|
122
|
+
method_def <<
|
|
123
|
+
"def #{method_name}(#{definition})" <<
|
|
124
|
+
" _ = #{receiver}" <<
|
|
125
|
+
" if !_.nil? || nil.respond_to?(:#{method})" <<
|
|
126
|
+
" _.#{method}(#{definition})" <<
|
|
127
|
+
" end" <<
|
|
128
|
+
"end"
|
|
129
|
+
else
|
|
130
|
+
method = method.to_s
|
|
131
|
+
method_name = method_name.to_s
|
|
132
|
+
|
|
133
|
+
method_def <<
|
|
134
|
+
"def #{method_name}(#{definition})" <<
|
|
135
|
+
" _ = #{receiver}" <<
|
|
136
|
+
" _.#{method}(#{definition})" <<
|
|
137
|
+
"rescue ::NoMethodError => e" <<
|
|
138
|
+
" if _.nil? && e.name == :#{method}" <<
|
|
139
|
+
" ::Kernel.raise ::ActiveSupport::DelegationError.nil_target(:#{method_name}, :'#{receiver}')" <<
|
|
140
|
+
" else" <<
|
|
141
|
+
" ::Kernel.raise" <<
|
|
142
|
+
" end" <<
|
|
143
|
+
"end"
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
owner.module_eval(method_def.join(";"), file, line)
|
|
147
|
+
method_names
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def generate_method_missing(owner, target, allow_nil: nil)
|
|
151
|
+
target = target.to_s
|
|
152
|
+
target = "self.#{target}" if RESERVED_METHOD_NAMES.include?(target) || target == "__target"
|
|
153
|
+
|
|
154
|
+
nil_behavior = if allow_nil
|
|
155
|
+
"nil"
|
|
156
|
+
else
|
|
157
|
+
"::Kernel.raise ::ActiveSupport::DelegationError.nil_target(method, :'#{target}')"
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
owner.module_eval <<~RUBY, __FILE__, __LINE__ + 1
|
|
161
|
+
def respond_to_missing?(name, include_private = false)
|
|
162
|
+
# It may look like an oversight, but we deliberately do not pass
|
|
163
|
+
# +include_private+, because they do not get delegated.
|
|
164
|
+
|
|
165
|
+
return false if name == :marshal_dump || name == :_dump
|
|
166
|
+
#{target}.respond_to?(name) || super
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def method_missing(method, ...)
|
|
170
|
+
__target = #{target}
|
|
171
|
+
if __target.nil? && !nil.respond_to?(method)
|
|
172
|
+
#{nil_behavior}
|
|
173
|
+
elsif __target.respond_to?(method)
|
|
174
|
+
__target.public_send(method, ...)
|
|
175
|
+
else
|
|
176
|
+
super
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
RUBY
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_support/inflector/methods"
|
|
4
|
+
|
|
5
|
+
module ActiveSupport
|
|
6
|
+
# = Active Support \Autoload
|
|
7
|
+
#
|
|
8
|
+
# Autoload and eager load conveniences for your library.
|
|
9
|
+
#
|
|
10
|
+
# This module allows you to define autoloads based on
|
|
11
|
+
# \Rails conventions (i.e. no need to define the path
|
|
12
|
+
# it is automatically guessed based on the filename)
|
|
13
|
+
# and also define a set of constants that needs to be
|
|
14
|
+
# eager loaded:
|
|
15
|
+
#
|
|
16
|
+
# module MyLib
|
|
17
|
+
# extend ActiveSupport::Autoload
|
|
18
|
+
#
|
|
19
|
+
# autoload :Model
|
|
20
|
+
#
|
|
21
|
+
# eager_autoload do
|
|
22
|
+
# autoload :Cache
|
|
23
|
+
# end
|
|
24
|
+
# end
|
|
25
|
+
#
|
|
26
|
+
# Then your library can be eager loaded by simply calling:
|
|
27
|
+
#
|
|
28
|
+
# MyLib.eager_load!
|
|
29
|
+
module Autoload
|
|
30
|
+
def autoload(const_name, path = @_at_path)
|
|
31
|
+
unless path
|
|
32
|
+
full = [name, @_under_path, const_name.to_s].compact.join("::")
|
|
33
|
+
path = Inflector.underscore(full)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
if @_eager_autoload
|
|
37
|
+
@_eagerloaded_constants ||= []
|
|
38
|
+
@_eagerloaded_constants << const_name
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
super const_name, path
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def autoload_under(path)
|
|
45
|
+
@_under_path, old_path = path, @_under_path
|
|
46
|
+
yield
|
|
47
|
+
ensure
|
|
48
|
+
@_under_path = old_path
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def autoload_at(path)
|
|
52
|
+
@_at_path, old_path = path, @_at_path
|
|
53
|
+
yield
|
|
54
|
+
ensure
|
|
55
|
+
@_at_path = old_path
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def eager_autoload
|
|
59
|
+
old_eager, @_eager_autoload = @_eager_autoload, true
|
|
60
|
+
yield
|
|
61
|
+
ensure
|
|
62
|
+
@_eager_autoload = old_eager
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def eager_load!
|
|
66
|
+
if @_eagerloaded_constants
|
|
67
|
+
@_eagerloaded_constants.each { |const_name| const_get(const_name) }
|
|
68
|
+
@_eagerloaded_constants = nil
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|