activesupport 4.0.13 → 4.2.11.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activesupport might be problematic. Click here for more details.

Files changed (166) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +406 -418
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +7 -2
  5. data/lib/active_support/backtrace_cleaner.rb +8 -8
  6. data/lib/active_support/benchmarkable.rb +0 -10
  7. data/lib/active_support/cache/file_store.rb +32 -22
  8. data/lib/active_support/cache/mem_cache_store.rb +5 -7
  9. data/lib/active_support/cache/memory_store.rb +1 -0
  10. data/lib/active_support/cache/strategy/local_cache.rb +11 -30
  11. data/lib/active_support/cache/strategy/local_cache_middleware.rb +44 -0
  12. data/lib/active_support/cache.rb +75 -41
  13. data/lib/active_support/callbacks.rb +482 -261
  14. data/lib/active_support/concern.rb +23 -7
  15. data/lib/active_support/configurable.rb +1 -1
  16. data/lib/active_support/core_ext/array/access.rb +11 -1
  17. data/lib/active_support/core_ext/array/conversions.rb +2 -17
  18. data/lib/active_support/core_ext/array/grouping.rb +29 -12
  19. data/lib/active_support/core_ext/array/prepend_and_append.rb +2 -2
  20. data/lib/active_support/core_ext/array.rb +0 -1
  21. data/lib/active_support/core_ext/big_decimal/conversions.rb +0 -15
  22. data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +16 -0
  23. data/lib/active_support/core_ext/class/attribute.rb +1 -2
  24. data/lib/active_support/core_ext/class/attribute_accessors.rb +4 -170
  25. data/lib/active_support/core_ext/class/delegating_attributes.rb +13 -8
  26. data/lib/active_support/core_ext/class/subclasses.rb +0 -2
  27. data/lib/active_support/core_ext/class.rb +0 -1
  28. data/lib/active_support/core_ext/date/calculations.rb +10 -0
  29. data/lib/active_support/core_ext/date/conversions.rb +9 -1
  30. data/lib/active_support/core_ext/date/zones.rb +2 -33
  31. data/lib/active_support/core_ext/date_and_time/calculations.rb +41 -11
  32. data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
  33. data/lib/active_support/core_ext/date_and_time/zones.rb +41 -0
  34. data/lib/active_support/core_ext/date_time/calculations.rb +45 -22
  35. data/lib/active_support/core_ext/date_time/compatibility.rb +16 -0
  36. data/lib/active_support/core_ext/date_time/conversions.rb +4 -2
  37. data/lib/active_support/core_ext/date_time/zones.rb +3 -21
  38. data/lib/active_support/core_ext/date_time.rb +1 -0
  39. data/lib/active_support/core_ext/digest/uuid.rb +51 -0
  40. data/lib/active_support/core_ext/enumerable.rb +17 -1
  41. data/lib/active_support/core_ext/file/atomic.rb +1 -1
  42. data/lib/active_support/core_ext/hash/compact.rb +24 -0
  43. data/lib/active_support/core_ext/hash/conversions.rb +9 -8
  44. data/lib/active_support/core_ext/hash/except.rb +8 -2
  45. data/lib/active_support/core_ext/hash/indifferent_access.rb +1 -0
  46. data/lib/active_support/core_ext/hash/keys.rb +25 -19
  47. data/lib/active_support/core_ext/hash/slice.rb +8 -2
  48. data/lib/active_support/core_ext/hash/transform_values.rb +23 -0
  49. data/lib/active_support/core_ext/hash.rb +2 -1
  50. data/lib/active_support/core_ext/integer/time.rb +0 -15
  51. data/lib/active_support/core_ext/kernel/concern.rb +10 -0
  52. data/lib/active_support/core_ext/kernel/debugger.rb +1 -1
  53. data/lib/active_support/core_ext/kernel/reporting.rb +13 -2
  54. data/lib/active_support/core_ext/kernel.rb +3 -2
  55. data/lib/active_support/core_ext/load_error.rb +4 -1
  56. data/lib/active_support/core_ext/marshal.rb +8 -5
  57. data/lib/active_support/core_ext/module/aliasing.rb +2 -2
  58. data/lib/active_support/core_ext/module/attr_internal.rb +2 -1
  59. data/lib/active_support/core_ext/module/attribute_accessors.rb +160 -14
  60. data/lib/active_support/core_ext/module/concerning.rb +135 -0
  61. data/lib/active_support/core_ext/module/delegation.rb +53 -25
  62. data/lib/active_support/core_ext/module/deprecation.rb +0 -2
  63. data/lib/active_support/core_ext/module/introspection.rb +0 -16
  64. data/lib/active_support/core_ext/module/method_transplanting.rb +13 -0
  65. data/lib/active_support/core_ext/module.rb +1 -0
  66. data/lib/active_support/core_ext/numeric/conversions.rb +11 -3
  67. data/lib/active_support/core_ext/numeric/time.rb +4 -29
  68. data/lib/active_support/core_ext/object/blank.rb +44 -18
  69. data/lib/active_support/core_ext/object/deep_dup.rb +6 -6
  70. data/lib/active_support/core_ext/object/duplicable.rb +72 -33
  71. data/lib/active_support/core_ext/object/inclusion.rb +16 -15
  72. data/lib/active_support/core_ext/object/itself.rb +15 -0
  73. data/lib/active_support/core_ext/object/json.rb +197 -0
  74. data/lib/active_support/core_ext/object/to_query.rb +14 -6
  75. data/lib/active_support/core_ext/object/try.rb +36 -14
  76. data/lib/active_support/core_ext/object/with_options.rb +30 -3
  77. data/lib/active_support/core_ext/object.rb +2 -1
  78. data/lib/active_support/core_ext/string/access.rb +35 -35
  79. data/lib/active_support/core_ext/string/conversions.rb +10 -9
  80. data/lib/active_support/core_ext/string/exclude.rb +3 -3
  81. data/lib/active_support/core_ext/string/filters.rb +51 -3
  82. data/lib/active_support/core_ext/string/inflections.rb +15 -10
  83. data/lib/active_support/core_ext/string/output_safety.rb +97 -33
  84. data/lib/active_support/core_ext/string/zones.rb +1 -0
  85. data/lib/active_support/core_ext/thread.rb +12 -5
  86. data/lib/active_support/core_ext/time/calculations.rb +47 -68
  87. data/lib/active_support/core_ext/time/compatibility.rb +14 -0
  88. data/lib/active_support/core_ext/time/conversions.rb +4 -2
  89. data/lib/active_support/core_ext/time/zones.rb +2 -20
  90. data/lib/active_support/core_ext/time.rb +1 -0
  91. data/lib/active_support/core_ext.rb +0 -1
  92. data/lib/active_support/dependencies/autoload.rb +1 -1
  93. data/lib/active_support/dependencies.rb +64 -25
  94. data/lib/active_support/deprecation/behaviors.rb +4 -4
  95. data/lib/active_support/deprecation.rb +4 -4
  96. data/lib/active_support/duration.rb +55 -11
  97. data/lib/active_support/file_update_checker.rb +1 -1
  98. data/lib/active_support/gem_version.rb +15 -0
  99. data/lib/active_support/hash_with_indifferent_access.rb +39 -11
  100. data/lib/active_support/i18n.rb +4 -4
  101. data/lib/active_support/i18n_railtie.rb +1 -7
  102. data/lib/active_support/inflections.rb +6 -1
  103. data/lib/active_support/inflector/inflections.rb +19 -19
  104. data/lib/active_support/inflector/methods.rb +66 -25
  105. data/lib/active_support/json/decoding.rb +15 -22
  106. data/lib/active_support/json/encoding.rb +125 -286
  107. data/lib/active_support/key_generator.rb +8 -10
  108. data/lib/active_support/lazy_load_hooks.rb +1 -1
  109. data/lib/active_support/log_subscriber/test_helper.rb +1 -1
  110. data/lib/active_support/logger.rb +51 -1
  111. data/lib/active_support/logger_silence.rb +7 -4
  112. data/lib/active_support/logger_thread_safe_level.rb +32 -0
  113. data/lib/active_support/message_encryptor.rb +14 -6
  114. data/lib/active_support/message_verifier.rb +16 -12
  115. data/lib/active_support/multibyte/chars.rb +2 -3
  116. data/lib/active_support/multibyte/unicode.rb +46 -58
  117. data/lib/active_support/notifications/fanout.rb +12 -7
  118. data/lib/active_support/notifications/instrumenter.rb +2 -1
  119. data/lib/active_support/notifications.rb +11 -6
  120. data/lib/active_support/number_helper/number_converter.rb +182 -0
  121. data/lib/active_support/number_helper/number_to_currency_converter.rb +46 -0
  122. data/lib/active_support/number_helper/number_to_delimited_converter.rb +23 -0
  123. data/lib/active_support/number_helper/number_to_human_converter.rb +66 -0
  124. data/lib/active_support/number_helper/number_to_human_size_converter.rb +58 -0
  125. data/lib/active_support/number_helper/number_to_percentage_converter.rb +12 -0
  126. data/lib/active_support/number_helper/number_to_phone_converter.rb +49 -0
  127. data/lib/active_support/number_helper/number_to_rounded_converter.rb +87 -0
  128. data/lib/active_support/number_helper.rb +32 -324
  129. data/lib/active_support/ordered_options.rb +8 -0
  130. data/lib/active_support/per_thread_registry.rb +13 -10
  131. data/lib/active_support/security_utils.rb +27 -0
  132. data/lib/active_support/subscriber.rb +35 -3
  133. data/lib/active_support/test_case.rb +52 -19
  134. data/lib/active_support/testing/assertions.rb +1 -31
  135. data/lib/active_support/testing/autorun.rb +2 -2
  136. data/lib/active_support/testing/constant_lookup.rb +1 -5
  137. data/lib/active_support/testing/declarative.rb +7 -21
  138. data/lib/active_support/testing/isolation.rb +29 -69
  139. data/lib/active_support/testing/setup_and_teardown.rb +17 -2
  140. data/lib/active_support/testing/tagged_logging.rb +2 -2
  141. data/lib/active_support/testing/time_helpers.rb +134 -0
  142. data/lib/active_support/time.rb +0 -2
  143. data/lib/active_support/time_with_zone.rb +60 -40
  144. data/lib/active_support/values/time_zone.rb +101 -101
  145. data/lib/active_support/values/unicode_tables.dat +0 -0
  146. data/lib/active_support/version.rb +4 -7
  147. data/lib/active_support/xml_mini/jdom.rb +6 -5
  148. data/lib/active_support/xml_mini/libxml.rb +1 -3
  149. data/lib/active_support/xml_mini/libxmlsax.rb +1 -4
  150. data/lib/active_support/xml_mini/nokogiri.rb +1 -3
  151. data/lib/active_support/xml_mini/nokogirisax.rb +1 -3
  152. data/lib/active_support/xml_mini/rexml.rb +7 -8
  153. data/lib/active_support/xml_mini.rb +33 -15
  154. data/lib/active_support.rb +27 -2
  155. metadata +43 -43
  156. data/lib/active_support/basic_object.rb +0 -11
  157. data/lib/active_support/buffered_logger.rb +0 -21
  158. data/lib/active_support/core_ext/array/uniq_by.rb +0 -19
  159. data/lib/active_support/core_ext/hash/diff.rb +0 -14
  160. data/lib/active_support/core_ext/logger.rb +0 -67
  161. data/lib/active_support/core_ext/object/to_json.rb +0 -27
  162. data/lib/active_support/core_ext/proc.rb +0 -17
  163. data/lib/active_support/core_ext/string/encoding.rb +0 -8
  164. data/lib/active_support/file_watcher.rb +0 -36
  165. data/lib/active_support/json/variable.rb +0 -18
  166. data/lib/active_support/testing/pending.rb +0 -14
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2005-2013 David Heinemeier Hansson
1
+ Copyright (c) 2005-2014 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
data/README.rdoc CHANGED
@@ -14,7 +14,7 @@ The latest version of Active Support can be installed with RubyGems:
14
14
 
