activesupport 4.2.11.3 → 5.2.8.1

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.

Files changed (256) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +435 -403
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +4 -5
  5. data/lib/active_support/all.rb +5 -3
  6. data/lib/active_support/array_inquirer.rb +48 -0
  7. data/lib/active_support/backtrace_cleaner.rb +7 -5
  8. data/lib/active_support/benchmarkable.rb +6 -4
  9. data/lib/active_support/builder.rb +3 -1
  10. data/lib/active_support/cache/file_store.rb +41 -35
  11. data/lib/active_support/cache/mem_cache_store.rb +91 -91
  12. data/lib/active_support/cache/memory_store.rb +27 -30
  13. data/lib/active_support/cache/null_store.rb +7 -8
  14. data/lib/active_support/cache/redis_cache_store.rb +466 -0
  15. data/lib/active_support/cache/strategy/local_cache.rb +67 -34
  16. data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
  17. data/lib/active_support/cache.rb +287 -196
  18. data/lib/active_support/callbacks.rb +640 -590
  19. data/lib/active_support/concern.rb +11 -5
  20. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +35 -0
  21. data/lib/active_support/concurrency/share_lock.rb +227 -0
  22. data/lib/active_support/configurable.rb +8 -5
  23. data/lib/active_support/core_ext/array/access.rb +29 -1
  24. data/lib/active_support/core_ext/array/conversions.rb +22 -18
  25. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  26. data/lib/active_support/core_ext/array/grouping.rb +11 -18
  27. data/lib/active_support/core_ext/array/inquiry.rb +19 -0
  28. data/lib/active_support/core_ext/array/prepend_and_append.rb +5 -3
  29. data/lib/active_support/core_ext/array/wrap.rb +7 -4
  30. data/lib/active_support/core_ext/array.rb +9 -6
  31. data/lib/active_support/core_ext/benchmark.rb +3 -1
  32. data/lib/active_support/core_ext/big_decimal/conversions.rb +10 -12
  33. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  34. data/lib/active_support/core_ext/class/attribute.rb +41 -22
  35. data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
  36. data/lib/active_support/core_ext/class/subclasses.rb +20 -6
  37. data/lib/active_support/core_ext/class.rb +4 -3
  38. data/lib/active_support/core_ext/date/acts_like.rb +3 -1
  39. data/lib/active_support/core_ext/date/blank.rb +14 -0
  40. data/lib/active_support/core_ext/date/calculations.rb +11 -9
  41. data/lib/active_support/core_ext/date/conversions.rb +25 -23
  42. data/lib/active_support/core_ext/date/zones.rb +4 -2
  43. data/lib/active_support/core_ext/date.rb +6 -4
  44. data/lib/active_support/core_ext/date_and_time/calculations.rb +170 -58
  45. data/lib/active_support/core_ext/date_and_time/compatibility.rb +4 -3
  46. data/lib/active_support/core_ext/date_and_time/zones.rb +12 -12
  47. data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
  48. data/lib/active_support/core_ext/date_time/blank.rb +14 -0
  49. data/lib/active_support/core_ext/date_time/calculations.rb +36 -18
  50. data/lib/active_support/core_ext/date_time/compatibility.rb +8 -6
  51. data/lib/active_support/core_ext/date_time/conversions.rb +16 -12
  52. data/lib/active_support/core_ext/date_time.rb +7 -5
  53. data/lib/active_support/core_ext/digest/uuid.rb +7 -5
  54. data/lib/active_support/core_ext/digest.rb +3 -0
  55. data/lib/active_support/core_ext/enumerable.rb +101 -33
  56. data/lib/active_support/core_ext/file/atomic.rb +38 -31
  57. data/lib/active_support/core_ext/file.rb +3 -1
  58. data/lib/active_support/core_ext/hash/compact.rb +14 -9
  59. data/lib/active_support/core_ext/hash/conversions.rb +62 -41
  60. data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
  61. data/lib/active_support/core_ext/hash/except.rb +11 -8
  62. data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -3
  63. data/lib/active_support/core_ext/hash/keys.rb +33 -27
  64. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  65. data/lib/active_support/core_ext/hash/slice.rb +8 -8
  66. data/lib/active_support/core_ext/hash/transform_values.rb +14 -5
  67. data/lib/active_support/core_ext/hash.rb +11 -9
  68. data/lib/active_support/core_ext/integer/inflections.rb +3 -1
  69. data/lib/active_support/core_ext/integer/multiple.rb +2 -0
  70. data/lib/active_support/core_ext/integer/time.rb +11 -18
  71. data/lib/active_support/core_ext/integer.rb +5 -3
  72. data/lib/active_support/core_ext/kernel/agnostics.rb +2 -0
  73. data/lib/active_support/core_ext/kernel/concern.rb +5 -1
  74. data/lib/active_support/core_ext/kernel/reporting.rb +4 -84
  75. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  76. data/lib/active_support/core_ext/kernel.rb +6 -5
  77. data/lib/active_support/core_ext/load_error.rb +3 -22
  78. data/lib/active_support/core_ext/marshal.rb +8 -8
  79. data/lib/active_support/core_ext/module/aliasing.rb +6 -44
  80. data/lib/active_support/core_ext/module/anonymous.rb +12 -1
  81. data/lib/active_support/core_ext/module/attr_internal.rb +8 -9
  82. data/lib/active_support/core_ext/module/attribute_accessors.rb +43 -40
  83. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +150 -0
  84. data/lib/active_support/core_ext/module/concerning.rb +11 -12
  85. data/lib/active_support/core_ext/module/delegation.rb +98 -36
  86. data/lib/active_support/core_ext/module/deprecation.rb +4 -2
  87. data/lib/active_support/core_ext/module/introspection.rb +9 -9
  88. data/lib/active_support/core_ext/module/reachable.rb +5 -2
  89. data/lib/active_support/core_ext/module/redefine_method.rb +49 -0
  90. data/lib/active_support/core_ext/module/remove_method.rb +8 -3
  91. data/lib/active_support/core_ext/module.rb +14 -11
  92. data/lib/active_support/core_ext/name_error.rb +22 -2
  93. data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
  94. data/lib/active_support/core_ext/numeric/conversions.rb +78 -81
  95. data/lib/active_support/core_ext/numeric/inquiry.rb +28 -0
  96. data/lib/active_support/core_ext/numeric/time.rb +35 -23
  97. data/lib/active_support/core_ext/numeric.rb +6 -3
  98. data/lib/active_support/core_ext/object/acts_like.rb +12 -1
  99. data/lib/active_support/core_ext/object/blank.rb +27 -2
  100. data/lib/active_support/core_ext/object/conversions.rb +6 -4
  101. data/lib/active_support/core_ext/object/deep_dup.rb +13 -4
  102. data/lib/active_support/core_ext/object/duplicable.rb +41 -14
  103. data/lib/active_support/core_ext/object/inclusion.rb +5 -3
  104. data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
  105. data/lib/active_support/core_ext/object/json.rb +49 -19
  106. data/lib/active_support/core_ext/object/to_param.rb +3 -1
  107. data/lib/active_support/core_ext/object/to_query.rb +10 -5
  108. data/lib/active_support/core_ext/object/try.rb +69 -21
  109. data/lib/active_support/core_ext/object/with_options.rb +16 -3
  110. data/lib/active_support/core_ext/object.rb +14 -13
  111. data/lib/active_support/core_ext/range/compare_range.rb +61 -0
  112. data/lib/active_support/core_ext/range/conversions.rb +27 -7
  113. data/lib/active_support/core_ext/range/each.rb +19 -17
  114. data/lib/active_support/core_ext/range/include_range.rb +2 -22
  115. data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -0
  116. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  117. data/lib/active_support/core_ext/range.rb +7 -4
  118. data/lib/active_support/core_ext/regexp.rb +6 -0
  119. data/lib/active_support/core_ext/securerandom.rb +25 -0
  120. data/lib/active_support/core_ext/string/access.rb +8 -6
  121. data/lib/active_support/core_ext/string/behavior.rb +3 -1
  122. data/lib/active_support/core_ext/string/conversions.rb +7 -4
  123. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  124. data/lib/active_support/core_ext/string/filters.rb +6 -5
  125. data/lib/active_support/core_ext/string/indent.rb +6 -4
  126. data/lib/active_support/core_ext/string/inflections.rb +61 -24
  127. data/lib/active_support/core_ext/string/inquiry.rb +3 -1
  128. data/lib/active_support/core_ext/string/multibyte.rb +15 -7
  129. data/lib/active_support/core_ext/string/output_safety.rb +62 -38
  130. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
  131. data/lib/active_support/core_ext/string/strip.rb +4 -5
  132. data/lib/active_support/core_ext/string/zones.rb +4 -2
  133. data/lib/active_support/core_ext/string.rb +15 -13
  134. data/lib/active_support/core_ext/time/acts_like.rb +3 -1
  135. data/lib/active_support/core_ext/time/calculations.rb +85 -51
  136. data/lib/active_support/core_ext/time/compatibility.rb +4 -2
  137. data/lib/active_support/core_ext/time/conversions.rb +20 -13
  138. data/lib/active_support/core_ext/time/zones.rb +41 -7
  139. data/lib/active_support/core_ext/time.rb +7 -6
  140. data/lib/active_support/core_ext/uri.rb +6 -8
  141. data/lib/active_support/core_ext.rb +3 -1
  142. data/lib/active_support/current_attributes.rb +195 -0
  143. data/lib/active_support/dependencies/autoload.rb +2 -0
  144. data/lib/active_support/dependencies/interlock.rb +57 -0
  145. data/lib/active_support/dependencies.rb +152 -161
  146. data/lib/active_support/deprecation/behaviors.rb +44 -11
  147. data/lib/active_support/deprecation/constant_accessor.rb +52 -0
  148. data/lib/active_support/deprecation/instance_delegator.rb +17 -2
  149. data/lib/active_support/deprecation/method_wrappers.rb +66 -20
  150. data/lib/active_support/deprecation/proxy_wrappers.rb +56 -28
  151. data/lib/active_support/deprecation/reporting.rb +32 -12
  152. data/lib/active_support/deprecation.rb +12 -9
  153. data/lib/active_support/descendants_tracker.rb +2 -0
  154. data/lib/active_support/digest.rb +20 -0
  155. data/lib/active_support/duration/iso8601_parser.rb +125 -0
  156. data/lib/active_support/duration/iso8601_serializer.rb +55 -0
  157. data/lib/active_support/duration.rb +314 -38
  158. data/lib/active_support/encrypted_configuration.rb +49 -0
  159. data/lib/active_support/encrypted_file.rb +99 -0
  160. data/lib/active_support/evented_file_update_checker.rb +205 -0
  161. data/lib/active_support/execution_wrapper.rb +131 -0
  162. data/lib/active_support/executor.rb +8 -0
  163. data/lib/active_support/file_update_checker.rb +63 -37
  164. data/lib/active_support/gem_version.rb +6 -4
  165. data/lib/active_support/gzip.rb +7 -5
  166. data/lib/active_support/hash_with_indifferent_access.rb +123 -28
  167. data/lib/active_support/i18n.rb +8 -6
  168. data/lib/active_support/i18n_railtie.rb +37 -13
  169. data/lib/active_support/inflections.rb +13 -11
  170. data/lib/active_support/inflector/inflections.rb +61 -12
  171. data/lib/active_support/inflector/methods.rb +163 -136
  172. data/lib/active_support/inflector/transliterate.rb +48 -27
  173. data/lib/active_support/inflector.rb +7 -5
  174. data/lib/active_support/json/decoding.rb +16 -13
  175. data/lib/active_support/json/encoding.rb +11 -58
  176. data/lib/active_support/json.rb +4 -2
  177. data/lib/active_support/key_generator.rb +25 -25
  178. data/lib/active_support/lazy_load_hooks.rb +50 -20
  179. data/lib/active_support/locale/en.yml +2 -0
  180. data/lib/active_support/log_subscriber/test_helper.rb +14 -12
  181. data/lib/active_support/log_subscriber.rb +13 -10
  182. data/lib/active_support/logger.rb +8 -7
  183. data/lib/active_support/logger_silence.rb +6 -4
  184. data/lib/active_support/logger_thread_safe_level.rb +7 -5
  185. data/lib/active_support/message_encryptor.rb +168 -53
  186. data/lib/active_support/message_verifier.rb +150 -17
  187. data/lib/active_support/messages/metadata.rb +71 -0
  188. data/lib/active_support/messages/rotation_configuration.rb +22 -0
  189. data/lib/active_support/messages/rotator.rb +56 -0
  190. data/lib/active_support/multibyte/chars.rb +36 -23
  191. data/lib/active_support/multibyte/unicode.rb +100 -96
  192. data/lib/active_support/multibyte.rb +4 -2
  193. data/lib/active_support/notifications/fanout.rb +11 -9
  194. data/lib/active_support/notifications/instrumenter.rb +27 -7
  195. data/lib/active_support/notifications.rb +11 -7
  196. data/lib/active_support/number_helper/number_converter.rb +13 -11
  197. data/lib/active_support/number_helper/number_to_currency_converter.rb +9 -9
  198. data/lib/active_support/number_helper/number_to_delimited_converter.rb +9 -3
  199. data/lib/active_support/number_helper/number_to_human_converter.rb +11 -9
  200. data/lib/active_support/number_helper/number_to_human_size_converter.rb +9 -8
  201. data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
  202. data/lib/active_support/number_helper/number_to_phone_converter.rb +13 -4
  203. data/lib/active_support/number_helper/number_to_rounded_converter.rb +23 -56
  204. data/lib/active_support/number_helper/rounding_helper.rb +66 -0
  205. data/lib/active_support/number_helper.rb +94 -68
  206. data/lib/active_support/option_merger.rb +3 -1
  207. data/lib/active_support/ordered_hash.rb +6 -4
  208. data/lib/active_support/ordered_options.rb +23 -5
  209. data/lib/active_support/per_thread_registry.rb +9 -4
  210. data/lib/active_support/proxy_object.rb +2 -0
  211. data/lib/active_support/rails.rb +16 -8
  212. data/lib/active_support/railtie.rb +43 -9
  213. data/lib/active_support/reloader.rb +131 -0
  214. data/lib/active_support/rescuable.rb +108 -53
  215. data/lib/active_support/security_utils.rb +15 -11
  216. data/lib/active_support/string_inquirer.rb +11 -3
  217. data/lib/active_support/subscriber.rb +21 -16
  218. data/lib/active_support/tagged_logging.rb +14 -11
  219. data/lib/active_support/test_case.rb +19 -47
  220. data/lib/active_support/testing/assertions.rb +137 -20
  221. data/lib/active_support/testing/autorun.rb +4 -2
  222. data/lib/active_support/testing/constant_lookup.rb +2 -1
  223. data/lib/active_support/testing/declarative.rb +3 -1
  224. data/lib/active_support/testing/deprecation.rb +14 -10
  225. data/lib/active_support/testing/file_fixtures.rb +36 -0
  226. data/lib/active_support/testing/isolation.rb +34 -25
  227. data/lib/active_support/testing/method_call_assertions.rb +43 -0
  228. data/lib/active_support/testing/setup_and_teardown.rb +13 -8
  229. data/lib/active_support/testing/stream.rb +44 -0
  230. data/lib/active_support/testing/tagged_logging.rb +3 -1
  231. data/lib/active_support/testing/time_helpers.rb +81 -15
  232. data/lib/active_support/time.rb +14 -12
  233. data/lib/active_support/time_with_zone.rb +169 -39
  234. data/lib/active_support/values/time_zone.rb +196 -61
  235. data/lib/active_support/values/unicode_tables.dat +0 -0
  236. data/lib/active_support/version.rb +3 -1
  237. data/lib/active_support/xml_mini/jdom.rb +116 -114
  238. data/lib/active_support/xml_mini/libxml.rb +16 -13
  239. data/lib/active_support/xml_mini/libxmlsax.rb +15 -14
  240. data/lib/active_support/xml_mini/nokogiri.rb +14 -12
  241. data/lib/active_support/xml_mini/nokogirisax.rb +14 -13
  242. data/lib/active_support/xml_mini/rexml.rb +11 -9
  243. data/lib/active_support/xml_mini.rb +37 -37
  244. data/lib/active_support.rb +12 -11
  245. metadata +57 -27
  246. data/lib/active_support/concurrency/latch.rb +0 -27
  247. data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -16
  248. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
  249. data/lib/active_support/core_ext/date_time/zones.rb +0 -6
  250. data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
  251. data/lib/active_support/core_ext/module/method_transplanting.rb +0 -13
  252. data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
  253. data/lib/active_support/core_ext/object/itself.rb +0 -15
  254. data/lib/active_support/core_ext/struct.rb +0 -6
  255. data/lib/active_support/core_ext/thread.rb +0 -86
  256. data/lib/active_support/core_ext/time/marshal.rb +0 -30
