activesupport 4.2.11.3 → 5.0.0.beta1

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 (174) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +309 -485
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +2 -3
  5. data/lib/active_support.rb +8 -15
  6. data/lib/active_support/array_inquirer.rb +44 -0
  7. data/lib/active_support/backtrace_cleaner.rb +1 -1
  8. data/lib/active_support/cache.rb +59 -72
  9. data/lib/active_support/cache/file_store.rb +27 -19
  10. data/lib/active_support/cache/mem_cache_store.rb +71 -60
  11. data/lib/active_support/cache/memory_store.rb +16 -21
  12. data/lib/active_support/cache/null_store.rb +1 -4
  13. data/lib/active_support/cache/strategy/local_cache.rb +31 -20
  14. data/lib/active_support/callbacks.rb +107 -111
  15. data/lib/active_support/concern.rb +1 -1
  16. data/lib/active_support/concurrency/latch.rb +7 -15
  17. data/lib/active_support/concurrency/share_lock.rb +142 -0
  18. data/lib/active_support/configurable.rb +1 -0
  19. data/lib/active_support/core_ext.rb +2 -1
  20. data/lib/active_support/core_ext/array.rb +1 -0
  21. data/lib/active_support/core_ext/array/access.rb +13 -1
  22. data/lib/active_support/core_ext/array/conversions.rb +6 -4
  23. data/lib/active_support/core_ext/array/inquiry.rb +17 -0
  24. data/lib/active_support/core_ext/array/wrap.rb +5 -4
  25. data/lib/active_support/core_ext/big_decimal/conversions.rb +8 -10
  26. data/lib/active_support/core_ext/class.rb +0 -1
  27. data/lib/active_support/core_ext/class/attribute.rb +10 -9
  28. data/lib/active_support/core_ext/class/subclasses.rb +5 -2
  29. data/lib/active_support/core_ext/date.rb +1 -1
  30. data/lib/active_support/core_ext/date/blank.rb +12 -0
  31. data/lib/active_support/core_ext/date/calculations.rb +1 -1
  32. data/lib/active_support/core_ext/date/conversions.rb +3 -3
  33. data/lib/active_support/core_ext/date_and_time/calculations.rb +93 -27
  34. data/lib/active_support/core_ext/date_and_time/zones.rb +1 -2
  35. data/lib/active_support/core_ext/date_time.rb +1 -1
  36. data/lib/active_support/core_ext/date_time/blank.rb +12 -0
  37. data/lib/active_support/core_ext/date_time/calculations.rb +7 -23
  38. data/lib/active_support/core_ext/date_time/conversions.rb +2 -0
  39. data/lib/active_support/core_ext/enumerable.rb +27 -17
  40. data/lib/active_support/core_ext/file/atomic.rb +30 -25
  41. data/lib/active_support/core_ext/hash/compact.rb +15 -19
  42. data/lib/active_support/core_ext/hash/conversions.rb +21 -2
  43. data/lib/active_support/core_ext/hash/deep_merge.rb +1 -1
  44. data/lib/active_support/core_ext/hash/except.rb +9 -8
  45. data/lib/active_support/core_ext/hash/indifferent_access.rb +1 -1
  46. data/lib/active_support/core_ext/hash/keys.rb +22 -18
  47. data/lib/active_support/core_ext/hash/slice.rb +1 -1
  48. data/lib/active_support/core_ext/hash/transform_values.rb +13 -7
  49. data/lib/active_support/core_ext/integer/time.rb +1 -1
  50. data/lib/active_support/core_ext/kernel.rb +0 -1
  51. data/lib/active_support/core_ext/kernel/debugger.rb +3 -10
  52. data/lib/active_support/core_ext/kernel/reporting.rb +0 -84
  53. data/lib/active_support/core_ext/load_error.rb +4 -2
  54. data/lib/active_support/core_ext/marshal.rb +8 -13
  55. data/lib/active_support/core_ext/module.rb +1 -0
  56. data/lib/active_support/core_ext/module/aliasing.rb +6 -1
  57. data/lib/active_support/core_ext/module/anonymous.rb +10 -1
  58. data/lib/active_support/core_ext/module/attr_internal.rb +2 -5
  59. data/lib/active_support/core_ext/module/attribute_accessors.rb +7 -7
  60. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +141 -0
  61. data/lib/active_support/core_ext/module/concerning.rb +4 -4
  62. data/lib/active_support/core_ext/module/delegation.rb +7 -14
  63. data/lib/active_support/core_ext/module/method_transplanting.rb +3 -13
  64. data/lib/active_support/core_ext/module/qualified_const.rb +30 -12
  65. data/lib/active_support/core_ext/module/remove_method.rb +23 -0
  66. data/lib/active_support/core_ext/name_error.rb +15 -2
  67. data/lib/active_support/core_ext/numeric.rb +1 -0
  68. data/lib/active_support/core_ext/numeric/bytes.rb +20 -0
  69. data/lib/active_support/core_ext/numeric/conversions.rb +12 -23
  70. data/lib/active_support/core_ext/numeric/inquiry.rb +26 -0
  71. data/lib/active_support/core_ext/numeric/time.rb +20 -0
  72. data/lib/active_support/core_ext/object.rb +0 -1
  73. data/lib/active_support/core_ext/object/blank.rb +11 -2
  74. data/lib/active_support/core_ext/object/deep_dup.rb +10 -3
  75. data/lib/active_support/core_ext/object/duplicable.rb +39 -70
  76. data/lib/active_support/core_ext/object/inclusion.rb +2 -2
  77. data/lib/active_support/core_ext/object/instance_variables.rb +1 -1
  78. data/lib/active_support/core_ext/object/json.rb +9 -7
  79. data/lib/active_support/core_ext/object/to_query.rb +1 -1
  80. data/lib/active_support/core_ext/object/try.rb +67 -21
  81. data/lib/active_support/core_ext/object/with_options.rb +1 -1
  82. data/lib/active_support/core_ext/range/conversions.rb +18 -6
  83. data/lib/active_support/core_ext/range/each.rb +16 -18
  84. data/lib/active_support/core_ext/range/include_range.rb +20 -20
  85. data/lib/active_support/core_ext/securerandom.rb +23 -0
  86. data/lib/active_support/core_ext/string/access.rb +1 -1
  87. data/lib/active_support/core_ext/string/behavior.rb +1 -1
  88. data/lib/active_support/core_ext/string/conversions.rb +2 -2
  89. data/lib/active_support/core_ext/string/filters.rb +1 -2
  90. data/lib/active_support/core_ext/string/inflections.rb +23 -5
  91. data/lib/active_support/core_ext/string/multibyte.rb +11 -7
  92. data/lib/active_support/core_ext/string/output_safety.rb +8 -9
  93. data/lib/active_support/core_ext/string/strip.rb +3 -6
  94. data/lib/active_support/core_ext/struct.rb +3 -6
  95. data/lib/active_support/core_ext/time.rb +0 -2
  96. data/lib/active_support/core_ext/time/calculations.rb +18 -16
  97. data/lib/active_support/core_ext/time/conversions.rb +4 -2
  98. data/lib/active_support/core_ext/time/marshal.rb +2 -29
  99. data/lib/active_support/core_ext/time/zones.rb +19 -3
  100. data/lib/active_support/core_ext/uri.rb +1 -3
  101. data/lib/active_support/dependencies.rb +79 -44
  102. data/lib/active_support/dependencies/interlock.rb +47 -0
  103. data/lib/active_support/deprecation/behaviors.rb +12 -0
  104. data/lib/active_support/deprecation/method_wrappers.rb +42 -16
  105. data/lib/active_support/deprecation/proxy_wrappers.rb +47 -24
  106. data/lib/active_support/deprecation/reporting.rb +13 -2
  107. data/lib/active_support/duration.rb +5 -8
  108. data/lib/active_support/evented_file_update_checker.rb +150 -0
  109. data/lib/active_support/file_update_checker.rb +1 -1
  110. data/lib/active_support/gem_version.rb +5 -5
  111. data/lib/active_support/hash_with_indifferent_access.rb +15 -17
  112. data/lib/active_support/i18n_railtie.rb +25 -4
  113. data/lib/active_support/inflector/inflections.rb +36 -5
  114. data/lib/active_support/inflector/methods.rb +87 -89
  115. data/lib/active_support/inflector/transliterate.rb +36 -21
  116. data/lib/active_support/json/decoding.rb +2 -8
  117. data/lib/active_support/json/encoding.rb +0 -50
  118. data/lib/active_support/key_generator.rb +4 -4
  119. data/lib/active_support/log_subscriber.rb +1 -1
  120. data/lib/active_support/log_subscriber/test_helper.rb +3 -3
  121. data/lib/active_support/logger.rb +4 -52
  122. data/lib/active_support/logger_silence.rb +3 -5
  123. data/lib/active_support/message_encryptor.rb +4 -11
  124. data/lib/active_support/message_verifier.rb +64 -8
  125. data/lib/active_support/multibyte/chars.rb +12 -3
  126. data/lib/active_support/multibyte/unicode.rb +6 -8
  127. data/lib/active_support/notifications.rb +2 -2
  128. data/lib/active_support/notifications/fanout.rb +5 -5
  129. data/lib/active_support/notifications/instrumenter.rb +19 -2
  130. data/lib/active_support/number_helper.rb +21 -15
  131. data/lib/active_support/number_helper/number_to_currency_converter.rb +4 -4
  132. data/lib/active_support/number_helper/number_to_delimited_converter.rb +7 -2
  133. data/lib/active_support/number_helper/number_to_human_converter.rb +6 -4
  134. data/lib/active_support/number_helper/number_to_human_size_converter.rb +5 -1
  135. data/lib/active_support/number_helper/number_to_percentage_converter.rb +1 -1
  136. data/lib/active_support/number_helper/number_to_rounded_converter.rb +28 -25
  137. data/lib/active_support/ordered_options.rb +15 -1
  138. data/lib/active_support/per_thread_registry.rb +3 -0
  139. data/lib/active_support/rails.rb +2 -2
  140. data/lib/active_support/railtie.rb +6 -1
  141. data/lib/active_support/rescuable.rb +4 -4
  142. data/lib/active_support/security_utils.rb +0 -7
  143. data/lib/active_support/string_inquirer.rb +1 -1
  144. data/lib/active_support/subscriber.rb +5 -10
  145. data/lib/active_support/tagged_logging.rb +3 -1
  146. data/lib/active_support/test_case.rb +13 -25
  147. data/lib/active_support/testing/assertions.rb +15 -13
  148. data/lib/active_support/testing/autorun.rb +8 -1
  149. data/lib/active_support/testing/composite_filter.rb +54 -0
  150. data/lib/active_support/testing/deprecation.rb +9 -8
  151. data/lib/active_support/testing/file_fixtures.rb +34 -0
  152. data/lib/active_support/testing/isolation.rb +22 -8
  153. data/lib/active_support/testing/method_call_assertions.rb +41 -0
  154. data/lib/active_support/testing/stream.rb +42 -0
  155. data/lib/active_support/testing/time_helpers.rb +6 -6
  156. data/lib/active_support/time_with_zone.rb +135 -53
  157. data/lib/active_support/values/time_zone.rb +80 -46
  158. data/lib/active_support/values/unicode_tables.dat +0 -0
  159. data/lib/active_support/xml_mini.rb +15 -30
  160. data/lib/active_support/xml_mini/jdom.rb +1 -1
  161. data/lib/active_support/xml_mini/libxml.rb +5 -3
  162. data/lib/active_support/xml_mini/libxmlsax.rb +4 -1
  163. data/lib/active_support/xml_mini/nokogiri.rb +5 -3
  164. data/lib/active_support/xml_mini/nokogirisax.rb +3 -1
  165. data/lib/active_support/xml_mini/rexml.rb +3 -1
  166. metadata +57 -21
  167. data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -16
  168. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
  169. data/lib/active_support/core_ext/date_and_time/compatibility.rb +0 -15
  170. data/lib/active_support/core_ext/date_time/compatibility.rb +0 -16
  171. data/lib/active_support/core_ext/object/itself.rb +0 -15
  172. data/lib/active_support/core_ext/thread.rb +0 -86
  173. data/lib/active_support/core_ext/time/compatibility.rb +0 -14
  174. data/lib/active_support/logger_thread_safe_level.rb +0 -32
