activesupport 5.1.7 → 5.2.4.3
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 +4 -4
- data/CHANGELOG.md +401 -541
- data/MIT-LICENSE +1 -1
- data/README.rdoc +3 -3
- data/lib/active_support.rb +5 -13
- data/lib/active_support/all.rb +2 -0
- data/lib/active_support/array_inquirer.rb +2 -0
- data/lib/active_support/backtrace_cleaner.rb +2 -0
- data/lib/active_support/benchmarkable.rb +2 -0
- data/lib/active_support/builder.rb +2 -0
- data/lib/active_support/cache.rb +197 -83
- data/lib/active_support/cache/file_store.rb +5 -4
- data/lib/active_support/cache/mem_cache_store.rb +39 -39
- data/lib/active_support/cache/memory_store.rb +2 -0
- data/lib/active_support/cache/null_store.rb +2 -0
- data/lib/active_support/cache/redis_cache_store.rb +466 -0
- data/lib/active_support/cache/strategy/local_cache.rb +33 -2
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +2 -0
- data/lib/active_support/callbacks.rb +28 -39
- data/lib/active_support/concern.rb +10 -4
- data/lib/active_support/concurrency/share_lock.rb +2 -0
- data/lib/active_support/configurable.rb +2 -0
- data/lib/active_support/core_ext.rb +3 -1
- data/lib/active_support/core_ext/array.rb +2 -0
- data/lib/active_support/core_ext/array/access.rb +4 -2
- data/lib/active_support/core_ext/array/conversions.rb +2 -0
- data/lib/active_support/core_ext/array/extract_options.rb +2 -0
- data/lib/active_support/core_ext/array/grouping.rb +2 -0
- data/lib/active_support/core_ext/array/inquiry.rb +2 -0
- data/lib/active_support/core_ext/array/prepend_and_append.rb +4 -2
- data/lib/active_support/core_ext/array/wrap.rb +2 -0
- data/lib/active_support/core_ext/benchmark.rb +2 -0
- data/lib/active_support/core_ext/big_decimal.rb +2 -0
- data/lib/active_support/core_ext/big_decimal/conversions.rb +2 -0
- data/lib/active_support/core_ext/class.rb +2 -0
- data/lib/active_support/core_ext/class/attribute.rb +34 -16
- data/lib/active_support/core_ext/class/attribute_accessors.rb +2 -0
- data/lib/active_support/core_ext/class/subclasses.rb +1 -2
- data/lib/active_support/core_ext/date.rb +2 -0
- data/lib/active_support/core_ext/date/acts_like.rb +2 -0
- data/lib/active_support/core_ext/date/blank.rb +2 -0
- data/lib/active_support/core_ext/date/calculations.rb +2 -0
- data/lib/active_support/core_ext/date/conversions.rb +10 -9
- data/lib/active_support/core_ext/date/zones.rb +2 -0
- data/lib/active_support/core_ext/date_and_time/calculations.rb +50 -16
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +3 -1
- data/lib/active_support/core_ext/date_and_time/zones.rb +2 -0
- data/lib/active_support/core_ext/date_time.rb +2 -0
- data/lib/active_support/core_ext/date_time/acts_like.rb +2 -0
- data/lib/active_support/core_ext/date_time/blank.rb +2 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +2 -0
- data/lib/active_support/core_ext/date_time/compatibility.rb +7 -5
- data/lib/active_support/core_ext/date_time/conversions.rb +2 -0
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/digest/uuid.rb +3 -1
- data/lib/active_support/core_ext/enumerable.rb +8 -1
- data/lib/active_support/core_ext/file.rb +2 -0
- data/lib/active_support/core_ext/file/atomic.rb +3 -1
- data/lib/active_support/core_ext/hash.rb +2 -0
- data/lib/active_support/core_ext/hash/compact.rb +2 -0
- data/lib/active_support/core_ext/hash/conversions.rb +4 -2
- data/lib/active_support/core_ext/hash/deep_merge.rb +8 -12
- data/lib/active_support/core_ext/hash/except.rb +2 -0
- data/lib/active_support/core_ext/hash/indifferent_access.rb +2 -0
- data/lib/active_support/core_ext/hash/keys.rb +2 -0
- data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
- data/lib/active_support/core_ext/hash/slice.rb +4 -4
- data/lib/active_support/core_ext/hash/transform_values.rb +2 -0
- data/lib/active_support/core_ext/integer.rb +2 -0
- data/lib/active_support/core_ext/integer/inflections.rb +2 -0
- data/lib/active_support/core_ext/integer/multiple.rb +2 -0
- data/lib/active_support/core_ext/integer/time.rb +7 -14
- data/lib/active_support/core_ext/kernel.rb +2 -0
- data/lib/active_support/core_ext/kernel/agnostics.rb +2 -0
- data/lib/active_support/core_ext/kernel/concern.rb +2 -0
- data/lib/active_support/core_ext/kernel/reporting.rb +2 -0
- data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
- data/lib/active_support/core_ext/load_error.rb +2 -7
- data/lib/active_support/core_ext/marshal.rb +2 -0
- data/lib/active_support/core_ext/module.rb +3 -0
- data/lib/active_support/core_ext/module/aliasing.rb +2 -0
- data/lib/active_support/core_ext/module/anonymous.rb +2 -0
- data/lib/active_support/core_ext/module/attr_internal.rb +2 -0
- data/lib/active_support/core_ext/module/attribute_accessors.rb +21 -24
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +2 -0
- data/lib/active_support/core_ext/module/concerning.rb +7 -8
- data/lib/active_support/core_ext/module/delegation.rb +31 -29
- data/lib/active_support/core_ext/module/deprecation.rb +2 -0
- data/lib/active_support/core_ext/module/introspection.rb +2 -0
- data/lib/active_support/core_ext/module/reachable.rb +3 -0
- data/lib/active_support/core_ext/module/redefine_method.rb +49 -0
- data/lib/active_support/core_ext/module/remove_method.rb +5 -23
- data/lib/active_support/core_ext/name_error.rb +7 -0
- data/lib/active_support/core_ext/numeric.rb +2 -0
- data/lib/active_support/core_ext/numeric/bytes.rb +2 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +9 -7
- data/lib/active_support/core_ext/numeric/inquiry.rb +2 -0
- data/lib/active_support/core_ext/numeric/time.rb +7 -15
- data/lib/active_support/core_ext/object.rb +2 -0
- data/lib/active_support/core_ext/object/acts_like.rb +12 -1
- data/lib/active_support/core_ext/object/blank.rb +12 -1
- data/lib/active_support/core_ext/object/conversions.rb +2 -0
- data/lib/active_support/core_ext/object/deep_dup.rb +2 -0
- data/lib/active_support/core_ext/object/duplicable.rb +10 -8
- data/lib/active_support/core_ext/object/inclusion.rb +2 -0
- data/lib/active_support/core_ext/object/instance_variables.rb +2 -0
- data/lib/active_support/core_ext/object/json.rb +8 -0
- data/lib/active_support/core_ext/object/to_param.rb +2 -0
- data/lib/active_support/core_ext/object/to_query.rb +2 -0
- data/lib/active_support/core_ext/object/try.rb +2 -0
- data/lib/active_support/core_ext/object/with_options.rb +3 -1
- data/lib/active_support/core_ext/range.rb +4 -1
- data/lib/active_support/core_ext/range/compare_range.rb +61 -0
- data/lib/active_support/core_ext/range/conversions.rb +9 -1
- data/lib/active_support/core_ext/range/each.rb +5 -1
- data/lib/active_support/core_ext/range/include_range.rb +2 -22
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -0
- data/lib/active_support/core_ext/range/overlaps.rb +2 -0
- data/lib/active_support/core_ext/regexp.rb +2 -0
- data/lib/active_support/core_ext/securerandom.rb +2 -0
- data/lib/active_support/core_ext/string.rb +2 -0
- data/lib/active_support/core_ext/string/access.rb +2 -0
- data/lib/active_support/core_ext/string/behavior.rb +2 -0
- data/lib/active_support/core_ext/string/conversions.rb +2 -0
- data/lib/active_support/core_ext/string/exclude.rb +2 -0
- data/lib/active_support/core_ext/string/filters.rb +2 -0
- data/lib/active_support/core_ext/string/indent.rb +2 -0
- data/lib/active_support/core_ext/string/inflections.rb +26 -12
- data/lib/active_support/core_ext/string/inquiry.rb +2 -0
- data/lib/active_support/core_ext/string/multibyte.rb +4 -0
- data/lib/active_support/core_ext/string/output_safety.rb +6 -7
- data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
- data/lib/active_support/core_ext/string/strip.rb +2 -0
- data/lib/active_support/core_ext/string/zones.rb +2 -0
- data/lib/active_support/core_ext/time.rb +2 -0
- data/lib/active_support/core_ext/time/acts_like.rb +2 -0
- data/lib/active_support/core_ext/time/calculations.rb +23 -15
- data/lib/active_support/core_ext/time/compatibility.rb +4 -2
- data/lib/active_support/core_ext/time/conversions.rb +2 -0
- data/lib/active_support/core_ext/time/zones.rb +6 -4
- data/lib/active_support/core_ext/uri.rb +6 -6
- data/lib/active_support/current_attributes.rb +195 -0
- data/lib/active_support/dependencies.rb +25 -26
- data/lib/active_support/dependencies/autoload.rb +2 -0
- data/lib/active_support/dependencies/interlock.rb +2 -0
- data/lib/active_support/deprecation.rb +4 -2
- data/lib/active_support/deprecation/behaviors.rb +28 -9
- data/lib/active_support/deprecation/constant_accessor.rb +4 -2
- data/lib/active_support/deprecation/instance_delegator.rb +2 -0
- data/lib/active_support/deprecation/method_wrappers.rb +30 -17
- data/lib/active_support/deprecation/proxy_wrappers.rb +5 -2
- data/lib/active_support/deprecation/reporting.rb +5 -3
- data/lib/active_support/descendants_tracker.rb +2 -0
- data/lib/active_support/digest.rb +20 -0
- data/lib/active_support/duration.rb +11 -7
- data/lib/active_support/duration/iso8601_parser.rb +4 -2
- data/lib/active_support/duration/iso8601_serializer.rb +4 -2
- data/lib/active_support/encrypted_configuration.rb +49 -0
- data/lib/active_support/encrypted_file.rb +99 -0
- data/lib/active_support/evented_file_update_checker.rb +2 -0
- data/lib/active_support/execution_wrapper.rb +2 -0
- data/lib/active_support/executor.rb +2 -0
- data/lib/active_support/file_update_checker.rb +2 -0
- data/lib/active_support/gem_version.rb +5 -3
- data/lib/active_support/gzip.rb +2 -0
- data/lib/active_support/hash_with_indifferent_access.rb +55 -1
- data/lib/active_support/i18n.rb +3 -1
- data/lib/active_support/i18n_railtie.rb +4 -6
- data/lib/active_support/inflections.rb +2 -0
- data/lib/active_support/inflector.rb +2 -0
- data/lib/active_support/inflector/inflections.rb +20 -4
- data/lib/active_support/inflector/methods.rb +43 -24
- data/lib/active_support/inflector/transliterate.rb +17 -8
- data/lib/active_support/json.rb +2 -0
- data/lib/active_support/json/decoding.rb +2 -0
- data/lib/active_support/json/encoding.rb +2 -0
- data/lib/active_support/key_generator.rb +3 -1
- data/lib/active_support/lazy_load_hooks.rb +2 -0
- data/lib/active_support/log_subscriber.rb +3 -2
- data/lib/active_support/log_subscriber/test_helper.rb +2 -0
- data/lib/active_support/logger.rb +2 -0
- data/lib/active_support/logger_silence.rb +3 -2
- data/lib/active_support/logger_thread_safe_level.rb +4 -1
- data/lib/active_support/message_encryptor.rb +95 -22
- data/lib/active_support/message_verifier.rb +78 -7
- data/lib/active_support/messages/metadata.rb +71 -0
- data/lib/active_support/messages/rotation_configuration.rb +22 -0
- data/lib/active_support/messages/rotator.rb +56 -0
- data/lib/active_support/multibyte.rb +2 -0
- data/lib/active_support/multibyte/chars.rb +2 -0
- data/lib/active_support/multibyte/unicode.rb +4 -2
- data/lib/active_support/notifications.rb +2 -0
- data/lib/active_support/notifications/fanout.rb +4 -2
- data/lib/active_support/notifications/instrumenter.rb +2 -0
- data/lib/active_support/number_helper.rb +2 -0
- data/lib/active_support/number_helper/number_converter.rb +2 -0
- data/lib/active_support/number_helper/number_to_currency_converter.rb +2 -0
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +2 -0
- data/lib/active_support/number_helper/number_to_human_converter.rb +2 -0
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +2 -0
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +2 -0
- data/lib/active_support/number_helper/number_to_phone_converter.rb +3 -1
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +2 -20
- data/lib/active_support/number_helper/rounding_helper.rb +6 -4
- data/lib/active_support/option_merger.rb +2 -0
- data/lib/active_support/ordered_hash.rb +2 -0
- data/lib/active_support/ordered_options.rb +5 -3
- data/lib/active_support/per_thread_registry.rb +2 -0
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/rails.rb +2 -0
- data/lib/active_support/railtie.rb +37 -8
- data/lib/active_support/reloader.rb +7 -5
- data/lib/active_support/rescuable.rb +3 -2
- data/lib/active_support/security_utils.rb +15 -11
- data/lib/active_support/string_inquirer.rb +2 -0
- data/lib/active_support/subscriber.rb +8 -2
- data/lib/active_support/tagged_logging.rb +2 -0
- data/lib/active_support/test_case.rb +3 -2
- data/lib/active_support/testing/assertions.rb +31 -14
- data/lib/active_support/testing/autorun.rb +2 -0
- data/lib/active_support/testing/constant_lookup.rb +2 -0
- data/lib/active_support/testing/declarative.rb +2 -0
- data/lib/active_support/testing/deprecation.rb +2 -0
- data/lib/active_support/testing/file_fixtures.rb +2 -0
- data/lib/active_support/testing/isolation.rb +3 -1
- data/lib/active_support/testing/method_call_assertions.rb +2 -0
- data/lib/active_support/testing/setup_and_teardown.rb +12 -7
- data/lib/active_support/testing/stream.rb +2 -0
- data/lib/active_support/testing/tagged_logging.rb +2 -0
- data/lib/active_support/testing/time_helpers.rb +33 -3
- data/lib/active_support/time.rb +2 -0
- data/lib/active_support/time_with_zone.rb +38 -0
- data/lib/active_support/values/time_zone.rb +20 -8
- data/lib/active_support/version.rb +2 -0
- data/lib/active_support/xml_mini.rb +4 -2
- data/lib/active_support/xml_mini/jdom.rb +4 -2
- data/lib/active_support/xml_mini/libxml.rb +3 -1
- data/lib/active_support/xml_mini/libxmlsax.rb +4 -2
- data/lib/active_support/xml_mini/nokogiri.rb +3 -1
- data/lib/active_support/xml_mini/nokogirisax.rb +3 -1
- data/lib/active_support/xml_mini/rexml.rb +3 -1
- metadata +17 -5
data/MIT-LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -14,14 +14,14 @@ The latest version of Active Support can be installed with RubyGems:
|
|
14
14
|
|
15
15
|
Source code can be downloaded as part of the Rails project on GitHub:
|
16
16
|
|
17
|
-
* https://github.com/rails/rails/tree/
|
17
|
+
* https://github.com/rails/rails/tree/5-2-stable/activesupport
|
18
18
|
|
19
19
|
|
20
20
|
== License
|
21
21
|
|
22
22
|
Active Support is released under the MIT license:
|
23
23
|
|
24
|
-
*
|
24
|
+
* https://opensource.org/licenses/MIT
|
25
25
|
|
26
26
|
|
27
27
|
== Support
|
@@ -30,7 +30,7 @@ API documentation is at:
|
|
30
30
|
|
31
31
|
* http://api.rubyonrails.org
|
32
32
|
|
33
|
-
Bug reports
|
33
|
+
Bug reports for the Ruby on Rails project can be filed here:
|
34
34
|
|
35
35
|
* https://github.com/rails/rails/issues
|
36
36
|
|
data/lib/active_support.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
#--
|
2
|
-
# Copyright (c) 2005-
|
4
|
+
# Copyright (c) 2005-2018 David Heinemeier Hansson
|
3
5
|
#
|
4
6
|
# Permission is hereby granted, free of charge, to any person obtaining
|
5
7
|
# a copy of this software and associated documentation files (the
|
@@ -32,6 +34,7 @@ module ActiveSupport
|
|
32
34
|
extend ActiveSupport::Autoload
|
33
35
|
|
34
36
|
autoload :Concern
|
37
|
+
autoload :CurrentAttributes
|
35
38
|
autoload :Dependencies
|
36
39
|
autoload :DescendantsTracker
|
37
40
|
autoload :ExecutionWrapper
|
@@ -50,6 +53,7 @@ module ActiveSupport
|
|
50
53
|
autoload :Callbacks
|
51
54
|
autoload :Configurable
|
52
55
|
autoload :Deprecation
|
56
|
+
autoload :Digest
|
53
57
|
autoload :Gzip
|
54
58
|
autoload :Inflector
|
55
59
|
autoload :JSON
|
@@ -79,18 +83,6 @@ module ActiveSupport
|
|
79
83
|
|
80
84
|
cattr_accessor :test_order # :nodoc:
|
81
85
|
|
82
|
-
def self.halt_callback_chains_on_return_false
|
83
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
84
|
-
ActiveSupport.halt_callback_chains_on_return_false is deprecated and will be removed in Rails 5.2.
|
85
|
-
MSG
|
86
|
-
end
|
87
|
-
|
88
|
-
def self.halt_callback_chains_on_return_false=(value)
|
89
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
90
|
-
ActiveSupport.halt_callback_chains_on_return_false= is deprecated and will be removed in Rails 5.2.
|
91
|
-
MSG
|
92
|
-
end
|
93
|
-
|
94
86
|
def self.to_time_preserves_timezone
|
95
87
|
DateAndTime::Compatibility.preserve_timezone
|
96
88
|
end
|
data/lib/active_support/all.rb
CHANGED
data/lib/active_support/cache.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "zlib"
|
2
4
|
require "active_support/core_ext/array/extract_options"
|
3
5
|
require "active_support/core_ext/array/wrap"
|
@@ -10,10 +12,11 @@ require "active_support/core_ext/string/inflections"
|
|
10
12
|
module ActiveSupport
|
11
13
|
# See ActiveSupport::Cache::Store for documentation.
|
12
14
|
module Cache
|
13
|
-
autoload :FileStore,
|
14
|
-
autoload :MemoryStore,
|
15
|
-
autoload :MemCacheStore,
|
16
|
-
autoload :NullStore,
|
15
|
+
autoload :FileStore, "active_support/cache/file_store"
|
16
|
+
autoload :MemoryStore, "active_support/cache/memory_store"
|
17
|
+
autoload :MemCacheStore, "active_support/cache/mem_cache_store"
|
18
|
+
autoload :NullStore, "active_support/cache/null_store"
|
19
|
+
autoload :RedisCacheStore, "active_support/cache/redis_cache_store"
|
17
20
|
|
18
21
|
# These options mean something to all cache implementations. Individual cache
|
19
22
|
# implementations may support additional options.
|
@@ -75,7 +78,7 @@ module ActiveSupport
|
|
75
78
|
#
|
76
79
|
# The +key+ argument can also respond to +cache_key+ or +to_param+.
|
77
80
|
def expand_cache_key(key, namespace = nil)
|
78
|
-
expanded_cache_key = namespace ? "#{namespace}/" : ""
|
81
|
+
expanded_cache_key = (namespace ? "#{namespace}/" : "").dup
|
79
82
|
|
80
83
|
if prefix = ENV["RAILS_CACHE_ID"] || ENV["RAILS_APP_VERSION"]
|
81
84
|
expanded_cache_key << "#{prefix}/"
|
@@ -88,16 +91,19 @@ module ActiveSupport
|
|
88
91
|
private
|
89
92
|
def retrieve_cache_key(key)
|
90
93
|
case
|
91
|
-
when key.respond_to?(:
|
92
|
-
when key.
|
93
|
-
when key.
|
94
|
-
|
94
|
+
when key.respond_to?(:cache_key_with_version) then key.cache_key_with_version
|
95
|
+
when key.respond_to?(:cache_key) then key.cache_key
|
96
|
+
when key.is_a?(Array) then key.map { |element| retrieve_cache_key(element) }.to_param
|
97
|
+
when key.respond_to?(:to_a) then retrieve_cache_key(key.to_a)
|
98
|
+
else key.to_param
|
95
99
|
end.to_s
|
96
100
|
end
|
97
101
|
|
98
102
|
# Obtains the specified cache store class, given the name of the +store+.
|
99
103
|
# Raises an error when the store class cannot be found.
|
100
104
|
def retrieve_store_class(store)
|
105
|
+
# require_relative cannot be used here because the class might be
|
106
|
+
# provided by another gem, like redis-activesupport for example.
|
101
107
|
require "active_support/cache/#{store}"
|
102
108
|
rescue LoadError => e
|
103
109
|
raise "Could not find cache store adapter for #{store} (#{e})"
|
@@ -143,18 +149,34 @@ module ActiveSupport
|
|
143
149
|
# cache.namespace = -> { @last_mod_time } # Set the namespace to a variable
|
144
150
|
# @last_mod_time = Time.now # Invalidate the entire cache by changing namespace
|
145
151
|
#
|
146
|
-
#
|
147
|
-
#
|
148
|
-
#
|
149
|
-
# <tt
|
150
|
-
#
|
151
|
-
# <tt>:compress_threshold</tt> option. The default threshold is 16K.
|
152
|
+
# Cached data larger than 1kB are compressed by default. To turn off
|
153
|
+
# compression, pass <tt>compress: false</tt> to the initializer or to
|
154
|
+
# individual +fetch+ or +write+ method calls. The 1kB compression
|
155
|
+
# threshold is configurable with the <tt>:compress_threshold</tt> option,
|
156
|
+
# specified in bytes.
|
152
157
|
class Store
|
153
158
|
cattr_accessor :logger, instance_writer: true
|
154
159
|
|
155
160
|
attr_reader :silence, :options
|
156
161
|
alias :silence? :silence
|
157
162
|
|
163
|
+
class << self
|
164
|
+
private
|
165
|
+
def retrieve_pool_options(options)
|
166
|
+
{}.tap do |pool_options|
|
167
|
+
pool_options[:size] = options.delete(:pool_size) if options[:pool_size]
|
168
|
+
pool_options[:timeout] = options.delete(:pool_timeout) if options[:pool_timeout]
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def ensure_connection_pool_added!
|
173
|
+
require "connection_pool"
|
174
|
+
rescue LoadError => e
|
175
|
+
$stderr.puts "You don't have connection_pool installed in your application. Please add it to your Gemfile and run bundle install"
|
176
|
+
raise e
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
158
180
|
# Creates a new cache. The options will be passed to any write method calls
|
159
181
|
# except for <tt>:namespace</tt> which can be used to set the global
|
160
182
|
# namespace for the cache.
|
@@ -207,8 +229,7 @@ module ActiveSupport
|
|
207
229
|
# ask whether you should force a cache write. Otherwise, it's clearer to
|
208
230
|
# just call <tt>Cache#write</tt>.
|
209
231
|
#
|
210
|
-
# Setting <tt
|
211
|
-
# in a compressed format.
|
232
|
+
# Setting <tt>compress: false</tt> disables compression of the cache entry.
|
212
233
|
#
|
213
234
|
# Setting <tt>:expires_in</tt> will set an expiration time on the cache.
|
214
235
|
# All caches support auto-expiring content after a specified number of
|
@@ -219,6 +240,10 @@ module ActiveSupport
|
|
219
240
|
# cache = ActiveSupport::Cache::MemoryStore.new(expires_in: 5.minutes)
|
220
241
|
# cache.write(key, value, expires_in: 1.minute) # Set a lower value for one entry
|
221
242
|
#
|
243
|
+
# Setting <tt>:version</tt> verifies the cache stored under <tt>name</tt>
|
244
|
+
# is of the same version. nil is returned on mismatches despite contents.
|
245
|
+
# This feature is used to support recyclable cache keys.
|
246
|
+
#
|
222
247
|
# Setting <tt>:race_condition_ttl</tt> is very useful in situations where
|
223
248
|
# a cache entry is used very frequently and is under heavy load. If a
|
224
249
|
# cache expires and due to heavy load several different processes will try
|
@@ -287,6 +312,7 @@ module ActiveSupport
|
|
287
312
|
instrument(:read, name, options) do |payload|
|
288
313
|
cached_entry = read_entry(key, options) unless options[:force]
|
289
314
|
entry = handle_expired_entry(cached_entry, key, options)
|
315
|
+
entry = nil if entry && entry.mismatched?(normalize_version(name, options))
|
290
316
|
payload[:super_operation] = :fetch if payload
|
291
317
|
payload[:hit] = !!entry if payload
|
292
318
|
end
|
@@ -303,21 +329,30 @@ module ActiveSupport
|
|
303
329
|
end
|
304
330
|
end
|
305
331
|
|
306
|
-
#
|
332
|
+
# Reads data from the cache, using the given key. If there is data in
|
307
333
|
# the cache with the given key, then that data is returned. Otherwise,
|
308
334
|
# +nil+ is returned.
|
309
335
|
#
|
336
|
+
# Note, if data was written with the <tt>:expires_in<tt> or <tt>:version</tt> options,
|
337
|
+
# both of these conditions are applied before the data is returned.
|
338
|
+
#
|
310
339
|
# Options are passed to the underlying cache implementation.
|
311
340
|
def read(name, options = nil)
|
312
341
|
options = merged_options(options)
|
313
|
-
key
|
342
|
+
key = normalize_key(name, options)
|
343
|
+
version = normalize_version(name, options)
|
344
|
+
|
314
345
|
instrument(:read, name, options) do |payload|
|
315
346
|
entry = read_entry(key, options)
|
347
|
+
|
316
348
|
if entry
|
317
349
|
if entry.expired?
|
318
350
|
delete_entry(key, options)
|
319
351
|
payload[:hit] = false if payload
|
320
352
|
nil
|
353
|
+
elsif entry.mismatched?(version)
|
354
|
+
payload[:hit] = false if payload
|
355
|
+
nil
|
321
356
|
else
|
322
357
|
payload[:hit] = true if payload
|
323
358
|
entry.value
|
@@ -339,19 +374,24 @@ module ActiveSupport
|
|
339
374
|
options = names.extract_options!
|
340
375
|
options = merged_options(options)
|
341
376
|
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
entry = read_entry(key, options)
|
346
|
-
if entry
|
347
|
-
if entry.expired?
|
348
|
-
delete_entry(key, options)
|
349
|
-
else
|
350
|
-
results[name] = entry.value
|
351
|
-
end
|
377
|
+
instrument :read_multi, names, options do |payload|
|
378
|
+
read_multi_entries(names, options).tap do |results|
|
379
|
+
payload[:hits] = results.keys
|
352
380
|
end
|
353
381
|
end
|
354
|
-
|
382
|
+
end
|
383
|
+
|
384
|
+
# Cache Storage API to write multiple values at once.
|
385
|
+
def write_multi(hash, options = nil)
|
386
|
+
options = merged_options(options)
|
387
|
+
|
388
|
+
instrument :write_multi, hash, options do |payload|
|
389
|
+
entries = hash.each_with_object({}) do |(name, value), memo|
|
390
|
+
memo[normalize_key(name, options)] = Entry.new(value, options.merge(version: normalize_version(name, options)))
|
391
|
+
end
|
392
|
+
|
393
|
+
write_multi_entries entries, options
|
394
|
+
end
|
355
395
|
end
|
356
396
|
|
357
397
|
# Fetches data from the cache, using the given keys. If there is data in
|
@@ -378,13 +418,19 @@ module ActiveSupport
|
|
378
418
|
|
379
419
|
options = names.extract_options!
|
380
420
|
options = merged_options(options)
|
381
|
-
results = read_multi(*names, options)
|
382
421
|
|
383
|
-
names
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
422
|
+
instrument :read_multi, names, options do |payload|
|
423
|
+
read_multi_entries(names, options).tap do |results|
|
424
|
+
payload[:hits] = results.keys
|
425
|
+
payload[:super_operation] = :fetch_multi
|
426
|
+
|
427
|
+
writes = {}
|
428
|
+
|
429
|
+
(names - results.keys).each do |name|
|
430
|
+
results[name] = writes[name] = yield(name)
|
431
|
+
end
|
432
|
+
|
433
|
+
write_multi writes, options
|
388
434
|
end
|
389
435
|
end
|
390
436
|
end
|
@@ -396,7 +442,7 @@ module ActiveSupport
|
|
396
442
|
options = merged_options(options)
|
397
443
|
|
398
444
|
instrument(:write, name, options) do
|
399
|
-
entry = Entry.new(value, options)
|
445
|
+
entry = Entry.new(value, options.merge(version: normalize_version(name, options)))
|
400
446
|
write_entry(normalize_key(name, options), entry, options)
|
401
447
|
end
|
402
448
|
end
|
@@ -420,7 +466,7 @@ module ActiveSupport
|
|
420
466
|
|
421
467
|
instrument(:exist?, name) do
|
422
468
|
entry = read_entry(normalize_key(name, options), options)
|
423
|
-
(entry && !entry.expired?) || false
|
469
|
+
(entry && !entry.expired? && !entry.mismatched?(normalize_version(name, options))) || false
|
424
470
|
end
|
425
471
|
end
|
426
472
|
|
@@ -502,6 +548,36 @@ module ActiveSupport
|
|
502
548
|
raise NotImplementedError.new
|
503
549
|
end
|
504
550
|
|
551
|
+
# Reads multiple entries from the cache implementation. Subclasses MAY
|
552
|
+
# implement this method.
|
553
|
+
def read_multi_entries(names, options)
|
554
|
+
results = {}
|
555
|
+
names.each do |name|
|
556
|
+
key = normalize_key(name, options)
|
557
|
+
version = normalize_version(name, options)
|
558
|
+
entry = read_entry(key, options)
|
559
|
+
|
560
|
+
if entry
|
561
|
+
if entry.expired?
|
562
|
+
delete_entry(key, options)
|
563
|
+
elsif entry.mismatched?(version)
|
564
|
+
# Skip mismatched versions
|
565
|
+
else
|
566
|
+
results[name] = entry.value
|
567
|
+
end
|
568
|
+
end
|
569
|
+
end
|
570
|
+
results
|
571
|
+
end
|
572
|
+
|
573
|
+
# Writes multiple entries to the cache implementation. Subclasses MAY
|
574
|
+
# implement this method.
|
575
|
+
def write_multi_entries(hash, options)
|
576
|
+
hash.each do |key, entry|
|
577
|
+
write_entry key, entry, options
|
578
|
+
end
|
579
|
+
end
|
580
|
+
|
505
581
|
# Deletes an entry from the cache implementation. Subclasses must
|
506
582
|
# implement this method.
|
507
583
|
def delete_entry(key, options)
|
@@ -517,6 +593,36 @@ module ActiveSupport
|
|
517
593
|
end
|
518
594
|
end
|
519
595
|
|
596
|
+
# Expands and namespaces the cache key. May be overridden by
|
597
|
+
# cache stores to do additional normalization.
|
598
|
+
def normalize_key(key, options = nil)
|
599
|
+
namespace_key expanded_key(key), options
|
600
|
+
end
|
601
|
+
|
602
|
+
# Prefix the key with a namespace string:
|
603
|
+
#
|
604
|
+
# namespace_key 'foo', namespace: 'cache'
|
605
|
+
# # => 'cache:foo'
|
606
|
+
#
|
607
|
+
# With a namespace block:
|
608
|
+
#
|
609
|
+
# namespace_key 'foo', namespace: -> { 'cache' }
|
610
|
+
# # => 'cache:foo'
|
611
|
+
def namespace_key(key, options = nil)
|
612
|
+
options = merged_options(options)
|
613
|
+
namespace = options[:namespace]
|
614
|
+
|
615
|
+
if namespace.respond_to?(:call)
|
616
|
+
namespace = namespace.call
|
617
|
+
end
|
618
|
+
|
619
|
+
if namespace
|
620
|
+
"#{namespace}:#{key}"
|
621
|
+
else
|
622
|
+
key
|
623
|
+
end
|
624
|
+
end
|
625
|
+
|
520
626
|
# Expands key to be a consistent string value. Invokes +cache_key+ if
|
521
627
|
# object responds to +cache_key+. Otherwise, +to_param+ method will be
|
522
628
|
# called. If the key is a Hash, then keys will be sorted alphabetically.
|
@@ -537,14 +643,16 @@ module ActiveSupport
|
|
537
643
|
key.to_param
|
538
644
|
end
|
539
645
|
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
key
|
547
|
-
key
|
646
|
+
def normalize_version(key, options = nil)
|
647
|
+
(options && options[:version].try(:to_param)) || expanded_version(key)
|
648
|
+
end
|
649
|
+
|
650
|
+
def expanded_version(key)
|
651
|
+
case
|
652
|
+
when key.respond_to?(:cache_version) then key.cache_version.to_param
|
653
|
+
when key.is_a?(Array) then key.map { |element| expanded_version(element) }.compact.to_param
|
654
|
+
when key.respond_to?(:to_a) then expanded_version(key.to_a)
|
655
|
+
end
|
548
656
|
end
|
549
657
|
|
550
658
|
def instrument(operation, key, options = nil)
|
@@ -591,34 +699,37 @@ module ActiveSupport
|
|
591
699
|
end
|
592
700
|
end
|
593
701
|
|
594
|
-
# This class is used to represent cache entries. Cache entries have a value
|
595
|
-
# expiration time. The expiration time is used to support the :race_condition_ttl option
|
596
|
-
# on the cache.
|
702
|
+
# This class is used to represent cache entries. Cache entries have a value, an optional
|
703
|
+
# expiration time, and an optional version. The expiration time is used to support the :race_condition_ttl option
|
704
|
+
# on the cache. The version is used to support the :version option on the cache for rejecting
|
705
|
+
# mismatches.
|
597
706
|
#
|
598
707
|
# Since cache entries in most instances will be serialized, the internals of this class are highly optimized
|
599
708
|
# using short instance variable names that are lazily defined.
|
600
709
|
class Entry # :nodoc:
|
601
|
-
|
710
|
+
attr_reader :version
|
602
711
|
|
603
|
-
|
604
|
-
# +:compress+, +:compress_threshold+, and +:expires_in+.
|
605
|
-
def initialize(value, options = {})
|
606
|
-
if should_compress?(value, options)
|
607
|
-
@value = compress(value)
|
608
|
-
@compressed = true
|
609
|
-
else
|
610
|
-
@value = value
|
611
|
-
end
|
712
|
+
DEFAULT_COMPRESS_LIMIT = 1.kilobyte
|
612
713
|
|
714
|
+
# Creates a new cache entry for the specified value. Options supported are
|
715
|
+
# +:compress+, +:compress_threshold+, +:version+ and +:expires_in+.
|
716
|
+
def initialize(value, compress: true, compress_threshold: DEFAULT_COMPRESS_LIMIT, version: nil, expires_in: nil, **)
|
717
|
+
@value = value
|
718
|
+
@version = version
|
613
719
|
@created_at = Time.now.to_f
|
614
|
-
@expires_in =
|
615
|
-
|
720
|
+
@expires_in = expires_in && expires_in.to_f
|
721
|
+
|
722
|
+
compress!(compress_threshold) if compress
|
616
723
|
end
|
617
724
|
|
618
725
|
def value
|
619
726
|
compressed? ? uncompress(@value) : @value
|
620
727
|
end
|
621
728
|
|
729
|
+
def mismatched?(version)
|
730
|
+
@version && version && @version != version
|
731
|
+
end
|
732
|
+
|
622
733
|
# Checks if the entry is expired. The +expires_in+ parameter can override
|
623
734
|
# the value set when the entry was created.
|
624
735
|
def expired?
|
@@ -640,17 +751,13 @@ module ActiveSupport
|
|
640
751
|
# Returns the size of the cached value. This could be less than
|
641
752
|
# <tt>value.size</tt> if the data is compressed.
|
642
753
|
def size
|
643
|
-
|
644
|
-
|
754
|
+
case value
|
755
|
+
when NilClass
|
756
|
+
0
|
757
|
+
when String
|
758
|
+
@value.bytesize
|
645
759
|
else
|
646
|
-
|
647
|
-
when NilClass
|
648
|
-
0
|
649
|
-
when String
|
650
|
-
@value.bytesize
|
651
|
-
else
|
652
|
-
@s = Marshal.dump(@value).bytesize
|
653
|
-
end
|
760
|
+
@s ||= Marshal.dump(@value).bytesize
|
654
761
|
end
|
655
762
|
end
|
656
763
|
|
@@ -667,23 +774,30 @@ module ActiveSupport
|
|
667
774
|
end
|
668
775
|
|
669
776
|
private
|
670
|
-
def
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
777
|
+
def compress!(compress_threshold)
|
778
|
+
case @value
|
779
|
+
when nil, true, false, Numeric
|
780
|
+
uncompressed_size = 0
|
781
|
+
when String
|
782
|
+
uncompressed_size = @value.bytesize
|
783
|
+
else
|
784
|
+
serialized = Marshal.dump(@value)
|
785
|
+
uncompressed_size = serialized.bytesize
|
676
786
|
end
|
677
787
|
|
678
|
-
|
679
|
-
|
788
|
+
if uncompressed_size >= compress_threshold
|
789
|
+
serialized ||= Marshal.dump(@value)
|
790
|
+
compressed = Zlib::Deflate.deflate(serialized)
|
680
791
|
|
681
|
-
|
682
|
-
|
792
|
+
if compressed.bytesize < uncompressed_size
|
793
|
+
@value = compressed
|
794
|
+
@compressed = true
|
795
|
+
end
|
796
|
+
end
|
683
797
|
end
|
684
798
|
|
685
|
-
def
|
686
|
-
|
799
|
+
def compressed?
|
800
|
+
defined?(@compressed)
|
687
801
|
end
|
688
802
|
|
689
803
|
def uncompress(value)
|