@@ -1,29 +1,29 @@
1
- require 'benchmark'
2
- require 'zlib'
3
- require 'active_support/core_ext/array/extract_options'
4
- require 'active_support/core_ext/array/wrap'
5
- require 'active_support/core_ext/benchmark'
6
- require 'active_support/core_ext/module/attribute_accessors'
7
- require 'active_support/core_ext/numeric/bytes'
8
- require 'active_support/core_ext/numeric/time'
9
- require 'active_support/core_ext/object/to_param'
10
- require 'active_support/core_ext/string/inflections'
11
- require 'active_support/deprecation'
1
+ # frozen_string_literal: true
2
+
3
+ require "zlib"
4
+ require "active_support/core_ext/array/extract_options"
5
+ require "active_support/core_ext/array/wrap"
6
+ require "active_support/core_ext/module/attribute_accessors"
7
+ require "active_support/core_ext/numeric/bytes"
8
+ require "active_support/core_ext/numeric/time"
9
+ require "active_support/core_ext/object/to_param"
10
+ require "active_support/core_ext/string/inflections"
12
11
 
13
12
  module ActiveSupport
14
13
  # See ActiveSupport::Cache::Store for documentation.
15
14
  module Cache
16
- autoload :FileStore, 'active_support/cache/file_store'
17
- autoload :MemoryStore, 'active_support/cache/memory_store'
18
- autoload :MemCacheStore, 'active_support/cache/mem_cache_store'
19
- autoload :NullStore, 'active_support/cache/null_store'
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"
20
20
 