@@ -1,4 +1,4 @@
1
- Copyright (c) 2005-2014 David Heinemeier Hansson
1
+ Copyright (c) 2005-2015 David Heinemeier Hansson
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
@@ -10,11 +10,11 @@ outside of Rails.
10
10
 
11
11
  The latest version of Active Support can be installed with RubyGems:
12
12
 
13
- % [sudo] gem install activesupport
13
+ $ gem install activesupport
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/4-2-stable/activesupport
17
+ * https://github.com/rails/rails/tree/master/activesupport
18
18
 
19
19
 
20
20
  == License
@@ -37,4 +37,3 @@ Bug reports can be filed for the Ruby on Rails project here:
37
37
  Feature requests should be discussed on the rails-core mailing list here:
38
38
 
39
39
  * https://groups.google.com/forum/?fromgroups#!forum/rubyonrails-core
40
-
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2014 David Heinemeier Hansson
2
+ # Copyright (c) 2005-2015 David Heinemeier Hansson
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining
5
5
  # a copy of this software and associated documentation files (the
@@ -26,7 +26,6 @@ require "active_support/dependencies/autoload"
26
26
  require "active_support/version"
27
27
  require "active_support/logger"
28
28
  require "active_support/lazy_load_hooks"
29
- require "active_support/core_ext/date_and_time/compatibility"
30
29
 