15
15
  Source code can be downloaded as part of the Rails project on GitHub:
16
16
 
17
- * https://github.com/rails/rails/tree/4-0-stable/activesupport
17
+ * https://github.com/rails/rails/tree/4-2-stable/activesupport
18
18
 
19
19
 
20
20
  == License
@@ -30,6 +30,11 @@ API documentation is at:
30
30
 
31
31
  * http://api.rubyonrails.org
32
32
 
33
- Bug reports and feature requests can be filed with the rest for the Ruby on Rails project here:
33
+ Bug reports can be filed for the Ruby on Rails project here:
34
34
 
35
35
  * https://github.com/rails/rails/issues
36
+
37
+ Feature requests should be discussed on the rails-core mailing list here:
38
+
39
+ * https://groups.google.com/forum/?fromgroups#!forum/rubyonrails-core
40
+
@@ -13,17 +13,17 @@ module ActiveSupport
13
13
  # can focus on the rest.
14
14
  #
15
15
  # bc = BacktraceCleaner.new
16
- # bc.add_filter { |line| line.gsub(Rails.root, '') }
17
- # bc.add_silencer { |line| line =~ /mongrel|rubygems/ }
18
- # bc.clean(exception.backtrace) # will strip the Rails.root prefix and skip any lines from mongrel or rubygems
16
+ # bc.add_filter { |line| line.gsub(Rails.root.to_s, '') } # strip the Rails.root prefix
17
+ # bc.add_silencer { |line| line =~ /mongrel|rubygems/ } # skip any lines from mongrel or rubygems
18
+ # bc.clean(exception.backtrace) # perform the cleanup
19
19
  #