21
21
  # These options mean something to all cache implementations. Individual cache
22
22
  # implementations may support additional options.
23
23
  UNIVERSAL_OPTIONS = [:namespace, :compress, :compress_threshold, :expires_in, :race_condition_ttl]
24
24
 
25
25
  module Strategy
26
- autoload :LocalCache, 'active_support/cache/strategy/local_cache'
26
+ autoload :LocalCache, "active_support/cache/strategy/local_cache"
27
27
  end
28
28
 
29
29
  class << self
@@ -73,12 +73,12 @@ module ActiveSupport
73
73
  # each of elements in the array will be turned into parameters/keys and
74
74
  # concatenated into a single key. For example:
75
75
  #
76
- # expand_cache_key([:foo, :bar]) # => "foo/bar"
77
- # expand_cache_key([:foo, :bar], "namespace") # => "namespace/foo/bar"
76
+ # ActiveSupport::Cache.expand_cache_key([:foo, :bar]) # => "foo/bar"
77
+ # ActiveSupport::Cache.expand_cache_key([:foo, :bar], "namespace") # => "namespace/foo/bar"
78
78
  #
79
79
  # The +key+ argument can also respond to +cache_key+ or +to_param+.
80
80
  def expand_cache_key(key, namespace = nil)
81
- expanded_cache_key = namespace ? "#{namespace}/" : ""
81
+ expanded_cache_key = (namespace ? "#{namespace}/" : "").dup
82
82
 