31
30
  module ActiveSupport
32
31
  extend ActiveSupport::Autoload
@@ -35,6 +34,7 @@ module ActiveSupport
35
34
  autoload :Dependencies
36
35
  autoload :DescendantsTracker
37
36
  autoload :FileUpdateChecker
37
+ autoload :EventedFileUpdateChecker
38
38
  autoload :LogSubscriber
39
39
  autoload :Notifications
40
40
 
@@ -60,6 +60,7 @@ module ActiveSupport
60
60
  autoload :StringInquirer
61
61
  autoload :TaggedLogging
62
62
  autoload :XmlMini
63
+ autoload :ArrayInquirer
63
64
  end
64
65
 
65
66
  autoload :Rescuable
@@ -72,22 +73,14 @@ module ActiveSupport
72
73
  NumberHelper.eager_load!
73
74
  end
74
75
 
75
- @@test_order = nil
76
+ cattr_accessor :test_order # :nodoc:
76
77
 
77
- def self.test_order=(new_order) # :nodoc:
78
- @@test_order = new_order
78
+ def self.halt_callback_chains_on_return_false
79
+ Callbacks.halt_and_display_warning_on_return_false
79
80
  end
80
81
 
81
- def self.test_order # :nodoc:
82
- @@test_order
83
- end
84
-
85
- def self.to_time_preserves_timezone
86
- DateAndTime::Compatibility.preserve_timezone
87
- end
88
-
89
- def self.to_time_preserves_timezone=(value)
90
- DateAndTime::Compatibility.preserve_timezone = value
82
+ def self.halt_callback_chains_on_return_false=(value)
83
+ Callbacks.halt_and_display_warning_on_return_false = value
91
84
  end