20
20
  # To reconfigure an existing BacktraceCleaner (like the default one in Rails)
21
21
  # and show as much data as possible, you can always call
22
22
  # <tt>BacktraceCleaner#remove_silencers!</tt>, which will restore the
23
23
  # backtrace to a pristine state. If you need to reconfigure an existing
24
24
  # BacktraceCleaner so that it does not filter or modify the paths of any lines
25
- # of the backtrace, you can call BacktraceCleaner#remove_filters! These two
26
- # methods will give you a completely untouched backtrace.
25
+ # of the backtrace, you can call <tt>BacktraceCleaner#remove_filters!</tt>
26
+ # These two methods will give you a completely untouched backtrace.
27
27
  #
28
28
  # Inspired by the Quiet Backtrace gem by Thoughtbot.
29
29
  class BacktraceCleaner
@@ -65,14 +65,14 @@ module ActiveSupport
65
65
  @silencers << block
66
66
  end
67
67
 
68
- # Will remove all silencers, but leave in the filters. This is useful if
69
- # your context of debugging suddenly expands as you suspect a bug in one of
68
+ # Removes all silencers, but leaves in the filters. Useful if your
69
+ # context of debugging suddenly expands as you suspect a bug in one of
70
70
  # the libraries you use.
71
71
  def remove_silencers!