83
83
  if prefix = ENV["RAILS_CACHE_ID"] || ENV["RAILS_APP_VERSION"]
84
84
  expanded_cache_key << "#{prefix}/"
@@ -91,16 +91,19 @@ module ActiveSupport
91
91
  private
92
92
  def retrieve_cache_key(key)
93
93
  case
94
- when key.respond_to?(:cache_key) then key.cache_key
95
- when key.is_a?(Array) then key.map { |element| retrieve_cache_key(element) }.to_param
96
- when key.respond_to?(:to_a) then retrieve_cache_key(key.to_a)
97
- else key.to_param
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
98
99
  end.to_s
99
100
  end
100
101
 
101
102
  # Obtains the specified cache store class, given the name of the +store+.
102
103
  # Raises an error when the store class cannot be found.
103
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.
104
107
  require "active_support/cache/#{store}"
105
108
  rescue LoadError => e
106
109
  raise "Could not find cache store adapter for #{store} (#{e})"
@@ -146,32 +149,48 @@ module ActiveSupport
146
149
  # cache.namespace = -> { @last_mod_time } # Set the namespace to a variable
147
150
  # @last_mod_time = Time.now # Invalidate the entire cache by changing namespace
148
151
  #
149
- # Caches can also store values in a compressed format to save space and
150
- # reduce time spent sending data. Since there is overhead, values must be
151
- # large enough to warrant compression. To turn on compression either pass
152
- # <tt>compress: true</tt> in the initializer or as an option to +fetch+
153
- # or +write+. To specify the threshold at which to compress values, set the
154
- # <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.
155
157
  class Store
156
- cattr_accessor :logger, :instance_writer => true
158
+ cattr_accessor :logger, instance_writer: true
157
159
 
158
160
  attr_reader :silence, :options
159
161
  alias :silence? :silence
160
162
 
161
- # Create a new cache. The options will be passed to any write method calls
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
+
180
+ # Creates a new cache. The options will be passed to any write method calls
162
181
  # except for <tt>:namespace</tt> which can be used to set the global
163
182
  # namespace for the cache.
164
183
  def initialize(options = nil)
165
184
  @options = options ? options.dup : {}
166
185
  end
167
186
 
168
- # Silence the logger.
187
+ # Silences the logger.
169
188
  def silence!
170
189
  @silence = true
171
190
  self
172
191
  end
173
192
 
174
- # Silence the logger within a block.
193
+ # Silences the logger within a block.
175
194
  def mute