92
85
  end
93
86
 
@@ -0,0 +1,44 @@
1
+ module ActiveSupport
2
+ # Wrapping an array in an +ArrayInquirer+ gives a friendlier way to check
3
+ # its string-like contents:
4
+ #
5
+ # variants = ActiveSupport::ArrayInquirer.new([:phone, :tablet])
6
+ #
7
+ # variants.phone? # => true
8
+ # variants.tablet? # => true
9
+ # variants.desktop? # => false
10
+ class ArrayInquirer < Array
11
+ # Passes each element of +candidates+ collection to ArrayInquirer collection.
12
+ # The method returns true if at least one element is the same. If +candidates+
13
+ # collection is not given, method returns true.
14
+ #
15
+ # variants = ActiveSupport::ArrayInquirer.new([:phone, :tablet])
16
+ #
17
+ # variants.any? # => true
18
+ # variants.any?(:phone, :tablet) # => true
19
+ # variants.any?('phone', 'desktop') # => true
20
+ # variants.any?(:desktop, :watch) # => false
21
+ def any?(*candidates, &block)
22
+ if candidates.none?
23
+ super
24
+ else
25
+ candidates.any? do |candidate|
26
+ include?(candidate.to_sym) || include?(candidate.to_s)
27
+ end
28
+ end
29
+ end
30
+
31
+ private
32
+ def respond_to_missing?(name, include_private = false)
33
+ name[-1] == '?'
34
+ end
35
+
36
+ def method_missing(name, *args)
37
+ if name[-1] == '?'
38
+ any?(name[0..-2])
39
+ else
40
+ super
41
+ end
42
+ end
43
+ end
44
+ end
@@ -25,7 +25,7 @@ module ActiveSupport
25
25
  # of the backtrace, you can call <tt>BacktraceCleaner#remove_filters!</tt>