72
72
  @silencers = []
73
73
  end
74
74
 
75
- # Removes all filters, but leaves in silencers. Useful if you suddenly
75
+ # Removes all filters, but leaves in the silencers. Useful if you suddenly
76
76
  # need to see entire filepaths in the backtrace that you had already
77
77
  # filtered out.
78
78
  def remove_filters!
@@ -45,15 +45,5 @@ module ActiveSupport
45
45
  yield
46
46
  end
47
47
  end
48
-
49
- # Silence the logger during the execution of the block.
50
- def silence
51
- message = "ActiveSupport::Benchmarkable#silence is deprecated. It will be removed from Rails 4.1."
52
- ActiveSupport::Deprecation.warn message
53
- old_logger_level, logger.level = logger.level, ::Logger::ERROR if logger
54
- yield
55
- ensure
56
- logger.level = old_logger_level if logger
57
- end
58
48
  end
59
49
  end
@@ -14,6 +14,7 @@ module ActiveSupport
14
14
 
15
15
  DIR_FORMATTER = "%03X"
16
16
  FILENAME_MAX_SIZE = 228 # max filename size on file system is 255, minus room for timestamp and random characters appended by Tempfile (used by atomic write)
17
+ FILEPATH_MAX_SIZE = 900 # max is 1024, plus some room
17
18
  EXCLUDED_DIRS = ['.', '..'].freeze
18
19
 
19
20
  def initialize(cache_path, options = nil)
@@ -22,11 +23,15 @@ module ActiveSupport
22
23
  extend Strategy::LocalCache
23
24
  end
24
25
 
26
+ # Deletes all items from the cache. In this case it deletes all the entries in the specified
27
+ # file store directory except for .gitkeep. Be careful which directory is specified in your
28
+ # config file when using +FileStore+ because everything in that directory will be deleted.
25
29
  def clear(options = nil)
26
30
  root_dirs = Dir.entries(cache_path).reject {|f| (EXCLUDED_DIRS + [".gitkeep"]).include?(f)}
27
31
  FileUtils.rm_r(root_dirs.collect{|f| File.join(cache_path, f)})
28
32
  end
29
33
 
34
+ # Preemptively iterates through all stored keys and removes the ones which have expired.
30
35
  def cleanup(options = nil)
31
36
  options = merged_options(options)
32
37
  search_dir(cache_path) do |fname|
@@ -36,32 +41,16 @@ module ActiveSupport
36
41
  end
37
42
  end
38
43
 
44
+ # Increments an already existing integer value that is stored in the cache.
45
+ # If the key is not found nothing is done.
39
46
  def increment(name, amount = 1, options = nil)
40
- file_name = key_file_path(namespaced_key(name, options))
41
- lock_file(file_name) do
42
- options = merged_options(options)
43
- if num = read(name, options)
44
- num = num.to_i + amount
45
- write(name, num, options)
46
- num
47
- else
48
- nil
49
- end
50
- end
47
+ modify_value(name, amount, options)
51
48
  end
52
49
 
50
+ # Decrements an already existing integer value that is stored in the cache.
51
+ # If the key is not found nothing is done.
53
52
  def decrement(name, amount = 1, options = nil)
54
- file_name = key_file_path(namespaced_key(name, options))
55
- lock_file(file_name) do
56
- options = merged_options(options)
57
- if num = read(name, options)
58
- num = num.to_i - amount
59
- write(name, num, options)
60
- num
61
- else
62
- nil
63
- end
64
- end
53
+ modify_value(name, -amount, options)
65
54
  end
66
55
 
67
56
  def delete_matched(matcher, options = nil)
@@ -89,6 +78,7 @@ module ActiveSupport
89
78
 
90
79
  def write_entry(key, entry, options)
91
80
  file_name = key_file_path(key)