176
195
  previous_silence, @silence = defined?(@silence) && @silence, true
177
196
  yield
@@ -179,18 +198,6 @@ module ActiveSupport
179
198
  @silence = previous_silence
180
199
  end
181
200
 
182
- # :deprecated:
183
- def self.instrument=(boolean)
184
- ActiveSupport::Deprecation.warn "ActiveSupport::Cache.instrument= is deprecated and will be removed in Rails 5. Instrumentation is now always on so you can safely stop using it."
185
- true
186
- end
187
-
188
- # :deprecated:
189
- def self.instrument
190
- ActiveSupport::Deprecation.warn "ActiveSupport::Cache.instrument is deprecated and will be removed in Rails 5. Instrumentation is now always on so you can safely stop using it."
191
- true
192
- end
193
-
194
201
  # Fetches data from the cache, using the given key. If there is data in
195
202
  # the cache with the given key, then that data is returned.
196
203
  #
@@ -210,13 +217,19 @@ module ActiveSupport
210
217
  # cache.fetch('city') # => "Duckburgh"
211
218
  #
212
219
  # You may also specify additional options via the +options+ argument.
213
- # Setting <tt>force: true</tt> will force a cache miss:
220
+ # Setting <tt>force: true</tt> forces a cache "miss," meaning we treat
221
+ # the cache value as missing even if it's present. Passing a block is
222
+ # required when +force+ is true so this always results in a cache write.
214
223
  #
215
224
  # cache.write('today', 'Monday')
216
- # cache.fetch('today', force: true) # => nil
225
+ # cache.fetch('today', force: true) { 'Tuesday' } # => 'Tuesday'
226
+ # cache.fetch('today', force: true) # => ArgumentError
227
+ #
228
+ # The +:force+ option is useful when you're calling some other method to
229
+ # ask whether you should force a cache write. Otherwise, it's clearer to
230
+ # just call <tt>Cache#write</tt>.
217
231
  #
218
- # Setting <tt>:compress</tt> will store a large cache entry set by the call
219
- # in a compressed format.
232
+ # Setting <tt>compress: false</tt> disables compression of the cache entry.
220
233
  #
221
234
  # Setting <tt>:expires_in</tt> will set an expiration time on the cache.
222
235
  # All caches support auto-expiring content after a specified number of
@@ -227,6 +240,10 @@ module ActiveSupport
227
240
  # cache = ActiveSupport::Cache::MemoryStore.new(expires_in: 5.minutes)
228
241
  # cache.write(key, value, expires_in: 1.minute) # Set a lower value for one entry
229
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
+ #
230
247
  # Setting <tt>:race_condition_ttl</tt> is very useful in situations where
231
248
  # a cache entry is used very frequently and is under heavy load. If a
232
249
  # cache expires and due to heavy load several different processes will try
@@ -255,22 +272,23 @@ module ActiveSupport
255
272
  # sleep 60
256
273
  #
257
274
  # Thread.new do
258
- # val_1 = cache.fetch('foo', race_condition_ttl: 10) do
275
+ # val_1 = cache.fetch('foo', race_condition_ttl: 10.seconds) do
259
276
  # sleep 1
260
277
  # 'new value 1'
261
278
  # end
262
279
  # end
263
280
  #
264
281
  # Thread.new do
265
- # val_2 = cache.fetch('foo', race_condition_ttl: 10) do
282
+ # val_2 = cache.fetch('foo', race_condition_ttl: 10.seconds) do
266
283
  # 'new value 2'
267
284
  # end
268
285
  # end
269
286
  #
270
- # # val_1 => "new value 1"
271
- # # val_2 => "original value"
272
- # # sleep 10 # First thread extend the life of cache by another 10 seconds
273
- # # cache.fetch('foo') => "new value 1"
287
+ # cache.fetch('foo') # => "original value"
288
+ # sleep 10 # First thread extended the life of cache by another 10 seconds
289
+ # cache.fetch('foo') # => "new value 1"
290
+ # val_1 # => "new value 1"
291
+ # val_2 # => "original value"
274
292
  #
275
293
  # Other options will be handled by the specific cache store implementation.
276
294
  # Internally, #fetch calls #read_entry, and calls #write_entry on a cache
@@ -288,36 +306,53 @@ module ActiveSupport
288
306
  def fetch(name, options = nil)
289
307
  if block_given?
290
308
  options = merged_options(options)
291
- key = namespaced_key(name, options)
309
+ key = normalize_key(name, options)
292
310
 
293
- cached_entry = find_cached_entry(key, name, options) unless options[:force]
294
- entry = handle_expired_entry(cached_entry, key, options)
311
+ entry = nil
312
+ instrument(:read, name, options) do |payload|
313
+ cached_entry = read_entry(key, options) unless options[:force]
314
+ entry = handle_expired_entry(cached_entry, key, options)
315
+ entry = nil if entry && entry.mismatched?(normalize_version(name, options))
316
+ payload[:super_operation] = :fetch if payload
317
+ payload[:hit] = !!entry if payload
318
+ end
295
319
 
296
320
  if entry
297
321
  get_entry_value(entry, name, options)
298
322
  else
299
323
  save_block_result_to_cache(name, options) { |_name| yield _name }
300
324
  end
325
+ elsif options && options[:force]
326
+ raise ArgumentError, "Missing block: Calling `Cache#fetch` with `force: true` requires a block."
301
327
  else
302
328
  read(name, options)
303
329
  end
304
330
  end
305
331
 
306
- # Fetches data from the cache, using the given key. If there is data in
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 = namespaced_key(name, options)
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
@@ -329,7 +364,7 @@ module ActiveSupport
329
364
  end
330
365
  end
331
366
 
