activesupport 4.0.12 → 7.0.2.4
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activesupport might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +249 -501
- data/MIT-LICENSE +2 -2
- data/README.rdoc +10 -5
- data/lib/active_support/actionable_error.rb +48 -0
- data/lib/active_support/all.rb +5 -3
- data/lib/active_support/array_inquirer.rb +48 -0
- data/lib/active_support/backtrace_cleaner.rb +41 -13
- data/lib/active_support/benchmarkable.rb +7 -15
- data/lib/active_support/builder.rb +3 -1
- data/lib/active_support/cache/file_store.rb +96 -74
- data/lib/active_support/cache/mem_cache_store.rb +211 -103
- data/lib/active_support/cache/memory_store.rb +90 -58
- data/lib/active_support/cache/null_store.rb +19 -7
- data/lib/active_support/cache/redis_cache_store.rb +468 -0
- data/lib/active_support/cache/strategy/local_cache.rb +86 -83
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +45 -0
- data/lib/active_support/cache.rb +580 -241
- data/lib/active_support/callbacks.rb +812 -425
- data/lib/active_support/code_generator.rb +65 -0
- data/lib/active_support/concern.rb +103 -14
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +33 -0
- data/lib/active_support/concurrency/share_lock.rb +226 -0
- data/lib/active_support/configurable.rb +21 -19
- data/lib/active_support/configuration_file.rb +51 -0
- data/lib/active_support/core_ext/array/access.rb +47 -1
- data/lib/active_support/core_ext/array/conversions.rb +35 -44
- data/lib/active_support/core_ext/array/deprecated_conversions.rb +25 -0
- data/lib/active_support/core_ext/array/extract.rb +21 -0
- data/lib/active_support/core_ext/array/extract_options.rb +2 -0
- data/lib/active_support/core_ext/array/grouping.rb +26 -16
- data/lib/active_support/core_ext/array/inquiry.rb +19 -0
- data/lib/active_support/core_ext/array/wrap.rb +7 -4
- data/lib/active_support/core_ext/array.rb +10 -7
- data/lib/active_support/core_ext/benchmark.rb +5 -3
- data/lib/active_support/core_ext/big_decimal/conversions.rb +9 -26
- data/lib/active_support/core_ext/big_decimal.rb +3 -1
- data/lib/active_support/core_ext/class/attribute.rb +52 -49
- data/lib/active_support/core_ext/class/attribute_accessors.rb +5 -169
- data/lib/active_support/core_ext/class/subclasses.rb +25 -26
- data/lib/active_support/core_ext/class.rb +4 -4
- data/lib/active_support/core_ext/date/acts_like.rb +3 -1
- data/lib/active_support/core_ext/date/blank.rb +14 -0
- data/lib/active_support/core_ext/date/calculations.rb +31 -18
- data/lib/active_support/core_ext/date/conversions.rb +43 -32
- data/lib/active_support/core_ext/date/deprecated_conversions.rb +26 -0
- data/lib/active_support/core_ext/date/zones.rb +5 -34
- data/lib/active_support/core_ext/date.rb +7 -4
- data/lib/active_support/core_ext/date_and_time/calculations.rb +198 -66
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +31 -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 +4 -2
- data/lib/active_support/core_ext/date_time/blank.rb +14 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +79 -38
- data/lib/active_support/core_ext/date_time/compatibility.rb +18 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +31 -26
- data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +22 -0
- data/lib/active_support/core_ext/date_time.rb +8 -4
- data/lib/active_support/core_ext/digest/uuid.rb +79 -0
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/enumerable.rb +249 -17
- data/lib/active_support/core_ext/file/atomic.rb +41 -32
- data/lib/active_support/core_ext/file.rb +3 -1
- data/lib/active_support/core_ext/hash/conversions.rb +71 -49
- data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
- data/lib/active_support/core_ext/hash/except.rb +14 -5
- data/lib/active_support/core_ext/hash/indifferent_access.rb +5 -3
- data/lib/active_support/core_ext/hash/keys.rb +39 -56
- data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
- data/lib/active_support/core_ext/hash/slice.rb +8 -23
- data/lib/active_support/core_ext/hash.rb +10 -8
- data/lib/active_support/core_ext/integer/inflections.rb +3 -1
- data/lib/active_support/core_ext/integer/multiple.rb +3 -1
- data/lib/active_support/core_ext/integer/time.rb +11 -33
- data/lib/active_support/core_ext/integer.rb +5 -3
- data/lib/active_support/core_ext/kernel/concern.rb +14 -0
- data/lib/active_support/core_ext/kernel/reporting.rb +9 -78
- data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
- data/lib/active_support/core_ext/kernel.rb +5 -4
- data/lib/active_support/core_ext/load_error.rb +5 -21
- data/lib/active_support/core_ext/module/aliasing.rb +6 -44
- data/lib/active_support/core_ext/module/anonymous.rb +12 -1
- data/lib/active_support/core_ext/module/attr_internal.rb +8 -8
- data/lib/active_support/core_ext/module/attribute_accessors.rb +186 -44
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +157 -0
- data/lib/active_support/core_ext/module/concerning.rb +140 -0
- data/lib/active_support/core_ext/module/delegation.rb +172 -45
- data/lib/active_support/core_ext/module/deprecation.rb +3 -3
- data/lib/active_support/core_ext/module/introspection.rb +23 -38
- data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
- data/lib/active_support/core_ext/module/remove_method.rb +8 -3
- data/lib/active_support/core_ext/module.rb +13 -10
- data/lib/active_support/core_ext/name_error.rb +45 -4
- data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +135 -127
- data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +60 -0
- data/lib/active_support/core_ext/numeric/time.rb +37 -50
- data/lib/active_support/core_ext/numeric.rb +6 -3
- data/lib/active_support/core_ext/object/acts_like.rb +41 -6
- data/lib/active_support/core_ext/object/blank.rb +70 -20
- data/lib/active_support/core_ext/object/conversions.rb +6 -4
- data/lib/active_support/core_ext/object/deep_dup.rb +19 -10
- data/lib/active_support/core_ext/object/duplicable.rb +17 -47
- data/lib/active_support/core_ext/object/inclusion.rb +18 -15
- data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
- data/lib/active_support/core_ext/object/json.rb +244 -0
- data/lib/active_support/core_ext/object/to_param.rb +3 -1
- data/lib/active_support/core_ext/object/to_query.rb +21 -8
- data/lib/active_support/core_ext/object/try.rb +106 -26
- data/lib/active_support/core_ext/object/with_options.rb +64 -5
- data/lib/active_support/core_ext/object.rb +14 -12
- data/lib/active_support/core_ext/pathname/existence.rb +21 -0
- data/lib/active_support/core_ext/pathname.rb +3 -0
- data/lib/active_support/core_ext/range/compare_range.rb +57 -0
- data/lib/active_support/core_ext/range/conversions.rb +37 -15
- data/lib/active_support/core_ext/range/deprecated_conversions.rb +26 -0
- data/lib/active_support/core_ext/range/each.rb +18 -17
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +7 -0
- data/lib/active_support/core_ext/range/overlaps.rb +2 -0
- data/lib/active_support/core_ext/range.rb +7 -4
- data/lib/active_support/core_ext/regexp.rb +10 -1
- data/lib/active_support/core_ext/securerandom.rb +45 -0
- data/lib/active_support/core_ext/string/access.rb +42 -51
- data/lib/active_support/core_ext/string/behavior.rb +3 -1
- data/lib/active_support/core_ext/string/conversions.rb +18 -13
- data/lib/active_support/core_ext/string/exclude.rb +5 -3
- data/lib/active_support/core_ext/string/filters.rb +97 -7
- data/lib/active_support/core_ext/string/indent.rb +6 -4
- data/lib/active_support/core_ext/string/inflections.rb +106 -25
- data/lib/active_support/core_ext/string/inquiry.rb +4 -1
- data/lib/active_support/core_ext/string/multibyte.rb +18 -9
- data/lib/active_support/core_ext/string/output_safety.rb +227 -54
- data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
- data/lib/active_support/core_ext/string/strip.rb +6 -5
- data/lib/active_support/core_ext/string/zones.rb +4 -1
- data/lib/active_support/core_ext/string.rb +15 -13
- 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/time/acts_like.rb +3 -1
- data/lib/active_support/core_ext/time/calculations.rb +178 -116
- data/lib/active_support/core_ext/time/compatibility.rb +16 -0
- data/lib/active_support/core_ext/time/conversions.rb +37 -25
- data/lib/active_support/core_ext/time/deprecated_conversions.rb +22 -0
- data/lib/active_support/core_ext/time/zones.rb +44 -42
- data/lib/active_support/core_ext/time.rb +8 -5
- data/lib/active_support/core_ext/uri.rb +4 -25
- data/lib/active_support/core_ext.rb +4 -2
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/current_attributes.rb +226 -0
- data/lib/active_support/dependencies/autoload.rb +3 -1
- data/lib/active_support/dependencies/interlock.rb +49 -0
- data/lib/active_support/dependencies/require_dependency.rb +28 -0
- data/lib/active_support/dependencies.rb +71 -696
- data/lib/active_support/deprecation/behaviors.rb +65 -16
- data/lib/active_support/deprecation/constant_accessor.rb +52 -0
- data/lib/active_support/deprecation/disallowed.rb +56 -0
- data/lib/active_support/deprecation/instance_delegator.rb +16 -2
- data/lib/active_support/deprecation/method_wrappers.rb +62 -21
- data/lib/active_support/deprecation/proxy_wrappers.rb +82 -31
- data/lib/active_support/deprecation/reporting.rb +81 -18
- data/lib/active_support/deprecation.rb +19 -11
- data/lib/active_support/descendants_tracker.rb +192 -34
- 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 +67 -0
- data/lib/active_support/duration.rb +437 -39
- data/lib/active_support/encrypted_configuration.rb +56 -0
- data/lib/active_support/encrypted_file.rb +117 -0
- data/lib/active_support/environment_inquirer.rb +20 -0
- data/lib/active_support/error_reporter.rb +117 -0
- data/lib/active_support/evented_file_update_checker.rb +170 -0
- data/lib/active_support/execution_context/test_helper.rb +13 -0
- data/lib/active_support/execution_context.rb +53 -0
- data/lib/active_support/execution_wrapper.rb +151 -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 +62 -37
- data/lib/active_support/fork_tracker.rb +71 -0
- data/lib/active_support/gem_version.rb +17 -0
- data/lib/active_support/gzip.rb +7 -5
- data/lib/active_support/hash_with_indifferent_access.rb +207 -54
- data/lib/active_support/html_safe_translation.rb +43 -0
- data/lib/active_support/i18n.rb +10 -6
- data/lib/active_support/i18n_railtie.rb +48 -19
- data/lib/active_support/inflections.rb +19 -12
- data/lib/active_support/inflector/inflections.rb +97 -37
- data/lib/active_support/inflector/methods.rb +192 -157
- data/lib/active_support/inflector/transliterate.rb +83 -33
- data/lib/active_support/inflector.rb +7 -5
- data/lib/active_support/isolated_execution_state.rb +64 -0
- data/lib/active_support/json/decoding.rb +37 -42
- data/lib/active_support/json/encoding.rb +93 -293
- data/lib/active_support/json.rb +4 -2
- data/lib/active_support/key_generator.rb +30 -47
- data/lib/active_support/lazy_load_hooks.rb +54 -21
- data/lib/active_support/locale/en.rb +33 -0
- data/lib/active_support/locale/en.yml +10 -4
- data/lib/active_support/log_subscriber/test_helper.rb +14 -12
- data/lib/active_support/log_subscriber.rb +61 -18
- data/lib/active_support/logger.rb +40 -4
- data/lib/active_support/logger_silence.rb +17 -20
- data/lib/active_support/logger_thread_safe_level.rb +69 -0
- data/lib/active_support/message_encryptor.rb +178 -55
- data/lib/active_support/message_verifier.rb +195 -26
- data/lib/active_support/messages/metadata.rb +80 -0
- data/lib/active_support/messages/rotation_configuration.rb +23 -0
- data/lib/active_support/messages/rotator.rb +57 -0
- data/lib/active_support/multibyte/chars.rb +45 -92
- data/lib/active_support/multibyte/unicode.rb +44 -377
- data/lib/active_support/multibyte.rb +5 -3
- data/lib/active_support/notifications/fanout.rb +177 -44
- data/lib/active_support/notifications/instrumenter.rb +117 -17
- data/lib/active_support/notifications.rb +106 -39
- data/lib/active_support/number_helper/number_converter.rb +181 -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 +59 -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 +152 -394
- data/lib/active_support/option_merger.rb +18 -5
- data/lib/active_support/ordered_hash.rb +8 -6
- data/lib/active_support/ordered_options.rb +43 -7
- data/lib/active_support/parameter_filter.rb +138 -0
- data/lib/active_support/per_thread_registry.rb +24 -11
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/rails.rb +10 -11
- data/lib/active_support/railtie.rb +118 -12
- data/lib/active_support/reloader.rb +130 -0
- data/lib/active_support/rescuable.rb +112 -57
- data/lib/active_support/ruby_features.rb +7 -0
- data/lib/active_support/secure_compare_rotator.rb +51 -0
- data/lib/active_support/security_utils.rb +38 -0
- data/lib/active_support/string_inquirer.rb +11 -4
- data/lib/active_support/subscriber.rb +109 -39
- data/lib/active_support/tagged_logging.rb +54 -17
- data/lib/active_support/test_case.rb +121 -37
- data/lib/active_support/testing/assertions.rb +177 -39
- data/lib/active_support/testing/autorun.rb +5 -3
- data/lib/active_support/testing/constant_lookup.rb +3 -6
- data/lib/active_support/testing/declarative.rb +10 -22
- data/lib/active_support/testing/deprecation.rb +65 -11
- data/lib/active_support/testing/file_fixtures.rb +38 -0
- data/lib/active_support/testing/isolation.rb +56 -87
- data/lib/active_support/testing/method_call_assertions.rb +70 -0
- data/lib/active_support/testing/parallelization/server.rb +82 -0
- data/lib/active_support/testing/parallelization/worker.rb +103 -0
- data/lib/active_support/testing/parallelization.rb +55 -0
- data/lib/active_support/testing/parallelize_executor.rb +76 -0
- data/lib/active_support/testing/setup_and_teardown.rb +30 -10
- data/lib/active_support/testing/stream.rb +41 -0
- data/lib/active_support/testing/tagged_logging.rb +6 -4
- data/lib/active_support/testing/time_helpers.rb +246 -0
- data/lib/active_support/time.rb +13 -13
- data/lib/active_support/time_with_zone.rb +315 -90
- data/lib/active_support/values/time_zone.rb +306 -135
- data/lib/active_support/version.rb +6 -7
- data/lib/active_support/xml_mini/jdom.rb +117 -115
- data/lib/active_support/xml_mini/libxml.rb +22 -21
- data/lib/active_support/xml_mini/libxmlsax.rb +17 -19
- data/lib/active_support/xml_mini/nokogiri.rb +19 -19
- data/lib/active_support/xml_mini/nokogirisax.rb +16 -17
- data/lib/active_support/xml_mini/rexml.rb +25 -17
- data/lib/active_support/xml_mini.rb +67 -56
- data/lib/active_support.rb +58 -3
- metadata +125 -66
- data/lib/active_support/basic_object.rb +0 -11
- data/lib/active_support/buffered_logger.rb +0 -21
- data/lib/active_support/concurrency/latch.rb +0 -27
- data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
- data/lib/active_support/core_ext/array/uniq_by.rb +0 -19
- data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -40
- data/lib/active_support/core_ext/date_time/zones.rb +0 -24
- data/lib/active_support/core_ext/hash/diff.rb +0 -14
- data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
- data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
- data/lib/active_support/core_ext/logger.rb +0 -67
- data/lib/active_support/core_ext/marshal.rb +0 -21
- data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
- data/lib/active_support/core_ext/module/reachable.rb +0 -8
- data/lib/active_support/core_ext/object/to_json.rb +0 -27
- data/lib/active_support/core_ext/proc.rb +0 -17
- data/lib/active_support/core_ext/range/include_range.rb +0 -23
- data/lib/active_support/core_ext/string/encoding.rb +0 -8
- data/lib/active_support/core_ext/struct.rb +0 -6
- data/lib/active_support/core_ext/thread.rb +0 -79
- data/lib/active_support/core_ext/time/marshal.rb +0 -30
- data/lib/active_support/file_watcher.rb +0 -36
- data/lib/active_support/json/variable.rb +0 -18
- data/lib/active_support/testing/pending.rb +0 -14
- data/lib/active_support/values/unicode_tables.dat +0 -0
data/MIT-LICENSE
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (c) 2005-
|
1
|
+
Copyright (c) 2005-2022 David Heinemeier Hansson
|
2
2
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining
|
4
4
|
a copy of this software and associated documentation files (the
|
@@ -17,4 +17,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
17
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
18
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
19
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
CHANGED
@@ -5,31 +5,36 @@ extensions that were found useful for the Rails framework. These additions
|
|
5
5
|
reside in this package so they can be loaded as needed in Ruby projects
|
6
6
|
outside of Rails.
|
7
7
|
|
8
|
+
You can read more about the extensions in the {Active Support Core Extensions}[https://edgeguides.rubyonrails.org/active_support_core_extensions.html] guide.
|
8
9
|
|
9
10
|
== Download and installation
|
10
11
|
|
11
12
|
The latest version of Active Support can be installed with RubyGems:
|
12
13
|
|
13
|
-
|
14
|
+
$ gem install activesupport
|
14
15
|
|
15
16
|
Source code can be downloaded as part of the Rails project on GitHub:
|
16
17
|
|
17
|
-
* https://github.com/rails/rails/tree/
|
18
|
+
* https://github.com/rails/rails/tree/main/activesupport
|
18
19
|
|
19
20
|
|
20
21
|
== License
|
21
22
|
|
22
23
|
Active Support is released under the MIT license:
|
23
24
|
|
24
|
-
*
|
25
|
+
* https://opensource.org/licenses/MIT
|
25
26
|
|
26
27
|
|
27
28
|
== Support
|
28
29
|
|
29
30
|
API documentation is at:
|
30
31
|
|
31
|
-
*
|
32
|
+
* https://api.rubyonrails.org
|
32
33
|
|
33
|
-
Bug reports
|
34
|
+
Bug reports for the Ruby on Rails project can be filed here:
|
34
35
|
|
35
36
|
* https://github.com/rails/rails/issues
|
37
|
+
|
38
|
+
Feature requests should be discussed on the rails-core mailing list here:
|
39
|
+
|
40
|
+
* https://discuss.rubyonrails.org/c/rubyonrails-core
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveSupport
|
4
|
+
# Actionable errors lets you define actions to resolve an error.
|
5
|
+
#
|
6
|
+
# To make an error actionable, include the <tt>ActiveSupport::ActionableError</tt>
|
7
|
+
# module and invoke the +action+ class macro to define the action. An action
|
8
|
+
# needs a name and a block to execute.
|
9
|
+
module ActionableError
|
10
|
+
extend Concern
|
11
|
+
|
12
|
+
class NonActionable < StandardError; end
|
13
|
+
|
14
|
+
included do
|
15
|
+
class_attribute :_actions, default: {}
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.actions(error) # :nodoc:
|
19
|
+
case error
|
20
|
+
when ActionableError, -> it { Class === it && it < ActionableError }
|
21
|
+
error._actions
|
22
|
+
else
|
23
|
+
{}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.dispatch(error, name) # :nodoc:
|
28
|
+
actions(error).fetch(name).call
|
29
|
+
rescue KeyError
|
30
|
+
raise NonActionable, "Cannot find action \"#{name}\""
|
31
|
+
end
|
32
|
+
|
33
|
+
module ClassMethods
|
34
|
+
# Defines an action that can resolve the error.
|
35
|
+
#
|
36
|
+
# class PendingMigrationError < MigrationError
|
37
|
+
# include ActiveSupport::ActionableError
|
38
|
+
#
|
39
|
+
# action "Run pending migrations" do
|
40
|
+
# ActiveRecord::Tasks::DatabaseTasks.migrate
|
41
|
+
# end
|
42
|
+
# end
|
43
|
+
def action(name, &block)
|
44
|
+
_actions[name] = block
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/active_support/all.rb
CHANGED
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveSupport
|
4
|
+
# Wrapping an array in an +ArrayInquirer+ gives a friendlier way to check
|
5
|
+
# its string-like contents:
|
6
|
+
#
|
7
|
+
# variants = ActiveSupport::ArrayInquirer.new([:phone, :tablet])
|
8
|
+
#
|
9
|
+
# variants.phone? # => true
|
10
|
+
# variants.tablet? # => true
|
11
|
+
# variants.desktop? # => false
|
12
|
+
class ArrayInquirer < Array
|
13
|
+
# Passes each element of +candidates+ collection to ArrayInquirer collection.
|
14
|
+
# The method returns true if any element from the ArrayInquirer collection
|
15
|
+
# is equal to the stringified or symbolized form of any element in the +candidates+ collection.
|
16
|
+
#
|
17
|
+
# If +candidates+ collection is not given, method returns true.
|
18
|
+
#
|
19
|
+
# variants = ActiveSupport::ArrayInquirer.new([:phone, :tablet])
|
20
|
+
#
|
21
|
+
# variants.any? # => true
|
22
|
+
# variants.any?(:phone, :tablet) # => true
|
23
|
+
# variants.any?('phone', 'desktop') # => true
|
24
|
+
# variants.any?(:desktop, :watch) # => false
|
25
|
+
def any?(*candidates)
|
26
|
+
if candidates.none?
|
27
|
+
super
|
28
|
+
else
|
29
|
+
candidates.any? do |candidate|
|
30
|
+
include?(candidate.to_sym) || include?(candidate.to_s)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
def respond_to_missing?(name, include_private = false)
|
37
|
+
name.end_with?("?") || super
|
38
|
+
end
|
39
|
+
|
40
|
+
def method_missing(name, *args)
|
41
|
+
if name.end_with?("?")
|
42
|
+
any?(name[0..-2])
|
43
|
+
else
|
44
|
+
super
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveSupport
|
2
4
|
# Backtraces often include many lines that are not relevant for the context
|
3
5
|
# under review. This makes it hard to find the signal amongst the backtrace
|
@@ -12,23 +14,26 @@ module ActiveSupport
|
|
12
14
|
# is to exclude the output of a noisy library from the backtrace, so that you
|
13
15
|
# can focus on the rest.
|
14
16
|
#
|
15
|
-
# bc = BacktraceCleaner.new
|
16
|
-
# bc.add_filter { |line| line.gsub(Rails.root, '') }
|
17
|
-
# bc.add_silencer { |line|
|
18
|
-
# bc.clean(exception.backtrace) #
|
17
|
+
# bc = ActiveSupport::BacktraceCleaner.new
|
18
|
+
# bc.add_filter { |line| line.gsub(Rails.root.to_s, '') } # strip the Rails.root prefix
|
19
|
+
# bc.add_silencer { |line| /puma|rubygems/.match?(line) } # skip any lines from puma or rubygems
|
20
|
+
# bc.clean(exception.backtrace) # perform the cleanup
|
19
21
|
#
|
20
22
|
# To reconfigure an existing BacktraceCleaner (like the default one in Rails)
|
21
23
|
# and show as much data as possible, you can always call
|
22
24
|
# <tt>BacktraceCleaner#remove_silencers!</tt>, which will restore the
|
23
25
|
# backtrace to a pristine state. If you need to reconfigure an existing
|
24
26
|
# BacktraceCleaner so that it does not filter or modify the paths of any lines
|
25
|
-
# of the backtrace, you can call BacktraceCleaner#remove_filters
|
26
|
-
# methods will give you a completely untouched backtrace.
|
27
|
+
# of the backtrace, you can call <tt>BacktraceCleaner#remove_filters!</tt>
|
28
|
+
# These two methods will give you a completely untouched backtrace.
|
27
29
|
#
|
28
|
-
# Inspired by the Quiet Backtrace gem by
|
30
|
+
# Inspired by the Quiet Backtrace gem by thoughtbot.
|
29
31
|
class BacktraceCleaner
|
30
32
|
def initialize
|
31
33
|
@filters, @silencers = [], []
|
34
|
+
add_gem_filter
|
35
|
+
add_gem_silencer
|
36
|
+
add_stdlib_silencer
|
32
37
|
end
|
33
38
|
|
34
39
|
# Returns the backtrace after all filters and silencers have been run
|
@@ -59,20 +64,20 @@ module ActiveSupport
|
|
59
64
|
# Adds a silencer from the block provided. If the silencer returns +true+
|
60
65
|
# for a given line, it will be excluded from the clean backtrace.
|
61
66
|
#
|
62
|
-
# # Will reject all lines that include the word "
|
63
|
-
# backtrace_cleaner.add_silencer { |line| line
|
67
|
+
# # Will reject all lines that include the word "puma", like "/gems/puma/server.rb" or "/app/my_puma_server/rb"
|
68
|
+
# backtrace_cleaner.add_silencer { |line| /puma/.match?(line) }
|
64
69
|
def add_silencer(&block)
|
65
70
|
@silencers << block
|
66
71
|
end
|
67
72
|
|
68
|
-
#
|
69
|
-
#
|
73
|
+
# Removes all silencers, but leaves in the filters. Useful if your
|
74
|
+
# context of debugging suddenly expands as you suspect a bug in one of
|
70
75
|
# the libraries you use.
|
71
76
|
def remove_silencers!
|
72
77
|
@silencers = []
|
73
78
|
end
|
74
79
|
|
75
|
-
# Removes all filters, but leaves in silencers. Useful if you suddenly
|
80
|
+
# Removes all filters, but leaves in the silencers. Useful if you suddenly
|
76
81
|
# need to see entire filepaths in the backtrace that you had already
|
77
82
|
# filtered out.
|
78
83
|
def remove_filters!
|
@@ -80,6 +85,25 @@ module ActiveSupport
|
|
80
85
|
end
|
81
86
|
|
82
87
|
private
|
88
|
+
FORMATTED_GEMS_PATTERN = /\A[^\/]+ \([\w.]+\) /
|
89
|
+
|
90
|
+
def add_gem_filter
|
91
|
+
gems_paths = (Gem.path | [Gem.default_dir]).map { |p| Regexp.escape(p) }
|
92
|
+
return if gems_paths.empty?
|
93
|
+
|
94
|
+
gems_regexp = %r{\A(#{gems_paths.join('|')})/(bundler/)?gems/([^/]+)-([\w.]+)/(.*)}
|
95
|
+
gems_result = '\3 (\4) \5'
|
96
|
+
add_filter { |line| line.sub(gems_regexp, gems_result) }
|
97
|
+
end
|
98
|
+
|
99
|
+
def add_gem_silencer
|
100
|
+
add_silencer { |line| FORMATTED_GEMS_PATTERN.match?(line) }
|
101
|
+
end
|
102
|
+
|
103
|
+
def add_stdlib_silencer
|
104
|
+
add_silencer { |line| line.start_with?(RbConfig::CONFIG["rubylibdir"]) }
|
105
|
+
end
|
106
|
+
|
83
107
|
def filter_backtrace(backtrace)
|
84
108
|
@filters.each do |f|
|
85
109
|
backtrace = backtrace.map { |line| f.call(line) }
|
@@ -97,7 +121,11 @@ module ActiveSupport
|
|
97
121
|
end
|
98
122
|
|
99
123
|
def noise(backtrace)
|
100
|
-
backtrace
|
124
|
+
backtrace.select do |line|
|
125
|
+
@silencers.any? do |s|
|
126
|
+
s.call(line)
|
127
|
+
end
|
128
|
+
end
|
101
129
|
end
|
102
130
|
end
|
103
131
|
end
|
@@ -1,5 +1,7 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/benchmark"
|
4
|
+
require "active_support/core_ext/hash/keys"
|
3
5
|
|
4
6
|
module ActiveSupport
|
5
7
|
module Benchmarkable
|
@@ -32,28 +34,18 @@ module ActiveSupport
|
|
32
34
|
# <% benchmark 'Process data files', level: :info, silence: true do %>
|
33
35
|
# <%= expensive_and_chatty_files_operation %>
|
34
36
|
# <% end %>
|
35
|
-
def benchmark(message = "Benchmarking", options = {})
|
37
|
+
def benchmark(message = "Benchmarking", options = {}, &block)
|
36
38
|
if logger
|
37
39
|
options.assert_valid_keys(:level, :silence)
|
38
40
|
options[:level] ||= :info
|
39
41
|
|
40
42
|
result = nil
|
41
|
-
ms = Benchmark.ms { result = options[:silence] ? silence
|
42
|
-
logger.
|
43
|
+
ms = Benchmark.ms { result = options[:silence] ? logger.silence(&block) : yield }
|
44
|
+
logger.public_send(options[:level], "%s (%.1fms)" % [ message, ms ])
|
43
45
|
result
|
44
46
|
else
|
45
47
|
yield
|
46
48
|
end
|
47
49
|
end
|
48
|
-
|
49
|
-
# Silence the logger during the execution of the block.
|
50
|
-
def silence
|
51
|
-
message = "ActiveSupport::Benchmarkable#silence is deprecated. It will be removed from Rails 4.1."
|
52
|
-
ActiveSupport::Deprecation.warn message
|
53
|
-
old_logger_level, logger.level = logger.level, ::Logger::ERROR if logger
|
54
|
-
yield
|
55
|
-
ensure
|
56
|
-
logger.level = old_logger_level if logger
|
57
|
-
end
|
58
50
|
end
|
59
51
|
end
|
@@ -1,7 +1,8 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/file/atomic"
|
4
|
+
require "active_support/core_ext/string/conversions"
|
5
|
+
require "uri/common"
|
5
6
|
|
6
7
|
module ActiveSupport
|
7
8
|
module Cache
|
@@ -13,55 +14,48 @@ module ActiveSupport
|
|
13
14
|
attr_reader :cache_path
|
14
15
|
|
15
16
|
DIR_FORMATTER = "%03X"
|
16
|
-
FILENAME_MAX_SIZE =
|
17
|
-
|
17
|
+
FILENAME_MAX_SIZE = 226 # max filename size on file system is 255, minus room for timestamp, pid, and random characters appended by Tempfile (used by atomic write)
|
18
|
+
FILEPATH_MAX_SIZE = 900 # max is 1024, plus some room
|
19
|
+
GITKEEP_FILES = [".gitkeep", ".keep"].freeze
|
18
20
|
|
19
|
-
def initialize(cache_path, options
|
21
|
+
def initialize(cache_path, **options)
|
20
22
|
super(options)
|
21
23
|
@cache_path = cache_path.to_s
|
22
|
-
extend Strategy::LocalCache
|
23
24
|
end
|
24
25
|
|
26
|
+
# Advertise cache versioning support.
|
27
|
+
def self.supports_cache_versioning?
|
28
|
+
true
|
29
|
+
end
|
30
|
+
|
31
|
+
# Deletes all items from the cache. In this case it deletes all the entries in the specified
|
32
|
+
# file store directory except for .keep or .gitkeep. Be careful which directory is specified in your
|
33
|
+
# config file when using +FileStore+ because everything in that directory will be deleted.
|
25
34
|
def clear(options = nil)
|
26
|
-
root_dirs = Dir.
|
27
|
-
FileUtils.rm_r(root_dirs.collect{|f| File.join(cache_path, f)})
|
35
|
+
root_dirs = (Dir.children(cache_path) - GITKEEP_FILES)
|
36
|
+
FileUtils.rm_r(root_dirs.collect { |f| File.join(cache_path, f) })
|
37
|
+
rescue Errno::ENOENT, Errno::ENOTEMPTY
|
28
38
|
end
|
29
39
|
|
40
|
+
# Preemptively iterates through all stored keys and removes the ones which have expired.
|
30
41
|
def cleanup(options = nil)
|
31
42
|
options = merged_options(options)
|
32
43
|
search_dir(cache_path) do |fname|
|
33
|
-
|
34
|
-
|
35
|
-
delete_entry(key, options) if entry && entry.expired?
|
44
|
+
entry = read_entry(fname, **options)
|
45
|
+
delete_entry(fname, **options) if entry && entry.expired?
|
36
46
|
end
|
37
47
|
end
|
38
48
|
|
49
|
+
# Increments an already existing integer value that is stored in the cache.
|
50
|
+
# If the key is not found nothing is done.
|
39
51
|
def increment(name, amount = 1, options = nil)
|
40
|
-
|
41
|
-
lock_file(file_name) do
|
42
|
-
options = merged_options(options)
|
43
|
-
if num = read(name, options)
|
44
|
-
num = num.to_i + amount
|
45
|
-
write(name, num, options)
|
46
|
-
num
|
47
|
-
else
|
48
|
-
nil
|
49
|
-
end
|
50
|
-
end
|
52
|
+
modify_value(name, amount, options)
|
51
53
|
end
|
52
54
|
|
55
|
+
# Decrements an already existing integer value that is stored in the cache.
|
56
|
+
# If the key is not found nothing is done.
|
53
57
|
def decrement(name, amount = 1, options = nil)
|
54
|
-
|
55
|
-
lock_file(file_name) do
|
56
|
-
options = merged_options(options)
|
57
|
-
if num = read(name, options)
|
58
|
-
num = num.to_i - amount
|
59
|
-
write(name, num, options)
|
60
|
-
num
|
61
|
-
else
|
62
|
-
nil
|
63
|
-
end
|
64
|
-
end
|
58
|
+
modify_value(name, -amount, options)
|
65
59
|
end
|
66
60
|
|
67
61
|
def delete_matched(matcher, options = nil)
|
@@ -70,56 +64,59 @@ module ActiveSupport
|
|
70
64
|
matcher = key_matcher(matcher, options)
|
71
65
|
search_dir(cache_path) do |path|
|
72
66
|
key = file_path_key(path)
|
73
|
-
delete_entry(
|
67
|
+
delete_entry(path, **options) if key.match(matcher)
|
74
68
|
end
|
75
69
|
end
|
76
70
|
end
|
77
71
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
File.open(file_name) { |f| Marshal.load(f) }
|
72
|
+
private
|
73
|
+
def read_entry(key, **options)
|
74
|
+
if payload = read_serialized_entry(key, **options)
|
75
|
+
entry = deserialize_entry(payload)
|
76
|
+
entry if entry.is_a?(Cache::Entry)
|
84
77
|
end
|
85
|
-
|
86
|
-
|
78
|
+
end
|
79
|
+
|
80
|
+
def read_serialized_entry(key, **)
|
81
|
+
File.binread(key) if File.exist?(key)
|
82
|
+
rescue => error
|
83
|
+
logger.error("FileStoreError (#{error}): #{error.message}") if logger
|
87
84
|
nil
|
88
85
|
end
|
89
86
|
|
90
|
-
def write_entry(key, entry, options)
|
91
|
-
|
92
|
-
|
93
|
-
|
87
|
+
def write_entry(key, entry, **options)
|
88
|
+
write_serialized_entry(key, serialize_entry(entry, **options), **options)
|
89
|
+
end
|
90
|
+
|
91
|
+
def write_serialized_entry(key, payload, **options)
|
92
|
+
return false if options[:unless_exist] && File.exist?(key)
|
93
|
+
ensure_cache_path(File.dirname(key))
|
94
|
+
File.atomic_write(key, cache_path) { |f| f.write(payload) }
|
94
95
|
true
|
95
96
|
end
|
96
97
|
|
97
|
-
def delete_entry(key, options)
|
98
|
-
|
99
|
-
if File.exist?(file_name)
|
98
|
+
def delete_entry(key, **options)
|
99
|
+
if File.exist?(key)
|
100
100
|
begin
|
101
|
-
File.delete(
|
102
|
-
delete_empty_directories(File.dirname(
|
101
|
+
File.delete(key)
|
102
|
+
delete_empty_directories(File.dirname(key))
|
103
103
|
true
|
104
|
-
rescue
|
104
|
+
rescue
|
105
105
|
# Just in case the error was caused by another process deleting the file first.
|
106
|
-
raise
|
106
|
+
raise if File.exist?(key)
|
107
107
|
false
|
108
108
|
end
|
109
109
|
end
|
110
110
|
end
|
111
111
|
|
112
|
-
private
|
113
112
|
# Lock a file for a block so only one process can modify it at a time.
|
114
|
-
def lock_file(file_name, &block)
|
113
|
+
def lock_file(file_name, &block)
|
115
114
|
if File.exist?(file_name)
|
116
|
-
File.open(file_name,
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
f.flock File::LOCK_UN
|
122
|
-
end
|
115
|
+
File.open(file_name, "r+") do |f|
|
116
|
+
f.flock File::LOCK_EX
|
117
|
+
yield
|
118
|
+
ensure
|
119
|
+
f.flock File::LOCK_UN
|
123
120
|
end
|
124
121
|
else
|
125
122
|
yield
|
@@ -127,20 +124,30 @@ module ActiveSupport
|
|
127
124
|
end
|
128
125
|
|
129
126
|
# Translate a key into a file path.
|
130
|
-
def
|
127
|
+
def normalize_key(key, options)
|
128
|
+
key = super
|
131
129
|
fname = URI.encode_www_form_component(key)
|
130
|
+
|
131
|
+
if fname.size > FILEPATH_MAX_SIZE
|
132
|
+
fname = ActiveSupport::Digest.hexdigest(key)
|
133
|
+
end
|
134
|
+
|
132
135
|
hash = Zlib.adler32(fname)
|
133
136
|
hash, dir_1 = hash.divmod(0x1000)
|
134
137
|
dir_2 = hash.modulo(0x1000)
|
135
|
-
fname_paths = []
|
136
138
|
|
137
139
|
# Make sure file name doesn't exceed file system limits.
|
138
|
-
|
139
|
-
fname_paths
|
140
|
-
|
141
|
-
|
140
|
+
if fname.length < FILENAME_MAX_SIZE
|
141
|
+
fname_paths = fname
|
142
|
+
else
|
143
|
+
fname_paths = []
|
144
|
+
begin
|
145
|
+
fname_paths << fname[0, FILENAME_MAX_SIZE]
|
146
|
+
fname = fname[FILENAME_MAX_SIZE..-1]
|
147
|
+
end until fname.blank?
|
148
|
+
end
|
142
149
|
|
143
|
-
File.join(cache_path, DIR_FORMATTER % dir_1, DIR_FORMATTER % dir_2,
|
150
|
+
File.join(cache_path, DIR_FORMATTER % dir_1, DIR_FORMATTER % dir_2, fname_paths)
|
144
151
|
end
|
145
152
|
|
146
153
|
# Translate a file path into a key.
|
@@ -152,7 +159,7 @@ module ActiveSupport
|
|
152
159
|
# Delete empty directories in the cache.
|
153
160
|
def delete_empty_directories(dir)
|
154
161
|
return if File.realpath(dir) == File.realpath(cache_path)
|
155
|
-
if Dir.
|
162
|
+
if Dir.children(dir).empty?
|
156
163
|
Dir.delete(dir) rescue nil
|
157
164
|
delete_empty_directories(File.dirname(dir))
|
158
165
|
end
|
@@ -165,8 +172,7 @@ module ActiveSupport
|
|
165
172
|
|
166
173
|
def search_dir(dir, &callback)
|
167
174
|
return if !File.exist?(dir)
|
168
|
-
Dir.
|
169
|
-
next if EXCLUDED_DIRS.include?(d)
|
175
|
+
Dir.each_child(dir) do |d|
|
170
176
|
name = File.join(dir, d)
|
171
177
|
if File.directory?(name)
|
172
178
|
search_dir(name, &callback)
|
@@ -175,6 +181,22 @@ module ActiveSupport
|
|
175
181
|
end
|
176
182
|
end
|
177
183
|
end
|
184
|
+
|
185
|
+
# Modifies the amount of an already existing integer value that is stored in the cache.
|
186
|
+
# If the key is not found nothing is done.
|
187
|
+
def modify_value(name, amount, options)
|
188
|
+
file_name = normalize_key(name, options)
|
189
|
+
|
190
|
+
lock_file(file_name) do
|
191
|
+
options = merged_options(options)
|
192
|
+
|
193
|
+
if num = read(name, options)
|
194
|
+
num = num.to_i + amount
|
195
|
+
write(name, num, options)
|
196
|
+
num
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
178
200
|
end
|
179
201
|
end
|
180
202
|
end
|