81
+ return false if options[:unless_exist] && File.exist?(file_name)
92
82
  ensure_cache_path(File.dirname(file_name))
93
83
  File.atomic_write(file_name, cache_path) {|f| Marshal.dump(entry, f)}
94
84
  true
@@ -128,6 +118,10 @@ module ActiveSupport
128
118
 
129
119
  # Translate a key into a file path.
130
120
  def key_file_path(key)
121
+ if key.size > FILEPATH_MAX_SIZE
122
+ key = Digest::MD5.hexdigest(key)
123
+ end
124
+
131
125
  fname = URI.encode_www_form_component(key)
132
126
  hash = Zlib.adler32(fname)
133
127
  hash, dir_1 = hash.divmod(0x1000)
@@ -175,6 +169,22 @@ module ActiveSupport
175
169
  end
176
170
  end
177
171
  end
172
+
173
+ # Modifies the amount of an already existing integer value that is stored in the cache.
174
+ # If the key is not found nothing is done.
175
+ def modify_value(name, amount, options)
176
+ file_name = key_file_path(namespaced_key(name, options))
177
+
178
+ lock_file(file_name) do
179
+ options = merged_options(options)
180
+
181
+ if num = read(name, options)
182
+ num = num.to_i + amount
183
+ write(name, num, options)
184
+ num
185
+ end
186
+ end
187
+ end
178
188
  end
179
189
  end
180
190
  end
@@ -41,17 +41,15 @@ module ActiveSupport
41
41
  #
42
42
  # If no addresses are specified, then MemCacheStore will connect to
43
43
  # localhost port 11211 (the default memcached port).
44
- #
45
- # Instead of addresses one can pass in a MemCache-like object. For example:
46
- #
47
- # require 'memcached' # gem install memcached; uses C bindings to libmemcached
48
- # ActiveSupport::Cache::MemCacheStore.new(Memcached::Rails.new("localhost:11211"))
49
44
  def initialize(*addresses)
50
45
  addresses = addresses.flatten
51
46
  options = addresses.extract_options!
52
47
  super(options)
53
48
 
54
- if addresses.first.respond_to?(:get)
49
+ unless [String, Dalli::Client, NilClass].include?(addresses.first.class)
50
+ raise ArgumentError, "First argument must be an empty array, an array of hosts or a Dalli::Client instance."
51
+ end
52
+ if addresses.first.is_a?(Dalli::Client)
55
53
  @data = addresses.first
56
54
  else
57
55
  mem_cache_options = options.dup
@@ -69,7 +67,7 @@ module ActiveSupport
69
67
  options = names.extract_options!
70
68
  options = merged_options(options)
71
69
  keys_to_names = Hash[names.map{|name| [escape_key(namespaced_key(name, options)), name]}]
72
- raw_values = @data.get_multi(keys_to_names.keys, :raw => true)
70
+ raw_values = @data.get_multi(keys_to_names.keys)
73
71
  values = {}
74
72
  raw_values.each do |key, value|
75
73
  entry = deserialize_entry(value)
@@ -36,6 +36,7 @@ module ActiveSupport
36
36
  end
37
37
  end
38
38
 
39
+ # Preemptively iterates through all stored keys and removes the ones which have expired.
39
40
  def cleanup(options = nil)
40
41
  options = merged_options(options)
41
42
  instrument(:cleanup, :size => @data.size) do
@@ -1,5 +1,6 @@
1
1
  require 'active_support/core_ext/object/duplicable'
2
2
  require 'active_support/core_ext/string/inflections'
3
+ require 'active_support/per_thread_registry'
3
4
 
4
5
  module ActiveSupport
5
6
  module Cache
@@ -8,6 +9,8 @@ module ActiveSupport
8
9
  # duration of a block. Repeated calls to the cache for the same key will hit the
9
10
  # in-memory cache for faster access.
10
11
  module LocalCache
12
+ autoload :Middleware, 'active_support/cache/strategy/local_cache_middleware'
13
+
11
14
  # Class for storing and registering the local caches.
12
15
  class LocalCacheRegistry # :nodoc:
13
16
  extend ActiveSupport::PerThreadRegistry
@@ -23,6 +26,9 @@ module ActiveSupport
23
26
  def set_cache_for(local_cache_key, value)
24
27
  @registry[local_cache_key] = value
25
28
  end
29
+
30
+ def self.set_cache_for(l, v); instance.set_cache_for l, v; end
31
+ def self.cache_for(l); instance.cache_for l; end
26
32
  end
27
33
 
28
34
  # Simple memory backed cache. This cache is not thread safe and is intended only
@@ -60,32 +66,6 @@ module ActiveSupport
60
66
  def with_local_cache
61
67
  use_temporary_local_cache(LocalStore.new) { yield }
62
68
  end