332
- # Read multiple values at once from the cache. Options can be passed
367
+ # Reads multiple values at once from the cache. Options can be passed
333
368
  # in the last argument.
334
369
  #
335
370
  # Some cache implementation may optimize this method.
@@ -338,44 +373,64 @@ module ActiveSupport
338
373
  def read_multi(*names)
339
374
  options = names.extract_options!
340
375
  options = merged_options(options)
341
- results = {}
342
- names.each do |name|
343
- key = namespaced_key(name, options)
344
- entry = read_entry(key, options)
345
- if entry
346
- if entry.expired?
347
- delete_entry(key, options)
348
- else
349
- results[name] = entry.value
350
- end
376
+
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)))
351
391
  end
392
+
393
+ write_multi_entries entries, options
352
394
  end
353
- results
354
395
  end
355
396
 
356
397
  # Fetches data from the cache, using the given keys. If there is data in
357
398
  # the cache with the given keys, then that data is returned. Otherwise,
358
399
  # the supplied block is called for each key for which there was no data,
359
400
  # and the result will be written to the cache and returned.
401
+ # Therefore, you need to pass a block that returns the data to be written
402
+ # to the cache. If you do not want to write the cache when the cache is
403
+ # not found, use #read_multi.
360
404
  #
361
405
  # Options are passed to the underlying cache implementation.
362
406
  #
363
407
  # Returns a hash with the data for each of the names. For example:
364
408
  #
365
409
  # cache.write("bim", "bam")
366
- # cache.fetch_multi("bim", "boom") { |key| key * 2 }
367
- # # => { "bam" => "bam", "boom" => "boomboom" }
410
+ # cache.fetch_multi("bim", "unknown_key") do |key|
411
+ # "Fallback value for key: #{key}"
412
+ # end
413
+ # # => { "bim" => "bam",
414
+ # # "unknown_key" => "Fallback value for key: unknown_key" }
368
415
  #
369
416
  def fetch_multi(*names)
417
+ raise ArgumentError, "Missing block: `Cache#fetch_multi` requires a block." unless block_given?
418
+
370
419
  options = names.extract_options!
371
420
  options = merged_options(options)
372
- results = read_multi(*names, options)
373
421
 
374
- names.each_with_object({}) do |name, memo|
375
- memo[name] = results.fetch(name) do
376
- value = yield name
377
- write(name, value, options)
378
- value
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
379
434
  end
380
435
  end
381
436
  end
@@ -387,8 +442,8 @@ module ActiveSupport
387
442
  options = merged_options(options)
388
443
 
389
444
  instrument(:write, name, options) do
390
- entry = Entry.new(value, options)
391
- write_entry(namespaced_key(name, options), entry, options)
445
+ entry = Entry.new(value, options.merge(version: normalize_version(name, options)))
446
+ write_entry(normalize_key(name, options), entry, options)
392
447
  end
393
448
  end
394
449
 
@@ -399,7 +454,7 @@ module ActiveSupport
399
454
  options = merged_options(options)
400
455
 
401
456
  instrument(:delete, name) do
402
- delete_entry(namespaced_key(name, options), options)
457
+ delete_entry(normalize_key(name, options), options)
403
458
  end
404
459
  end
405
460
 
@@ -410,12 +465,12 @@ module ActiveSupport
410
465
  options = merged_options(options)
411
466
 
412
467
  instrument(:exist?, name) do
413
- entry = read_entry(namespaced_key(name, options), options)
414
- (entry && !entry.expired?) || false
468
+ entry = read_entry(normalize_key(name, options), options)
469
+ (entry && !entry.expired? && !entry.mismatched?(normalize_version(name, options))) || false
415
470
  end
416
471
  end
417
472
 
418
- # Delete all entries with keys matching the pattern.
473
+ # Deletes all entries with keys matching the pattern.
419
474
  #
420
475
  # Options are passed to the underlying cache implementation.
421
476
  #
@@ -424,7 +479,7 @@ module ActiveSupport
424
479
  raise NotImplementedError.new("#{self.class.name} does not support delete_matched")
425
480
  end
426
481
 
427
- # Increment an integer value in the cache.
482
+ # Increments an integer value in the cache.
428
483
  #
429
484
  # Options are passed to the underlying cache implementation.
430
485
  #
@@ -433,7 +488,7 @@ module ActiveSupport
433
488
  raise NotImplementedError.new("#{self.class.name} does not support increment")
434
489
  end
435
490
 
436
- # Decrement an integer value in the cache.
491
+ # Decrements an integer value in the cache.
437
492
  #
438
493
  # Options are passed to the underlying cache implementation.
439
494
  #
@@ -442,7 +497,7 @@ module ActiveSupport
442
497
  raise NotImplementedError.new("#{self.class.name} does not support decrement")
443
498
  end
444
499
 
445
- # Cleanup the cache by removing expired entries.
500
+ # Cleanups the cache by removing expired entries.
446
501
  #
447
502
  # Options are passed to the underlying cache implementation.
448
503
  #
@@ -451,7 +506,7 @@ module ActiveSupport
451
506
  raise NotImplementedError.new("#{self.class.name} does not support cleanup")
452
507
  end
453
508
 
454
- # Clear the entire cache. Be careful with this method since it could
509
+ # Clears the entire cache. Be careful with this method since it could
455
510
  # affect other processes if shared cache is being used.
456
511
  #
457
512
  # The options hash is passed to the underlying cache implementation.
@@ -461,16 +516,16 @@ module ActiveSupport
461
516
  raise NotImplementedError.new("#{self.class.name} does not support clear")
462
517
  end
463
518
 
