activesupport 5.1.6 → 5.2.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activesupport might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +325 -576
- data/MIT-LICENSE +1 -1
- data/README.rdoc +3 -3
- 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/file_store.rb +5 -4
- data/lib/active_support/cache/mem_cache_store.rb +37 -27
- 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 +454 -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/cache.rb +181 -64
- data/lib/active_support/callbacks.rb +28 -39
- data/lib/active_support/concern.rb +3 -1
- data/lib/active_support/concurrency/share_lock.rb +2 -0
- data/lib/active_support/configurable.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/array.rb +2 -0
- data/lib/active_support/core_ext/benchmark.rb +2 -0
- data/lib/active_support/core_ext/big_decimal/conversions.rb +2 -0
- data/lib/active_support/core_ext/big_decimal.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/class.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.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/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/date_time.rb +2 -0
- data/lib/active_support/core_ext/digest/uuid.rb +3 -1
- data/lib/active_support/core_ext/enumerable.rb +3 -1
- data/lib/active_support/core_ext/file/atomic.rb +2 -0
- data/lib/active_support/core_ext/file.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/hash.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/integer.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/kernel.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/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/module.rb +3 -0
- data/lib/active_support/core_ext/name_error.rb +7 -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/numeric.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/object.rb +2 -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 -0
- 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/range.rb +3 -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/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/string.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/time.rb +2 -0
- data/lib/active_support/core_ext/uri.rb +4 -1
- data/lib/active_support/core_ext.rb +3 -1
- data/lib/active_support/current_attributes.rb +195 -0
- data/lib/active_support/dependencies/autoload.rb +2 -0
- data/lib/active_support/dependencies/interlock.rb +2 -0
- data/lib/active_support/dependencies.rb +16 -25
- data/lib/active_support/deprecation/behaviors.rb +24 -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 +8 -8
- data/lib/active_support/deprecation/proxy_wrappers.rb +5 -2
- data/lib/active_support/deprecation/reporting.rb +5 -3
- data/lib/active_support/deprecation.rb +4 -2
- data/lib/active_support/descendants_tracker.rb +2 -0
- data/lib/active_support/digest.rb +20 -0
- data/lib/active_support/duration/iso8601_parser.rb +4 -2
- data/lib/active_support/duration/iso8601_serializer.rb +4 -2
- data/lib/active_support/duration.rb +11 -7
- 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 +4 -2
- data/lib/active_support/gzip.rb +2 -0
- data/lib/active_support/hash_with_indifferent_access.rb +41 -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/inflections.rb +20 -4
- data/lib/active_support/inflector/methods.rb +41 -24
- data/lib/active_support/inflector/transliterate.rb +17 -8
- data/lib/active_support/inflector.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/json.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/test_helper.rb +2 -0
- data/lib/active_support/log_subscriber.rb +3 -2
- 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 +2 -0
- 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/chars.rb +2 -0
- data/lib/active_support/multibyte/unicode.rb +4 -2
- data/lib/active_support/multibyte.rb +2 -0
- data/lib/active_support/notifications/fanout.rb +2 -0
- data/lib/active_support/notifications/instrumenter.rb +2 -0
- data/lib/active_support/notifications.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/number_helper.rb +2 -0
- 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 +4 -2
- 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 +2 -0
- data/lib/active_support/tagged_logging.rb +2 -0
- data/lib/active_support/test_case.rb +2 -1
- 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 +10 -1
- 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 +19 -8
- data/lib/active_support/version.rb +2 -0
- 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
- data/lib/active_support/xml_mini.rb +3 -1
- data/lib/active_support.rb +5 -13
- metadata +15 -5
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
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
377
|
+
instrument :read_multi, names, options do |payload|
|
378
|
+
read_multi_entries(names, options).tap do |results|
|
379
|
+
payload[:hits] = results.keys
|
380
|
+
end
|
381
|
+
end
|
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)))
|
352
391
|
end
|
392
|
+
|
393
|
+
write_multi_entries entries, options
|
353
394
|
end
|
354
|
-
results
|
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,25 +699,27 @@ 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
|
711
|
+
|
712
|
+
DEFAULT_COMPRESS_LIMIT = 1.kilobyte
|
602
713
|
|
603
714
|
# Creates a new cache entry for the specified value. Options supported are
|
604
715
|
# +:compress+, +:compress_threshold+, and +:expires_in+.
|
605
716
|
def initialize(value, options = {})
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
else
|
610
|
-
@value = value
|
717
|
+
@value = value
|
718
|
+
if should_compress?(options)
|
719
|
+
compress!
|
611
720
|
end
|
612
721
|
|
722
|
+
@version = options[:version]
|
613
723
|
@created_at = Time.now.to_f
|
614
724
|
@expires_in = options[:expires_in]
|
615
725
|
@expires_in = @expires_in.to_f if @expires_in
|
@@ -619,6 +729,10 @@ module ActiveSupport
|
|
619
729
|
compressed? ? uncompress(@value) : @value
|
620
730
|
end
|
621
731
|
|
732
|
+
def mismatched?(version)
|
733
|
+
@version && version && @version != version
|
734
|
+
end
|
735
|
+
|
622
736
|
# Checks if the entry is expired. The +expires_in+ parameter can override
|
623
737
|
# the value set when the entry was created.
|
624
738
|
def expired?
|
@@ -667,28 +781,31 @@ module ActiveSupport
|
|
667
781
|
end
|
668
782
|
|
669
783
|
private
|
670
|
-
def should_compress?(
|
671
|
-
if value && options
|
672
|
-
compress_threshold = options
|
673
|
-
serialized_value_size = (value.is_a?(String) ? value :
|
784
|
+
def should_compress?(options)
|
785
|
+
if @value && options.fetch(:compress, true)
|
786
|
+
compress_threshold = options.fetch(:compress_threshold, DEFAULT_COMPRESS_LIMIT)
|
787
|
+
serialized_value_size = (@value.is_a?(String) ? @value : marshaled_value).bytesize
|
674
788
|
|
675
|
-
|
789
|
+
serialized_value_size >= compress_threshold
|
676
790
|
end
|
677
|
-
|
678
|
-
false
|
679
791
|
end
|
680
792
|
|
681
793
|
def compressed?
|
682
794
|
defined?(@compressed) ? @compressed : false
|
683
795
|
end
|
684
796
|
|
685
|
-
def compress
|
686
|
-
Zlib::Deflate.deflate(
|
797
|
+
def compress!
|
798
|
+
@value = Zlib::Deflate.deflate(marshaled_value)
|
799
|
+
@compressed = true
|
687
800
|
end
|
688
801
|
|
689
802
|
def uncompress(value)
|
690
803
|
Marshal.load(Zlib::Inflate.inflate(value))
|
691
804
|
end
|
805
|
+
|
806
|
+
def marshaled_value
|
807
|
+
@marshaled_value ||= Marshal.dump(@value)
|
808
|
+
end
|
692
809
|
end
|
693
810
|
end
|
694
811
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/concern"
|
2
4
|
require "active_support/descendants_tracker"
|
3
5
|
require "active_support/core_ext/array/extract_options"
|
@@ -62,8 +64,7 @@ module ActiveSupport
|
|
62
64
|
|
63
65
|
included do
|
64
66
|
extend ActiveSupport::DescendantsTracker
|
65
|
-
class_attribute :__callbacks, instance_writer: false
|
66
|
-
self.__callbacks ||= {}
|
67
|
+
class_attribute :__callbacks, instance_writer: false, default: {}
|
67
68
|
end
|
68
69
|
|
69
70
|
CALLBACK_FILTER_TYPES = [:before, :after, :around]
|
@@ -297,8 +298,8 @@ module ActiveSupport
|
|
297
298
|
@kind = kind
|
298
299
|
@filter = filter
|
299
300
|
@key = compute_identifier filter
|
300
|
-
@if = Array(options[:if])
|
301
|
-
@unless = Array(options[:unless])
|
301
|
+
@if = check_conditionals(Array(options[:if]))
|
302
|
+
@unless = check_conditionals(Array(options[:unless]))
|
302
303
|
end
|
303
304
|
|
304
305
|
def filter; @key; end
|
@@ -322,7 +323,7 @@ module ActiveSupport
|
|
322
323
|
|
323
324
|
def duplicates?(other)
|
324
325
|
case @filter
|
325
|
-
when Symbol
|
326
|
+
when Symbol
|
326
327
|
matches?(other.kind, other.filter)
|
327
328
|
else
|
328
329
|
false
|
@@ -349,9 +350,21 @@ module ActiveSupport
|
|
349
350
|
end
|
350
351
|
|
351
352
|
private
|
353
|
+
def check_conditionals(conditionals)
|
354
|
+
if conditionals.any? { |c| c.is_a?(String) }
|
355
|
+
raise ArgumentError, <<-MSG.squish
|
356
|
+
Passing string to be evaluated in :if and :unless conditional
|
357
|
+
options is not supported. Pass a symbol for an instance method,
|
358
|
+
or a lambda, proc or block, instead.
|
359
|
+
MSG
|
360
|
+
end
|
361
|
+
|
362
|
+
conditionals
|
363
|
+
end
|
364
|
+
|
352
365
|
def compute_identifier(filter)
|
353
366
|
case filter
|
354
|
-
when
|
367
|
+
when ::Proc
|
355
368
|
filter.object_id
|
356
369
|
else
|
357
370
|
filter
|
@@ -426,7 +439,6 @@ module ActiveSupport
|
|
426
439
|
# Filters support:
|
427
440
|
#
|
428
441
|
# Symbols:: A method to call.
|
429
|
-
# Strings:: Some content to evaluate.
|
430
442
|
# Procs:: A proc to call with the object.
|
431
443
|
# Objects:: An object with a <tt>before_foo</tt> method on it to call.
|
432
444
|
#
|
@@ -436,8 +448,6 @@ module ActiveSupport
|
|
436
448
|
case filter
|
437
449
|
when Symbol
|
438
450
|
new(nil, filter, [], nil)
|
439
|
-
when String
|
440
|
-
new(nil, :instance_exec, [:value], compile_lambda(filter))
|
441
451
|
when Conditionals::Value
|
442
452
|
new(filter, :call, [:target, :value], nil)
|
443
453
|
when ::Proc
|
@@ -454,10 +464,6 @@ module ActiveSupport
|
|
454
464
|
new(filter, method_to_call, [:target], nil)
|
455
465
|
end
|
456
466
|
end
|
457
|
-
|
458
|
-
def self.compile_lambda(filter)
|
459
|
-
eval("lambda { |value| #{filter} }")
|
460
|
-
end
|
461
467
|
end
|
462
468
|
|
463
469
|
# Execute before and after filters in a sequence instead of
|
@@ -512,7 +518,6 @@ module ActiveSupport
|
|
512
518
|
end
|
513
519
|
end
|
514
520
|
|
515
|
-
# An Array with a compile method.
|
516
521
|
class CallbackChain #:nodoc:#
|
517
522
|
include Enumerable
|
518
523
|
|
@@ -598,7 +603,7 @@ module ActiveSupport
|
|
598
603
|
Proc.new do |target, result_lambda|
|
599
604
|
terminate = true
|
600
605
|
catch(:abort) do
|
601
|
-
result_lambda.call
|
606
|
+
result_lambda.call
|
602
607
|
terminate = false
|
603
608
|
end
|
604
609
|
terminate
|
@@ -651,26 +656,17 @@ module ActiveSupport
|
|
651
656
|
#
|
652
657
|
# ===== Options
|
653
658
|
#
|
654
|
-
# * <tt>:if</tt> - A symbol
|
655
|
-
#
|
656
|
-
#
|
657
|
-
# * <tt>:unless</tt> - A symbol
|
658
|
-
#
|
659
|
-
#
|
659
|
+
# * <tt>:if</tt> - A symbol or an array of symbols, each naming an instance
|
660
|
+
# method or a proc; the callback will be called only when they all return
|
661
|
+
# a true value.
|
662
|
+
# * <tt>:unless</tt> - A symbol or an array of symbols, each naming an
|
663
|
+
# instance method or a proc; the callback will be called only when they
|
664
|
+
# all return a false value.
|
660
665
|
# * <tt>:prepend</tt> - If +true+, the callback will be prepended to the
|
661
666
|
# existing chain rather than appended.
|
662
667
|
def set_callback(name, *filter_list, &block)
|
663
668
|
type, filters, options = normalize_callback_params(filter_list, block)
|
664
669
|
|
665
|
-
if options[:if].is_a?(String) || options[:unless].is_a?(String)
|
666
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
667
|
-
Passing string to be evaluated in :if and :unless conditional
|
668
|
-
options is deprecated and will be removed in Rails 5.2 without
|
669
|
-
replacement. Pass a symbol for an instance method, or a lambda,
|
670
|
-
proc or block, instead.
|
671
|
-
MSG
|
672
|
-
end
|
673
|
-
|
674
670
|
self_chain = get_callbacks name
|
675
671
|
mapped = filters.map do |filter|
|
676
672
|
Callback.build(self_chain, filter, type, options)
|
@@ -695,13 +691,6 @@ module ActiveSupport
|
|
695
691
|
def skip_callback(name, *filter_list, &block)
|
696
692
|
type, filters, options = normalize_callback_params(filter_list, block)
|
697
693
|
|
698
|
-
if options[:if].is_a?(String) || options[:unless].is_a?(String)
|
699
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
700
|
-
Passing string to :if and :unless conditional options is deprecated
|
701
|
-
and will be removed in Rails 5.2 without replacement.
|
702
|
-
MSG
|
703
|
-
end
|
704
|
-
|
705
694
|
options[:raise] = true unless options.key?(:raise)
|
706
695
|
|
707
696
|
__update_callbacks(name) do |target, chain|
|
@@ -760,8 +749,8 @@ module ActiveSupport
|
|
760
749
|
# * <tt>:skip_after_callbacks_if_terminated</tt> - Determines if after
|
761
750
|
# callbacks should be terminated by the <tt>:terminator</tt> option. By
|
762
751
|
# default after callbacks are executed no matter if callback chain was
|
763
|
-
# terminated or not. This option
|
764
|
-
# option is
|
752
|
+
# terminated or not. This option has no effect if <tt>:terminator</tt>
|
753
|
+
# option is set to +nil+.
|
765
754
|
#
|
766
755
|
# * <tt>:scope</tt> - Indicates which methods should be executed when an
|
767
756
|
# object is used as a callback.
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveSupport
|
2
4
|
# A typical module looks like this:
|
3
5
|
#
|
@@ -111,7 +113,7 @@ module ActiveSupport
|
|
111
113
|
def append_features(base)
|
112
114
|
if base.instance_variable_defined?(:@_dependencies)
|
113
115
|
base.instance_variable_get(:@_dependencies) << self
|
114
|
-
|
116
|
+
false
|
115
117
|
else
|
116
118
|
return false if base < self
|
117
119
|
@_dependencies.each { |dep| base.include(dep) }
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Array
|
2
4
|
# Returns the tail of the array from +position+.
|
3
5
|
#
|
@@ -33,8 +35,8 @@ class Array
|
|
33
35
|
# people.without "Aaron", "Todd"
|
34
36
|
# # => ["David", "Rafael"]
|
35
37
|
#
|
36
|
-
# Note: This is an optimization of
|
37
|
-
# instead of
|
38
|
+
# Note: This is an optimization of <tt>Enumerable#without</tt> that uses <tt>Array#-</tt>
|
39
|
+
# instead of <tt>Array#reject</tt> for performance reasons.
|
38
40
|
def without(*elements)
|
39
41
|
self - elements
|
40
42
|
end
|
@@ -1,7 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Array
|
2
4
|
# The human way of thinking about adding stuff to the end of a list is with append.
|
3
|
-
alias_method :append,
|
5
|
+
alias_method :append, :push unless [].respond_to?(:append)
|
4
6
|
|
5
7
|
# The human way of thinking about adding stuff to the beginning of a list is with prepend.
|
6
|
-
alias_method :prepend, :unshift
|
8
|
+
alias_method :prepend, :unshift unless [].respond_to?(:prepend)
|
7
9
|
end
|