63
-
64
- #--
65
- # This class wraps up local storage for middlewares. Only the middleware method should
66
- # construct them.
67
- class Middleware # :nodoc:
68
- attr_reader :name, :local_cache_key
69
-
70
- def initialize(name, local_cache_key)
71
- @name = name
72
- @local_cache_key = local_cache_key
73
- @app = nil
74
- end
75
-
76
- def new(app)
77
- @app = app
78
- self
79
- end
80
-
81
- def call(env)
82
- LocalCacheRegistry.set_cache_for(local_cache_key, LocalStore.new)
83
- @app.call(env)
84
- ensure
85
- LocalCacheRegistry.set_cache_for(local_cache_key, nil)
86
- end
87
- end
88
-
89
69
  # Middleware class can be inserted as a Rack handler to be local cache for the
90
70
  # duration of request.
91
71
  def middleware
@@ -106,13 +86,13 @@ module ActiveSupport
106
86
 
107
87
  def increment(name, amount = 1, options = nil) # :nodoc:
108
88
  value = bypass_local_cache{super}
109
- increment_or_decrement(value, name, amount, options)
89
+ set_cache_value(value, name, amount, options)
110
90
  value
111
91
  end
112
92
 
113
93
  def decrement(name, amount = 1, options = nil) # :nodoc:
114
94
  value = bypass_local_cache{super}
115
- increment_or_decrement(value, name, amount, options)
95
+ set_cache_value(value, name, amount, options)
116
96
  value
117
97
  end
118
98
 
@@ -140,8 +120,7 @@ module ActiveSupport
140
120
  super
141
121
  end
142
122
 
143
- private
144
- def increment_or_decrement(value, name, amount, options)
123
+ def set_cache_value(value, name, amount, options)
145
124
  if local_cache
146
125
  local_cache.mute do
147
126
  if value
@@ -153,6 +132,8 @@ module ActiveSupport
153
132
  end
154
133
  end
155
134
 
135
+ private
136
+
156
137
  def local_cache_key
157
138
  @local_cache_key ||= "#{self.class.name.underscore}_local_cache_#{object_id}".gsub(/[\/-]/, '_').to_sym
158
139
  end
@@ -0,0 +1,44 @@
1
+ require 'rack/body_proxy'
2
+ require 'rack/utils'
3
+
4
+ module ActiveSupport
5
+ module Cache
6
+ module Strategy
7
+ module LocalCache
8
+
9
+ #--
10
+ # This class wraps up local storage for middlewares. Only the middleware method should
11
+ # construct them.
12
+ class Middleware # :nodoc:
13
+ attr_reader :name, :local_cache_key
14
+
15
+ def initialize(name, local_cache_key)
16
+ @name = name
17
+ @local_cache_key = local_cache_key
18
+ @app = nil
19
+ end
20
+
21
+ def new(app)
22
+ @app = app
23
+ self
24
+ end
25
+
26
+ def call(env)
27
+ LocalCacheRegistry.set_cache_for(local_cache_key, LocalStore.new)
28
+ response = @app.call(env)
29
+ response[2] = ::Rack::BodyProxy.new(response[2]) do
30
+ LocalCacheRegistry.set_cache_for(local_cache_key, nil)
31
+ end
32
+ response
33
+ rescue Rack::Utils::InvalidParameterError
34
+ LocalCacheRegistry.set_cache_for(local_cache_key, nil)
35
+ [400, {}, []]
36
+ rescue Exception
37
+ LocalCacheRegistry.set_cache_for(local_cache_key, nil)
38
+ raise
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -3,19 +3,20 @@ require 'zlib'
3
3
  require 'active_support/core_ext/array/extract_options'
4
4
  require 'active_support/core_ext/array/wrap'
5
5
  require 'active_support/core_ext/benchmark'
6
- require 'active_support/core_ext/class/attribute_accessors'
6
+ require 'active_support/core_ext/module/attribute_accessors'
7
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
12
 
12
13
  module ActiveSupport
13
14
  # See ActiveSupport::Cache::Store for documentation.
14
15
  module Cache
15
- autoload :FileStore, 'active_support/cache/file_store'
16
- autoload :MemoryStore, 'active_support/cache/memory_store'
16
+ autoload :FileStore, 'active_support/cache/file_store'
17
+ autoload :MemoryStore, 'active_support/cache/memory_store'
17
18
  autoload :MemCacheStore, 'active_support/cache/mem_cache_store'
18
- autoload :NullStore, 'active_support/cache/null_store'
19
+ autoload :NullStore, 'active_support/cache/null_store'
19
20
 
20
21
  # These options mean something to all cache implementations. Individual cache
21
22
  # implementations may support additional options.
@@ -26,7 +27,7 @@ module ActiveSupport
26
27
  end
27
28
 
28
29
  class << self