464
- protected
465
- # Add the namespace defined in the options to a pattern designed to
519
+ private
520
+ # Adds the namespace defined in the options to a pattern designed to
466
521
  # match keys. Implementations that support delete_matched should call
467
522
  # this method to translate a pattern that matches names into one that
468
523
  # matches namespaced keys.
469
- def key_matcher(pattern, options)
524
+ def key_matcher(pattern, options) # :doc:
470
525
  prefix = options[:namespace].is_a?(Proc) ? options[:namespace].call : options[:namespace]
471
526
  if prefix
472
527
  source = pattern.source
473
- if source.start_with?('^')
528
+ if source.start_with?("^")
474
529
  source = source[1, source.length]
475
530
  else
476
531
  source = ".*#{source[0, source.length]}"
@@ -481,27 +536,56 @@ module ActiveSupport
481
536
  end
482
537
  end
483
538
 
484
- # Read an entry from the cache implementation. Subclasses must implement
539
+ # Reads an entry from the cache implementation. Subclasses must implement
485
540
  # this method.
486
- def read_entry(key, options) # :nodoc:
541
+ def read_entry(key, options)
487
542
  raise NotImplementedError.new
488
543
  end
489
544
 
490
- # Write an entry to the cache implementation. Subclasses must implement
545
+ # Writes an entry to the cache implementation. Subclasses must implement
491
546
  # this method.
492
- def write_entry(key, entry, options) # :nodoc:
547
+ def write_entry(key, entry, options)
493
548
  raise NotImplementedError.new
494
549
  end
495
550
 
496
- # Delete an entry from the cache implementation. Subclasses must
551
+ # Reads multiple entries from the cache implementation. Subclasses MAY
497
552
  # implement this method.
498
- def delete_entry(key, options) # :nodoc:
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
+
581
+ # Deletes an entry from the cache implementation. Subclasses must
582
+ # implement this method.
583
+ def delete_entry(key, options)
499
584
  raise NotImplementedError.new
500
585
  end
501
586
 
502
- private
503
- # Merge the default options with ones specific to a method call.
504
- def merged_options(call_options) # :nodoc:
587
+ # Merges the default options with ones specific to a method call.
588
+ def merged_options(call_options)
505
589
  if call_options
506
590
  options.merge(call_options)
507
591
  else
@@ -509,64 +593,89 @@ module ActiveSupport
509
593
  end
510
594
  end
511
595
 
512
- # Expand key to be a consistent string value. Invoke +cache_key+ if
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
+
626
+ # Expands key to be a consistent string value. Invokes +cache_key+ if
513
627
  # object responds to +cache_key+. Otherwise, +to_param+ method will be
514
628
  # called. If the key is a Hash, then keys will be sorted alphabetically.
515
- def expanded_key(key) # :nodoc:
629
+ def expanded_key(key)
516
630
  return key.cache_key.to_s if key.respond_to?(:cache_key)
517
631
 
518
632
  case key
519
633
  when Array
520
634
  if key.size > 1
521
- key = key.collect{|element| expanded_key(element)}
635
+ key = key.collect { |element| expanded_key(element) }
522
636
  else
523
637
  key = key.first
524
638
  end
525
639
  when Hash
526
- key = key.sort_by { |k,_| k.to_s }.collect{|k,v| "#{k}=#{v}"}
640
+ key = key.sort_by { |k, _| k.to_s }.collect { |k, v| "#{k}=#{v}" }
527
641
  end
528
642
 
529
643
  key.to_param
530
644
  end
531
645
 
532
- # Prefix a key with the namespace. Namespace and key will be delimited
533
- # with a colon.
534
- def namespaced_key(key, options)
535
- key = expanded_key(key)
536
- namespace = options[:namespace] if options
537
- prefix = namespace.is_a?(Proc) ? namespace.call : namespace
538
- key = "#{prefix}:#{key}" if prefix
539
- 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
540
656
  end
541
657
 
542
658
  def instrument(operation, key, options = nil)