26
26
  # These two methods will give you a completely untouched backtrace.
27
27
  #
28
- # Inspired by the Quiet Backtrace gem by Thoughtbot.
28
+ # Inspired by the Quiet Backtrace gem by thoughtbot.
29
29
  class BacktraceCleaner
30
30
  def initialize
31
31
  @filters, @silencers = [], []
@@ -8,7 +8,7 @@ require 'active_support/core_ext/numeric/bytes'
8
8
  require 'active_support/core_ext/numeric/time'
9
9
  require 'active_support/core_ext/object/to_param'
10
10
  require 'active_support/core_ext/string/inflections'
11
- require 'active_support/deprecation'
11
+ require 'active_support/core_ext/string/strip'
12
12
 
13
13
  module ActiveSupport
14
14
  # See ActiveSupport::Cache::Store for documentation.
@@ -179,18 +179,6 @@ module ActiveSupport
179
179
  @silence = previous_silence
180
180
  end
181
181
 
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
182
  # Fetches data from the cache, using the given key. If there is data in
195
183
  # the cache with the given key, then that data is returned.
196
184
  #
@@ -288,15 +276,20 @@ module ActiveSupport
288
276
  def fetch(name, options = nil)
289
277
  if block_given?
290
278
  options = merged_options(options)
291
- key = namespaced_key(name, options)
279
+ key = normalize_key(name, options)
292
280
 
293
- cached_entry = find_cached_entry(key, name, options) unless options[:force]
294
- entry = handle_expired_entry(cached_entry, key, options)
281
+ instrument(:read, name, options) do |payload|
282
+ cached_entry = read_entry(key, options) unless options[:force]
283
+ payload[:super_operation] = :fetch if payload
284
+ entry = handle_expired_entry(cached_entry, key, options)
295
285
 
296
- if entry
297
- get_entry_value(entry, name, options)
298
- else
299
- save_block_result_to_cache(name, options) { |_name| yield _name }
286
+ if entry
287
+ payload[:hit] = true if payload
288
+ get_entry_value(entry, name, options)
289
+ else
290
+ payload[:hit] = false if payload
291
+ save_block_result_to_cache(name, options) { |_name| yield _name }
292
+ end
300
293
  end
301
294
  else
302
295
  read(name, options)
@@ -310,7 +303,7 @@ module ActiveSupport
310
303
  # Options are passed to the underlying cache implementation.
311
304
  def read(name, options = nil)
312
305
  options = merged_options(options)
313
- key = namespaced_key(name, options)
306
+ key = normalize_key(name, options)
314
307
  instrument(:read, name, options) do |payload|
315
308
  entry = read_entry(key, options)
316
309
  if entry