29
- # Creates a new CacheStore object according to the given options.
30
+ # Creates a new Store object according to the given options.
30
31
  #
31
32
  # If no arguments are passed to this method, then a new
32
33
  # ActiveSupport::Cache::MemoryStore object will be returned.
@@ -88,25 +89,24 @@ module ActiveSupport
88
89
  end
89
90
 
90
91
  private
92
+ def retrieve_cache_key(key)
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
98
+ end.to_s
99
+ end
91
100
 
92
- def retrieve_cache_key(key)
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
98
- end.to_s
99
- end
100
-
101
- # Obtains the specified cache store class, given the name of the +store+.
102
- # Raises an error when the store class cannot be found.
103
- def retrieve_store_class(store)
104
- require "active_support/cache/#{store}"
105
- rescue LoadError => e
106
- raise "Could not find cache store adapter for #{store} (#{e})"
107
- else
108
- ActiveSupport::Cache.const_get(store.to_s.camelize)
109
- end
101
+ # Obtains the specified cache store class, given the name of the +store+.
102
+ # Raises an error when the store class cannot be found.
103
+ def retrieve_store_class(store)
104
+ require "active_support/cache/#{store}"
105
+ rescue LoadError => e
106
+ raise "Could not find cache store adapter for #{store} (#{e})"
107
+ else
108
+ ActiveSupport::Cache.const_get(store.to_s.camelize)
109
+ end
110
110
  end
111
111
 
112
112
  # An abstract cache store class. There are multiple cache store
@@ -153,7 +153,6 @@ module ActiveSupport
153
153
  # or +write+. To specify the threshold at which to compress values, set the
154
154
  # <tt>:compress_threshold</tt> option. The default threshold is 16K.
155
155
  class Store
156
-
157
156
  cattr_accessor :logger, :instance_writer => true
158
157
 
159
158
  attr_reader :silence, :options
@@ -180,14 +179,16 @@ module ActiveSupport
180
179
  @silence = previous_silence
181
180
  end
182
181
 
183
- # Set to +true+ if cache stores should be instrumented.
184
- # Default is +false+.
182
+ # :deprecated:
185
183
  def self.instrument=(boolean)
186
- Thread.current[:instrument_cache_store] = 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
187
186
  end
188
187
 
188
+ # :deprecated:
189
189
  def self.instrument
190
- Thread.current[:instrument_cache_store] || false
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
191
192
  end
192
193
 
193
194
  # Fetches data from the cache, using the given key. If there is data in
@@ -228,7 +229,7 @@ module ActiveSupport
228
229
  #
229
230
  # Setting <tt>:race_condition_ttl</tt> is very useful in situations where
230
231
  # a cache entry is used very frequently and is under heavy load. If a
231
- # cache expires and due to heavy load seven different processes will try
232
+ # cache expires and due to heavy load several different processes will try
232
233
  # to read data natively and then they all will try to write to cache. To
233
234
  # avoid that case the first process to find an expired cache entry will
234
235
  # bump the cache expiration time by the value set in <tt>:race_condition_ttl</tt>.
@@ -236,7 +237,7 @@ module ActiveSupport
236
237
  # seconds. Because of extended life of the previous cache, other processes
237
238
  # will continue to use slightly stale data for a just a bit longer. In the
238
239
  # meantime that first process will go ahead and will write into cache the
239
- # new value. After that all the processes will start getting new value.
240
+ # new value. After that all the processes will start getting the new value.
240
241
  # The key is to keep <tt>:race_condition_ttl</tt> small.
241
242
  #
242
243
  # If the process regenerating the entry errors out, the entry will be
@@ -352,11 +353,39 @@ module ActiveSupport
352
353
  results
353
354
  end
354
355
 
356
+ # Fetches data from the cache, using the given keys. If there is data in
357
+ # the cache with the given keys, then that data is returned. Otherwise,
358
+ # the supplied block is called for each key for which there was no data,
359
+ # and the result will be written to the cache and returned.
360
+ #
361
+ # Options are passed to the underlying cache implementation.
362
+ #
363
+ # Returns a hash with the data for each of the names. For example:
364
+ #
365
+ # cache.write("bim", "bam")
366
+ # cache.fetch_multi("bim", "boom") { |key| key * 2 }
367
+ # # => { "bam" => "bam", "boom" => "boomboom" }
368
+ #
369
+ def fetch_multi(*names)
370
+ options = names.extract_options!
371
+ options = merged_options(options)
372
+ results = read_multi(*names, options)
373
+
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
379
+ end
380
+ end
381
+ end
382
+
355
383
  # Writes the value to the cache, with the key.
356
384
  #
357
385
  # Options are passed to the underlying cache implementation.
358
386
  def write(name, value, options = nil)
359
387
  options = merged_options(options)