543
- log(operation, key, options)
659
+ log { "Cache #{operation}: #{normalize_key(key, options)}#{options.blank? ? "" : " (#{options.inspect})"}" }
544
660
 
545
- payload = { :key => key }
661
+ payload = { key: key }
546
662
  payload.merge!(options) if options.is_a?(Hash)
547
- ActiveSupport::Notifications.instrument("cache_#{operation}.active_support", payload){ yield(payload) }
663
+ ActiveSupport::Notifications.instrument("cache_#{operation}.active_support", payload) { yield(payload) }
548
664
  end
549
665
 
550
- def log(operation, key, options = nil)
666
+ def log
551
667
  return unless logger && logger.debug? && !silence?
552
- logger.debug("Cache #{operation}: #{key}#{options.blank? ? "" : " (#{options.inspect})"}")
553
- end
554
-
555
- def find_cached_entry(key, name, options)
556
- instrument(:read, name, options) do |payload|
557
- payload[:super_operation] = :fetch if payload
558
- read_entry(key, options)
559
- end
668
+ logger.debug(yield)
560
669
  end
561
670
 
562
671
  def handle_expired_entry(entry, key, options)
563
672
  if entry && entry.expired?
564
673
  race_ttl = options[:race_condition_ttl].to_i
565
674
  if (race_ttl > 0) && (Time.now.to_f - entry.expires_at <= race_ttl)
566
- # When an entry has :race_condition_ttl defined, put the stale entry back into the cache
567
- # for a brief period while the entry is begin recalculated.
675
+ # When an entry has a positive :race_condition_ttl defined, put the stale entry back into the cache
676
+ # for a brief period while the entry is being recalculated.
568
677
  entry.expires_at = Time.now + race_ttl
569
- write_entry(key, entry, :expires_in => race_ttl * 2)
678
+ write_entry(key, entry, expires_in: race_ttl * 2)
570
679
  else
571
680
  delete_entry(key, options)
572
681
  end
@@ -576,12 +685,12 @@ module ActiveSupport
576
685
  end
577
686
 
578
687
  def get_entry_value(entry, name, options)
579
- instrument(:fetch_hit, name, options) { |payload| }
688
+ instrument(:fetch_hit, name, options) {}
580
689
  entry.value
581
690
  end
582
691
 
583
692
  def save_block_result_to_cache(name, options)
584
- result = instrument(:generate, name, options) do |payload|
693
+ result = instrument(:generate, name, options) do
585
694
  yield(name)
586
695
  end
587
696
 
@@ -590,39 +699,40 @@ module ActiveSupport
590
699
  end
591
700
  end
592
701
 
593
- # This class is used to represent cache entries. Cache entries have a value and an optional
594
- # expiration time. The expiration time is used to support the :race_condition_ttl option
595
- # 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.
596
706
  #
597
707
  # Since cache entries in most instances will be serialized, the internals of this class are highly optimized
598
708
  # using short instance variable names that are lazily defined.
599
709
  class Entry # :nodoc:
600
- DEFAULT_COMPRESS_LIMIT = 16.kilobytes
601
-
602
- # Create a new cache entry for the specified value. Options supported are
603
- # +:compress+, +:compress_threshold+, and +:expires_in+.
604
- def initialize(value, options = {})
605
- if should_compress?(value, options)
606
- @value = compress(value)
607
- @compressed = true
608
- else
609
- @value = value
610
- end
710
+ attr_reader :version
711
+
712
+ DEFAULT_COMPRESS_LIMIT = 1.kilobyte
611
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
612
719
  @created_at = Time.now.to_f
613
- @expires_in = options[:expires_in]
614
- @expires_in = @expires_in.to_f if @expires_in
720
+ @expires_in = expires_in && expires_in.to_f
721
+
722
+ compress!(compress_threshold) if compress
615
723
  end
616
724
 
617
725
  def value
618
- convert_version_4beta1_entry! if defined?(@v)
619
726
  compressed? ? uncompress(@value) : @value
620
727
  end
621
728
 
622
- # Check if the entry is expired. The +expires_in+ parameter can override
729
+ def mismatched?(version)
730
+ @version && version && @version != version
731
+ end
732
+
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?
625
- convert_version_4beta1_entry! if defined?(@v)
626
736
  @expires_in && @created_at + @expires_in <= Time.now.to_f
627
737
  end
628
738
 
@@ -641,25 +751,19 @@ module ActiveSupport
641
751
  # Returns the size of the cached value. This could be less than
642
752
  # <tt>value.size</tt> if the data is compressed.
643
753
  def size
644
- if defined?(@s)
645
- @s
754
+ case value
755
+ when NilClass
756
+ 0
757
+ when String
758
+ @value.bytesize
646
759
  else
647
- case value
648
- when NilClass
649
- 0
650
- when String
651
- @value.bytesize
652
- else
653
- @s = Marshal.dump(@value).bytesize
654
- end
760
+ @s ||= Marshal.dump(@value).bytesize
655
761
  end
656
762
  end
657
763
 
658
- # Duplicate the value in a class. This is used by cache implementations that don't natively
764
+ # Duplicates the value in a class. This is used by cache implementations that don't natively
659
765
  # serialize entries to protect against accidental cache modifications.
660
766
  def dup_value!
661
- convert_version_4beta1_entry! if defined?(@v)
662
-
663
767
  if @value && !compressed? && !(@value.is_a?(Numeric) || @value == true || @value == false)
664
768
  if @value.is_a?(String)
665
769
  @value = @value.dup
@@ -670,48 +774,35 @@ module ActiveSupport
670
774
  end
671
775
 
672
776
  private
673
- def should_compress?(value, options)
674
- if value && options[:compress]
675
- compress_threshold = options[:compress_threshold] || DEFAULT_COMPRESS_LIMIT
676
- serialized_value_size = (value.is_a?(String) ? value : Marshal.dump(value)).bytesize
677
-
678
- return true if serialized_value_size >= compress_threshold
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
679
786
  end
680
787
 
681
- false
682
- end
788
+ if uncompressed_size >= compress_threshold
789
+ serialized ||= Marshal.dump(@value)
790
+ compressed = Zlib::Deflate.deflate(serialized)
683
791
 
684
- def compressed?
685
- defined?(@compressed) ? @compressed : false
792
+ if compressed.bytesize < uncompressed_size
793
+ @value = compressed
794
+ @compressed = true
795
+ end
796
+ end
686
797
  end
687
798
 
688
- def compress(value)
689
- Zlib::Deflate.deflate(Marshal.dump(value))
799
+ def compressed?
800
+ defined?(@compressed)
690
801
  end
691
802
 
692
803
  def uncompress(value)
693
804
  Marshal.load(Zlib::Inflate.inflate(value))
694
805
  end
695
-
696
- # The internals of this method changed between Rails 3.x and 4.0. This method provides the glue
697
- # to ensure that cache entries created under the old version still work with the new class definition.
698
- def convert_version_4beta1_entry!
699
- if defined?(@v)
700
- @value = @v
701
- remove_instance_variable(:@v)
702
- end
703
-
704
- if defined?(@c)
705
- @compressed = @c
706
- remove_instance_variable(:@c)
707
- end
708
-
709
- if defined?(@x) && @x
710
- @created_at ||= Time.now.to_f
711
- @expires_in = @x - @created_at
712
- remove_instance_variable(:@x)
713
- end
714
- end
715
806
  end
716
807
  end
717
808
  end