@@ -338,19 +331,22 @@ module ActiveSupport
338
331
  def read_multi(*names)
339
332
  options = names.extract_options!
340
333
  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
334
+
335
+ instrument_multi(:read, names, options) do |payload|
336
+ results = {}
337
+ names.each do |name|
338
+ key = normalize_key(name, options)
339
+ entry = read_entry(key, options)
340
+ if entry
341
+ if entry.expired?
342
+ delete_entry(key, options)
343
+ else
344
+ results[name] = entry.value
345
+ end
350
346
  end
351
347
  end
348
+ results
352
349
  end
353
- results
354
350
  end
355
351
 
356
352
  # Fetches data from the cache, using the given keys. If there is data in
@@ -363,8 +359,11 @@ module ActiveSupport
363
359
  # Returns a hash with the data for each of the names. For example:
364
360
  #
365
361
  # cache.write("bim", "bam")
366
- # cache.fetch_multi("bim", "boom") { |key| key * 2 }
367
- # # => { "bam" => "bam", "boom" => "boomboom" }
362
+ # cache.fetch_multi("bim", "unknown_key") do |key|
363
+ # "Fallback value for key: #{key}"
364
+ # end
365
+ # # => { "bim" => "bam",
366
+ # # "unknown_key" => "Fallback value for key: unknown_key" }
368
367
  #
369
368
  def fetch_multi(*names)
370
369
  options = names.extract_options!
@@ -388,7 +387,7 @@ module ActiveSupport
388
387
 
389
388
  instrument(:write, name, options) do
390
389
  entry = Entry.new(value, options)
391
- write_entry(namespaced_key(name, options), entry, options)
390
+ write_entry(normalize_key(name, options), entry, options)
392
391
  end
393
392
  end
394
393
 
@@ -399,7 +398,7 @@ module ActiveSupport
399
398
  options = merged_options(options)
400
399
 
401
400
  instrument(:delete, name) do
402
- delete_entry(namespaced_key(name, options), options)
401
+ delete_entry(normalize_key(name, options), options)
403
402
  end
404
403
  end
405
404
 
@@ -410,7 +409,7 @@ module ActiveSupport
410
409
  options = merged_options(options)
411
410
 
412
411
  instrument(:exist?, name) do
413
- entry = read_entry(namespaced_key(name, options), options)
412
+ entry = read_entry(normalize_key(name, options), options)
414
413
  (entry && !entry.expired?) || false
415
414
  end
416
415
  end
@@ -531,7 +530,7 @@ module ActiveSupport
531
530
 
532
531
  # Prefix a key with the namespace. Namespace and key will be delimited
533
532
  # with a colon.
534
- def namespaced_key(key, options)
533
+ def normalize_key(key, options)
535
534
  key = expanded_key(key)
536
535
  namespace = options[:namespace] if options
537
536
  prefix = namespace.is_a?(Proc) ? namespace.call : namespace
@@ -539,32 +538,44 @@ module ActiveSupport
539
538
  key
540
539
  end
541
540
 
541
+ def namespaced_key(*args)
542
+ ActiveSupport::Deprecation.warn(<<-MESSAGE.strip_heredoc)
543
+ `namespaced_key` is deprecated and will be removed from Rails 5.1.
544
+ Please use `normalize_key` which will return a fully resolved key.
545
+ MESSAGE
546
+ normalize_key(*args)
547
+ end
548
+
542
549
  def instrument(operation, key, options = nil)