388
+
360
389
  instrument(:write, name, options) do
361
390
  entry = Entry.new(value, options)
362
391
  write_entry(namespaced_key(name, options), entry, options)
@@ -368,19 +397,21 @@ module ActiveSupport
368
397
  # Options are passed to the underlying cache implementation.
369
398
  def delete(name, options = nil)
370
399
  options = merged_options(options)
400
+
371
401
  instrument(:delete, name) do
372
402
  delete_entry(namespaced_key(name, options), options)
373
403
  end
374
404
  end
375
405
 
376
- # Return +true+ if the cache contains an entry for the given key.
406
+ # Returns +true+ if the cache contains an entry for the given key.
377
407
  #
378
408
  # Options are passed to the underlying cache implementation.
379
409
  def exist?(name, options = nil)
380
410
  options = merged_options(options)
411
+
381
412
  instrument(:exist?, name) do
382
413
  entry = read_entry(namespaced_key(name, options), options)
383
- entry && !entry.expired?
414
+ (entry && !entry.expired?) || false
384
415
  end
385
416
  end
386
417
 
@@ -423,7 +454,7 @@ module ActiveSupport
423
454
  # Clear the entire cache. Be careful with this method since it could
424
455
  # affect other processes if shared cache is being used.
425
456
  #
426
- # Options are passed to the underlying cache implementation.
457
+ # The options hash is passed to the underlying cache implementation.
427
458
  #
428
459
  # All implementations may not support this method.
429
460
  def clear(options = nil)
@@ -511,13 +542,9 @@ module ActiveSupport
511
542
  def instrument(operation, key, options = nil)
512
543
  log(operation, key, options)
513
544
 
514
- if self.class.instrument
515
- payload = { :key => key }
516
- payload.merge!(options) if options.is_a?(Hash)
517
- ActiveSupport::Notifications.instrument("cache_#{operation}.active_support", payload){ yield(payload) }
518
- else
519
- yield(nil)
520
- end
545
+ payload = { :key => key }
546
+ payload.merge!(options) if options.is_a?(Hash)
547
+ ActiveSupport::Notifications.instrument("cache_#{operation}.active_support", payload){ yield(payload) }
521
548
  end
522
549
 
523
550
  def log(operation, key, options = nil)
@@ -535,7 +562,7 @@ module ActiveSupport
535
562
  def handle_expired_entry(entry, key, options)
536
563
  if entry && entry.expired?
537
564
  race_ttl = options[:race_condition_ttl].to_i
538
- if race_ttl && (Time.now.to_f - entry.expires_at <= race_ttl)
565
+ if (race_ttl > 0) && (Time.now.to_f - entry.expires_at <= race_ttl)
539
566
  # When an entry has :race_condition_ttl defined, put the stale entry back into the cache
540
567
  # for a brief period while the entry is begin recalculated.
541
568
  entry.expires_at = Time.now + race_ttl
@@ -557,6 +584,7 @@ module ActiveSupport
557
584
  result = instrument(:generate, name, options) do |payload|
558
585
  yield(name)
559
586
  end
587
+
560
588
  write(name, result, options)
561
589
  result
562
590
  end
@@ -580,6 +608,7 @@ module ActiveSupport
580
608
  else
581
609
  @value = value
582
610
  end
611
+
583
612
  @created_at = Time.now.to_f
584
613
  @expires_in = options[:expires_in]
585
614
  @expires_in = @expires_in.to_f if @expires_in
@@ -630,6 +659,7 @@ module ActiveSupport
630
659
  # serialize entries to protect against accidental cache modifications.
631
660
  def dup_value!
632
661
  convert_version_4beta1_entry! if defined?(@v)
662
+
633
663
  if @value && !compressed? && !(@value.is_a?(Numeric) || @value == true || @value == false)
634
664
  if @value.is_a?(String)
635
665
  @value = @value.dup
@@ -644,8 +674,10 @@ module ActiveSupport
644
674
  if value && options[:compress]
645
675
  compress_threshold = options[:compress_threshold] || DEFAULT_COMPRESS_LIMIT
646
676
  serialized_value_size = (value.is_a?(String) ? value : Marshal.dump(value)).bytesize
677
+
647
678
  return true if serialized_value_size >= compress_threshold
648
679
  end
680
+
649
681
  false
650
682
  end
651
683
 
@@ -668,10 +700,12 @@ module ActiveSupport
668
700
  @value = @v
669
701
  remove_instance_variable(:@v)
670
702
  end
703
+
671
704
  if defined?(@c)
672
705
  @compressed = @c
673
706
  remove_instance_variable(:@c)
674
707
  end
708
+
675
709
  if defined?(@x) && @x
676
710
  @created_at ||= Time.now.to_f
677
711
  @expires_in = @x - @created_at