543
- log(operation, key, options)
550
+ log { "Cache #{operation}: #{normalize_key(key, options)}#{options.blank? ? "" : " (#{options.inspect})"}" }
544
551
 
545
552
  payload = { :key => key }
546
553
  payload.merge!(options) if options.is_a?(Hash)
547
554
  ActiveSupport::Notifications.instrument("cache_#{operation}.active_support", payload){ yield(payload) }
548
555
  end
549
556
 
550
- def log(operation, key, options = nil)
551
- return unless logger && logger.debug? && !silence?
552
- logger.debug("Cache #{operation}: #{key}#{options.blank? ? "" : " (#{options.inspect})"}")
557
+ def instrument_multi(operation, keys, options = nil)
558
+ log do
559
+ formatted_keys = keys.map { |k| "- #{k}" }.join("\n")
560
+ "Caches multi #{operation}:\n#{formatted_keys}#{options.blank? ? "" : " (#{options.inspect})"}"
561
+ end
562
+
563
+ payload = { key: keys }
564
+ payload.merge!(options) if options.is_a?(Hash)
565
+ ActiveSupport::Notifications.instrument("cache_#{operation}_multi.active_support", payload) { yield(payload) }
553
566
  end
554
567
 
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
568
+ def log
569
+ return unless logger && logger.debug? && !silence?
570
+ logger.debug(yield)
560
571
  end
561
572
 
562
573
  def handle_expired_entry(entry, key, options)
563
574
  if entry && entry.expired?
564
575
  race_ttl = options[:race_condition_ttl].to_i
565
576
  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.
577
+ # When an entry has a positive :race_condition_ttl defined, put the stale entry back into the cache
578
+ # for a brief period while the entry is being recalculated.
568
579
  entry.expires_at = Time.now + race_ttl
569
580
  write_entry(key, entry, :expires_in => race_ttl * 2)
570
581
  else
@@ -615,14 +626,12 @@ module ActiveSupport
615
626
  end
616
627
 
617
628
  def value
618
- convert_version_4beta1_entry! if defined?(@v)
619
629
  compressed? ? uncompress(@value) : @value
620
630
  end
621
631
 
622
632
  # Check if the entry is expired. The +expires_in+ parameter can override
623
633
  # the value set when the entry was created.
624
634
  def expired?
625
- convert_version_4beta1_entry! if defined?(@v)
626
635
  @expires_in && @created_at + @expires_in <= Time.now.to_f
627
636
  end
628
637
 
@@ -658,8 +667,6 @@ module ActiveSupport
658
667
  # Duplicate the value in a class. This is used by cache implementations that don't natively
659
668
  # serialize entries to protect against accidental cache modifications.
660
669
  def dup_value!
661
- convert_version_4beta1_entry! if defined?(@v)
662
-
663
670
  if @value && !compressed? && !(@value.is_a?(Numeric) || @value == true || @value == false)
664
671
  if @value.is_a?(String)
665
672
  @value = @value.dup
@@ -692,26 +699,6 @@ module ActiveSupport
692
699
  def uncompress(value)
693
700
  Marshal.load(Zlib::Inflate.inflate(value))
694
701
  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
702
  end
716
703
  end
717
704
  end
@@ -10,6 +10,7 @@ module ActiveSupport
10
10
  # FileStore implements the Strategy::LocalCache strategy which implements
11
11
  # an in-memory cache inside of a block.
12
12
  class FileStore < Store
13
+ prepend Strategy::LocalCache
13
14
  attr_reader :cache_path
14
15
 
15
16
  DIR_FORMATTER = "%03X"
@@ -20,7 +21,6 @@ module ActiveSupport
20
21
  def initialize(cache_path, options = nil)
21
22
  super(options)
22
23
  @cache_path = cache_path.to_s
23
- extend Strategy::LocalCache
24
24
  end
25
25
 
26
26
  # Deletes all items from the cache. In this case it deletes all the entries in the specified
@@ -29,6 +29,7 @@ module ActiveSupport
29
29
  def clear(options = nil)
30
30
  root_dirs = Dir.entries(cache_path).reject {|f| (EXCLUDED_DIRS + [".gitkeep"]).include?(f)}
31
31
  FileUtils.rm_r(root_dirs.collect{|f| File.join(cache_path, f)})
32
+ rescue Errno::ENOENT
32
33
  end
33
34
 
34
35
  # Preemptively iterates through all stored keys and removes the ones which have expired.
@@ -59,7 +60,7 @@ module ActiveSupport
59
60
  matcher = key_matcher(matcher, options)
60
61
  search_dir(cache_path) do |path|
61
62
  key = file_path_key(path)
62
- delete_entry(key, options) if key.match(matcher)
63
+ delete_entry(path, options) if key.match(matcher)
63
64
  end
64
65
  end
65
66
  end
@@ -67,9 +68,8 @@ module ActiveSupport
67
68
  protected
68
69
 
69
70
  def read_entry(key, options)
70
- file_name = key_file_path(key)
71
- if File.exist?(file_name)
72
- File.open(file_name) { |f| Marshal.load(f) }
71
+ if File.exist?(key)
72
+ File.open(key) { |f| Marshal.load(f) }
73
73
  end
74
74
  rescue => e
75
75
  logger.error("FileStoreError (#{e}): #{e.message}") if logger
@@ -77,23 +77,21 @@ module ActiveSupport
77
77
  end
78
78
 
79
79
  def write_entry(key, entry, options)
80
- file_name = key_file_path(key)
81
- return false if options[:unless_exist] && File.exist?(file_name)
82
- ensure_cache_path(File.dirname(file_name))
83
- File.atomic_write(file_name, cache_path) {|f| Marshal.dump(entry, f)}
80
+ return false if options[:unless_exist] && File.exist?(key)
81
+ ensure_cache_path(File.dirname(key))
82
+ File.atomic_write(key, cache_path) {|f| Marshal.dump(entry, f)}
84
83
  true
85
84
  end
86
85
 
87
86
  def delete_entry(key, options)
88
- file_name = key_file_path(key)
89
- if File.exist?(file_name)
87
+ if File.exist?(key)
90
88
  begin
91
- File.delete(file_name)
92
- delete_empty_directories(File.dirname(file_name))
89
+ File.delete(key)
90
+ delete_empty_directories(File.dirname(key))
93
91
  true
94
92
  rescue => e
95
93
  # Just in case the error was caused by another process deleting the file first.
96
- raise e if File.exist?(file_name)
94
+ raise e if File.exist?(key)
97
95
  false
98
96
  end
99
97
  end
@@ -117,12 +115,14 @@ module ActiveSupport
117
115
  end
118
116
 
119
117
  # Translate a key into a file path.
120
- def key_file_path(key)
121
- if key.size > FILEPATH_MAX_SIZE
122
- key = Digest::MD5.hexdigest(key)
118
+ def normalize_key(key, options)
119
+ key = super
120
+ fname = URI.encode_www_form_component(key)
121
+
122
+ if fname.size > FILEPATH_MAX_SIZE
123
+ fname = Digest::MD5.hexdigest(key)
123
124
  end
124
125
 
125
- fname = URI.encode_www_form_component(key)
126
126
  hash = Zlib.adler32(fname)
127
127
  hash, dir_1 = hash.divmod(0x1000)
128
128
  dir_2 = hash.modulo(0x1000)
@@ -137,6 +137,14 @@ module ActiveSupport
137
137
  File.join(cache_path, DIR_FORMATTER % dir_1, DIR_FORMATTER % dir_2, *fname_paths)
138
138
  end
139
139
 
140
+ def key_file_path(key)
141
+ ActiveSupport::Deprecation.warn(<<-MESSAGE.strip_heredoc)
142
+ `key_file_path` is deprecated and will be removed from Rails 5.1.
143
+ Please use `normalize_key` which will return a fully resolved key or nothing.
144
+ MESSAGE
145
+ key
146
+ end
147
+
140
148
  # Translate a file path into a key.
141
149
  def file_path_key(path)
142
150
  fname = path[cache_path.to_s.size..-1].split(File::SEPARATOR, 4).last
@@ -173,7 +181,7 @@ module ActiveSupport
173
181
  # Modifies the amount of an already existing integer value that is stored in the cache.
174
182
  # If the key is not found nothing is done.
175
183
  def modify_value(name, amount, options)
176
- file_name = key_file_path(namespaced_key(name, options))
184
+ file_name = normalize_key(name, options)
177
185
 
178
186
  lock_file(file_name) do
179
187
  options = merged_options(options)