activesupport 3.1.12 → 3.2.0.rc1

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 (78) hide show
  1. data/CHANGELOG.md +1539 -30
  2. data/README.rdoc +2 -2
  3. data/lib/active_support.rb +1 -1
  4. data/lib/active_support/benchmarkable.rb +13 -18
  5. data/lib/active_support/buffered_logger.rb +43 -55
  6. data/lib/active_support/cache.rb +109 -115
  7. data/lib/active_support/cache/file_store.rb +6 -17
  8. data/lib/active_support/cache/mem_cache_store.rb +10 -2
  9. data/lib/active_support/cache/null_store.rb +44 -0
  10. data/lib/active_support/cache/strategy/local_cache.rb +2 -2
  11. data/lib/active_support/callbacks.rb +38 -35
  12. data/lib/active_support/concern.rb +5 -10
  13. data/lib/active_support/core_ext/array.rb +1 -0
  14. data/lib/active_support/core_ext/array/access.rb +1 -1
  15. data/lib/active_support/core_ext/array/prepend_and_append.rb +7 -0
  16. data/lib/active_support/core_ext/array/wrap.rb +1 -1
  17. data/lib/active_support/core_ext/class.rb +0 -1
  18. data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -2
  19. data/lib/active_support/core_ext/date/calculations.rb +37 -14
  20. data/lib/active_support/core_ext/date/freeze.rb +6 -4
  21. data/lib/active_support/core_ext/date_time/calculations.rb +1 -1
  22. data/lib/active_support/core_ext/enumerable.rb +25 -8
  23. data/lib/active_support/core_ext/file/atomic.rb +1 -2
  24. data/lib/active_support/core_ext/hash/conversions.rb +7 -25
  25. data/lib/active_support/core_ext/hash/indifferent_access.rb +1 -1
  26. data/lib/active_support/core_ext/io.rb +15 -0
  27. data/lib/active_support/core_ext/kernel.rb +0 -1
  28. data/lib/active_support/core_ext/kernel/agnostics.rb +2 -2
  29. data/lib/active_support/core_ext/kernel/debugger.rb +1 -7
  30. data/lib/active_support/core_ext/module.rb +2 -2
  31. data/lib/active_support/core_ext/module/attribute_accessors.rb +6 -2
  32. data/lib/active_support/core_ext/module/delegation.rb +32 -21
  33. data/lib/active_support/core_ext/module/qualified_const.rb +64 -0
  34. data/lib/active_support/core_ext/module/reachable.rb +1 -3
  35. data/lib/active_support/core_ext/module/synchronization.rb +2 -0
  36. data/lib/active_support/core_ext/object/blank.rb +14 -2
  37. data/lib/active_support/core_ext/object/inclusion.rb +17 -7
  38. data/lib/active_support/core_ext/object/to_json.rb +2 -2
  39. data/lib/active_support/core_ext/range/conversions.rb +1 -1
  40. data/lib/active_support/core_ext/string/conversions.rb +2 -2
  41. data/lib/active_support/core_ext/string/inflections.rb +44 -6
  42. data/lib/active_support/core_ext/string/multibyte.rb +1 -1
  43. data/lib/active_support/core_ext/string/output_safety.rb +22 -25
  44. data/lib/active_support/core_ext/time/calculations.rb +66 -12
  45. data/lib/active_support/dependencies.rb +51 -52
  46. data/lib/active_support/file_update_checker.rb +100 -15
  47. data/lib/active_support/hash_with_indifferent_access.rb +5 -1
  48. data/lib/active_support/i18n.rb +1 -1
  49. data/lib/active_support/i18n_railtie.rb +9 -4
  50. data/lib/active_support/inflections.rb +3 -3
  51. data/lib/active_support/inflector/inflections.rb +53 -92
  52. data/lib/active_support/inflector/methods.rb +173 -9
  53. data/lib/active_support/json/decoding.rb +3 -17
  54. data/lib/active_support/json/encoding.rb +11 -14
  55. data/lib/active_support/memoizable.rb +12 -1
  56. data/lib/active_support/message_encryptor.rb +52 -20
  57. data/lib/active_support/message_verifier.rb +15 -4
  58. data/lib/active_support/notifications.rb +87 -14
  59. data/lib/active_support/notifications/instrumenter.rb +1 -2
  60. data/lib/active_support/ordered_hash.rb +7 -3
  61. data/lib/active_support/tagged_logging.rb +63 -0
  62. data/lib/active_support/testing/assertions.rb +1 -1
  63. data/lib/active_support/testing/mochaing.rb +2 -2
  64. data/lib/active_support/testing/performance/ruby.rb +1 -1
  65. data/lib/active_support/testing/setup_and_teardown.rb +4 -12
  66. data/lib/active_support/time_with_zone.rb +6 -3
  67. data/lib/active_support/values/time_zone.rb +3 -7
  68. data/lib/active_support/version.rb +3 -3
  69. data/lib/active_support/xml_mini.rb +3 -3
  70. data/lib/active_support/xml_mini/jdom.rb +4 -10
  71. metadata +28 -21
  72. checksums.yaml +0 -7
  73. data/lib/active_support/cache/compressed_mem_cache_store.rb +0 -13
  74. data/lib/active_support/cache/synchronized_memory_store.rb +0 -11
  75. data/lib/active_support/core_ext/class/inheritable_attributes.rb +0 -178
  76. data/lib/active_support/core_ext/kernel/requires.rb +0 -28
  77. data/lib/active_support/core_ext/module/attr_accessor_with_default.rb +0 -31
  78. data/lib/active_support/secure_random.rb +0 -6
@@ -8,7 +8,7 @@ outside of Rails.
8
8
 
9
9
  == Download and installation
10
10
 
11
- The latest version of Active Support can be installed with Rubygems:
11
+ The latest version of Active Support can be installed with RubyGems:
12
12
 
13
13
  % [sudo] gem install activesupport
14
14
 
@@ -26,7 +26,7 @@ Active Support is released under the MIT license.
26
26
 
27
27
  API documentation is at
28
28
 
29
- * http://api.rubyonrails.com
29
+ * http://api.rubyonrails.org
30
30
 
31
31
  Bug reports and feature requests can be filed with the rest for the Ruby on Rails project here:
32
32
 
@@ -70,8 +70,8 @@ module ActiveSupport
70
70
  autoload :OrderedHash
71
71
  autoload :OrderedOptions
72
72
  autoload :Rescuable
73
- autoload :SecureRandom
74
73
  autoload :StringInquirer
74
+ autoload :TaggedLogging
75
75
  autoload :XmlMini
76
76
  end
77
77
 
@@ -3,41 +3,36 @@ require 'active_support/core_ext/hash/keys'
3
3
 
4
4
  module ActiveSupport
5
5
  module Benchmarkable
6
- # Allows you to measure the execution time of a block
7
- # in a template and records the result to the log. Wrap this block around
8
- # expensive operations or possible bottlenecks to get a time reading
9
- # for the operation. For example, let's say you thought your file
10
- # processing method was taking too long; you could wrap it in a benchmark block.
6
+ # Allows you to measure the execution time of a block in a template and records the result to
7
+ # the log. Wrap this block around expensive operations or possible bottlenecks to get a time
8
+ # reading for the operation. For example, let's say you thought your file processing method
9
+ # was taking too long; you could wrap it in a benchmark block.
11
10
  #
12
11
  # <% benchmark "Process data files" do %>
13
12
  # <%= expensive_files_operation %>
14
13
  # <% end %>
15
14
  #
16
- # That would add something like "Process data files (345.2ms)" to the log,
17
- # which you can then use to compare timings when optimizing your code.
15
+ # That would add something like "Process data files (345.2ms)" to the log, which you can then
16
+ # use to compare timings when optimizing your code.
18
17
  #
19
- # You may give an optional logger level as the :level option.
20
- # (:debug, :info, :warn, :error); the default value is :info.
18
+ # You may give an optional logger level (:debug, :info, :warn, :error) as the :level option.
19
+ # The default logger level value is :info.
21
20
  #
22
21
  # <% benchmark "Low-level files", :level => :debug do %>
23
22
  # <%= lowlevel_files_operation %>
24
23
  # <% end %>
25
24
  #
26
- # Finally, you can pass true as the third argument to silence all log activity
27
- # inside the block. This is great for boiling down a noisy block to just a single statement:
25
+ # Finally, you can pass true as the third argument to silence all log activity (other than the
26
+ # timing information) from inside the block. This is great for boiling down a noisy block to
27
+ # just a single statement that produces one log line:
28
28
  #
29
29
  # <% benchmark "Process data files", :level => :info, :silence => true do %>
30
30
  # <%= expensive_and_chatty_files_operation %>
31
31
  # <% end %>
32
32
  def benchmark(message = "Benchmarking", options = {})
33
33
  if logger
34
- if options.is_a?(Symbol)
35
- ActiveSupport::Deprecation.warn("use benchmark('#{message}', :level => :#{options}) instead", caller)
36
- options = { :level => options, :silence => false }
37
- else
38
- options.assert_valid_keys(:level, :silence)
39
- options[:level] ||= :info
40
- end
34
+ options.assert_valid_keys(:level, :silence)
35
+ options[:level] ||= :info
41
36
 
42
37
  result = nil
43
38
  ms = Benchmark.ms { result = options[:silence] ? logger.silence { yield } : yield }
@@ -1,5 +1,9 @@
1
1
  require 'thread'
2
+ require 'logger'
3
+ require 'active_support/core_ext/logger'
2
4
  require 'active_support/core_ext/class/attribute_accessors'
5
+ require 'active_support/deprecation'
6
+ require 'fileutils'
3
7
 
4
8
  module ActiveSupport
5
9
  # Inspired by the buffered logger idea by Ezra
@@ -26,33 +30,34 @@ module ActiveSupport
26
30
  def silence(temporary_level = ERROR)
27
31
  if silencer
28
32
  begin
29
- old_logger_level, self.level = level, temporary_level
30
- yield self
33
+ logger = self.class.new @log_dest, temporary_level
34
+ yield logger
31
35
  ensure
32
- self.level = old_logger_level
36
+ logger.close
33
37
  end
34
38
  else
35
39
  yield self
36
40
  end
37
41
  end
42
+ deprecate :silence
38
43
 
39
- attr_accessor :level
40
44
  attr_reader :auto_flushing
45
+ deprecate :auto_flushing
41
46
 
42
47
  def initialize(log, level = DEBUG)
43
48
  @level = level
44
- @buffer = Hash.new { |h,k| h[k] = [] }
45
- @auto_flushing = 1
46
- @guard = Mutex.new
47
-
48
- if log.respond_to?(:write)
49
- @log = log
50
- elsif File.exist?(log)
51
- @log = open_log(log, (File::WRONLY | File::APPEND))
52
- else
53
- FileUtils.mkdir_p(File.dirname(log))
54
- @log = open_log(log, (File::WRONLY | File::APPEND | File::CREAT))
49
+ @log_dest = log
50
+
51
+ unless log.respond_to?(:write)
52
+ unless File.exist?(File.dirname(log))
53
+ ActiveSupport::Deprecation.warn(<<-eowarn)
54
+ Automatic directory creation for '#{log}' is deprecated. Please make sure the directory for your log file exists before creating the logger.
55
+ eowarn
56
+ FileUtils.mkdir_p(File.dirname(log))
57
+ end
55
58
  end
59
+
60
+ @log = open_logfile log
56
61
  end
57
62
 
58
63
  def open_log(log, mode)
@@ -61,30 +66,32 @@ module ActiveSupport
61
66
  open_log.sync = true
62
67
  end
63
68
  end
69
+ deprecate :open_log
70
+
71
+ def level
72
+ @log.level
73
+ end
74
+
75
+ def level=(l)
76
+ @log.level = l
77
+ end
64
78
 
65
79
  def add(severity, message = nil, progname = nil, &block)
66
- return if @level > severity
67
- message = (message || (block && block.call) || progname).to_s
68
- # If a newline is necessary then create a new message ending with a newline.
69
- # Ensures that the original message is not mutated.
70
- message = "#{message}\n" unless message[-1] == ?\n
71
- buffer << message
72
- auto_flush
73
- message
80
+ @log.add(severity, message, progname, &block)
74
81
  end
75
82
 
76
83
  # Dynamically add methods such as:
77
84
  # def info
78
85
  # def warn
79
86
  # def debug
80
- for severity in Severity.constants
87
+ Severity.constants.each do |severity|
81
88
  class_eval <<-EOT, __FILE__, __LINE__ + 1
82
89
  def #{severity.downcase}(message = nil, progname = nil, &block) # def debug(message = nil, progname = nil, &block)
83
90
  add(#{severity}, message, progname, &block) # add(DEBUG, message, progname, &block)
84
91
  end # end
85
92
 
86
93
  def #{severity.downcase}? # def debug?
87
- #{severity} >= @level # DEBUG >= @level
94
+ #{severity} >= level # DEBUG >= @level
88
95
  end # end
89
96
  EOT
90
97
  end
@@ -94,44 +101,25 @@ module ActiveSupport
94
101
  # never auto-flush. If you turn auto-flushing off, be sure to regularly
95
102
  # flush the log yourself -- it will eat up memory until you do.
96
103
  def auto_flushing=(period)
97
- @auto_flushing =
98
- case period
99
- when true; 1
100
- when false, nil, 0; MAX_BUFFER_SIZE
101
- when Integer; period
102
- else raise ArgumentError, "Unrecognized auto_flushing period: #{period.inspect}"
103
- end
104
104
  end
105
+ deprecate :auto_flushing=
105
106
 
106
107
  def flush
107
- @guard.synchronize do
108
- buffer.each do |content|
109
- @log.write(content)
110
- end
108
+ end
109
+ deprecate :flush
111
110
 
112
- # Important to do this even if buffer was empty or else @buffer will
113
- # accumulate empty arrays for each request where nothing was logged.
114
- clear_buffer
115
- end
111
+ def respond_to?(method, include_private = false)
112
+ return false if method.to_s == "flush"
113
+ super
116
114
  end
117
115
 
118
116
  def close
119
- flush
120
- @log.close if @log.respond_to?(:close)
121
- @log = nil
117
+ @log.close
122
118
  end
123
119
 
124
- protected
125
- def auto_flush
126
- flush if buffer.size >= @auto_flushing
127
- end
128
-
129
- def buffer
130
- @buffer[Thread.current]
131
- end
132
-
133
- def clear_buffer
134
- @buffer.delete(Thread.current)
135
- end
120
+ private
121
+ def open_logfile(log)
122
+ Logger.new log
123
+ end
136
124
  end
137
125
  end
@@ -16,8 +16,7 @@ module ActiveSupport
16
16
  autoload :FileStore, 'active_support/cache/file_store'
17
17
  autoload :MemoryStore, 'active_support/cache/memory_store'
18
18
  autoload :MemCacheStore, 'active_support/cache/mem_cache_store'
19
- autoload :SynchronizedMemoryStore, 'active_support/cache/synchronized_memory_store'
20
- autoload :CompressedMemCacheStore, 'active_support/cache/compressed_mem_cache_store'
19
+ autoload :NullStore, 'active_support/cache/null_store'
21
20
 
22
21
  # These options mean something to all cache implementations. Individual cache
23
22
  # implementations may support additional options.
@@ -27,75 +26,75 @@ module ActiveSupport
27
26
  autoload :LocalCache, 'active_support/cache/strategy/local_cache'
28
27
  end
29
28
 
30
- # Creates a new CacheStore object according to the given options.
31
- #
32
- # If no arguments are passed to this method, then a new
33
- # ActiveSupport::Cache::MemoryStore object will be returned.
34
- #
35
- # If you pass a Symbol as the first argument, then a corresponding cache
36
- # store class under the ActiveSupport::Cache namespace will be created.
37
- # For example:
38
- #
39
- # ActiveSupport::Cache.lookup_store(:memory_store)
40
- # # => returns a new ActiveSupport::Cache::MemoryStore object
41
- #
42
- # ActiveSupport::Cache.lookup_store(:mem_cache_store)
43
- # # => returns a new ActiveSupport::Cache::MemCacheStore object
44
- #
45
- # Any additional arguments will be passed to the corresponding cache store
46
- # class's constructor:
47
- #
48
- # ActiveSupport::Cache.lookup_store(:file_store, "/tmp/cache")
49
- # # => same as: ActiveSupport::Cache::FileStore.new("/tmp/cache")
50
- #
51
- # If the first argument is not a Symbol, then it will simply be returned:
52
- #
53
- # ActiveSupport::Cache.lookup_store(MyOwnCacheStore.new)
54
- # # => returns MyOwnCacheStore.new
55
- def self.lookup_store(*store_option)
56
- store, *parameters = *Array.wrap(store_option).flatten
57
-
58
- case store
59
- when Symbol
60
- store_class_name = store.to_s.camelize
61
- store_class =
62
- begin
63
- require "active_support/cache/#{store}"
64
- rescue LoadError => e
65
- raise "Could not find cache store adapter for #{store} (#{e})"
66
- else
67
- ActiveSupport::Cache.const_get(store_class_name)
68
- end
69
- store_class.new(*parameters)
70
- when nil
71
- ActiveSupport::Cache::MemoryStore.new
72
- else
73
- store
29
+ class << self
30
+ # Creates a new CacheStore object according to the given options.
31
+ #
32
+ # If no arguments are passed to this method, then a new
33
+ # ActiveSupport::Cache::MemoryStore object will be returned.
34
+ #
35
+ # If you pass a Symbol as the first argument, then a corresponding cache
36
+ # store class under the ActiveSupport::Cache namespace will be created.
37
+ # For example:
38
+ #
39
+ # ActiveSupport::Cache.lookup_store(:memory_store)
40
+ # # => returns a new ActiveSupport::Cache::MemoryStore object
41
+ #
42
+ # ActiveSupport::Cache.lookup_store(:mem_cache_store)
43
+ # # => returns a new ActiveSupport::Cache::MemCacheStore object
44
+ #
45
+ # Any additional arguments will be passed to the corresponding cache store
46
+ # class's constructor:
47
+ #
48
+ # ActiveSupport::Cache.lookup_store(:file_store, "/tmp/cache")
49
+ # # => same as: ActiveSupport::Cache::FileStore.new("/tmp/cache")
50
+ #
51
+ # If the first argument is not a Symbol, then it will simply be returned:
52
+ #
53
+ # ActiveSupport::Cache.lookup_store(MyOwnCacheStore.new)
54
+ # # => returns MyOwnCacheStore.new
55
+ def lookup_store(*store_option)
56
+ store, *parameters = *Array.wrap(store_option).flatten
57
+
58
+ case store
59
+ when Symbol
60
+ store_class_name = store.to_s.camelize
61
+ store_class =
62
+ begin
63
+ require "active_support/cache/#{store}"
64
+ rescue LoadError => e
65
+ raise "Could not find cache store adapter for #{store} (#{e})"
66
+ else
67
+ ActiveSupport::Cache.const_get(store_class_name)
68
+ end
69
+ store_class.new(*parameters)
70
+ when nil
71
+ ActiveSupport::Cache::MemoryStore.new
72
+ else
73
+ store
74
+ end
74
75
  end
75
- end
76
76
 
77
- def self.expand_cache_key(key, namespace = nil)
78
- expanded_cache_key = namespace ? "#{namespace}/" : ""
77
+ def expand_cache_key(key, namespace = nil)
78
+ expanded_cache_key = namespace ? "#{namespace}/" : ""
79
79
 
80
- prefix = ENV["RAILS_CACHE_ID"] || ENV["RAILS_APP_VERSION"]
81
- if prefix
82
- expanded_cache_key << "#{prefix}/"
80
+ prefix = ENV["RAILS_CACHE_ID"] || ENV["RAILS_APP_VERSION"]
81
+ if prefix
82
+ expanded_cache_key << "#{prefix}/"
83
+ end
84
+
85
+ expanded_cache_key << retrieve_cache_key(key)
86
+ expanded_cache_key
83
87
  end
84
88
 
85
- expanded_cache_key <<
86
- if key.respond_to?(:cache_key)
87
- key.cache_key
88
- elsif key.is_a?(Array)
89
- if key.size > 1
90
- key.collect { |element| expand_cache_key(element) }.to_param
91
- else
92
- key.first.to_param
93
- end
94
- elsif key
95
- key.to_param
96
- end.to_s
89
+ private
97
90
 
98
- expanded_cache_key
91
+ def retrieve_cache_key(key)
92
+ case
93
+ when key.respond_to?(:cache_key) then key.cache_key
94
+ when key.is_a?(Array) then ['Array', *key.map { |element| retrieve_cache_key(element) }].to_param
95
+ else key.to_param
96
+ end.to_s
97
+ end
99
98
  end
100
99
 
101
100
  # An abstract cache store class. There are multiple cache store
@@ -116,31 +115,32 @@ module ActiveSupport
116
115
  # cache.read("city") # => "Duckburgh"
117
116
  #
118
117
  # Keys are always translated into Strings and are case sensitive. When an
119
- # object is specified as a key, its +cache_key+ method will be called if it
120
- # is defined. Otherwise, the +to_param+ method will be called. Hashes and
121
- # Arrays can be used as keys. The elements will be delimited by slashes
122
- # and Hashes elements will be sorted by key so they are consistent.
118
+ # object is specified as a key and has a +cache_key+ method defined, this
119
+ # method will be called to define the key. Otherwise, the +to_param+
120
+ # method will be called. Hashes and Arrays can also be used as keys. The
121
+ # elements will be delimited by slashes, and the elements within a Hash
122
+ # will be sorted by key so they are consistent.
123
123
  #
124
124
  # cache.read("city") == cache.read(:city) # => true
125
125
  #
126
126
  # Nil values can be cached.
127
127
  #
128
- # If your cache is on a shared infrastructure, you can define a namespace for
129
- # your cache entries. If a namespace is defined, it will be prefixed on to every
130
- # key. The namespace can be either a static value or a Proc. If it is a Proc, it
131
- # will be invoked when each key is evaluated so that you can use application logic
132
- # to invalidate keys.
128
+ # If your cache is on a shared infrastructure, you can define a namespace
129
+ # for your cache entries. If a namespace is defined, it will be prefixed on
130
+ # to every key. The namespace can be either a static value or a Proc. If it
131
+ # is a Proc, it will be invoked when each key is evaluated so that you can
132
+ # use application logic to invalidate keys.
133
133
  #
134
134
  # cache.namespace = lambda { @last_mod_time } # Set the namespace to a variable
135
135
  # @last_mod_time = Time.now # Invalidate the entire cache by changing namespace
136
136
  #
137
137
  #
138
- # Caches can also store values in a compressed format to save space and reduce
139
- # time spent sending data. Since there is some overhead, values must be large
140
- # enough to warrant compression. To turn on compression either pass
141
- # <tt>:compress => true</tt> in the initializer or to +fetch+ or +write+.
142
- # To specify the threshold at which to compress values, set
143
- # <tt>:compress_threshold</tt>. The default threshold is 32K.
138
+ # Caches can also store values in a compressed format to save space and
139
+ # reduce time spent sending data. Since there is overhead, values must be
140
+ # large enough to warrant compression. To turn on compression either pass
141
+ # <tt>:compress => true</tt> in the initializer or as an option to +fetch+
142
+ # or +write+. To specify the threshold at which to compress values, set the
143
+ # <tt>:compress_threshold</tt> option. The default threshold is 16K.
144
144
  class Store
145
145
 
146
146
  cattr_accessor :logger, :instance_writer => true
@@ -150,7 +150,7 @@ module ActiveSupport
150
150
 
151
151
  # Create a new cache. The options will be passed to any write method calls except
152
152
  # for :namespace which can be used to set the global namespace for the cache.
153
- def initialize (options = nil)
153
+ def initialize(options = nil)
154
154
  @options = options ? options.dup : {}
155
155
  end
156
156
 
@@ -180,11 +180,11 @@ module ActiveSupport
180
180
  # Fetches data from the cache, using the given key. If there is data in
181
181
  # the cache with the given key, then that data is returned.
182
182
  #
183
- # If there is no such data in the cache (a cache miss occurred),
184
- # then nil will be returned. However, if a block has been passed, then
185
- # that block will be run in the event of a cache miss. The return value
186
- # of the block will be written to the cache under the given cache key,
187
- # and that return value will be returned.
183
+ # If there is no such data in the cache (a cache miss), then nil will be
184
+ # returned. However, if a block has been passed, that block will be run
185
+ # in the event of a cache miss. The return value of the block will be
186
+ # written to the cache under the given cache key, and that return value
187
+ # will be returned.
188
188
  #
189
189
  # cache.write("today", "Monday")
190
190
  # cache.fetch("today") # => "Monday"
@@ -205,10 +205,11 @@ module ActiveSupport
205
205
  # in a compressed format.
206
206
  #
207
207
  #
208
- # Setting <tt>:expires_in</tt> will set an expiration time on the cache. All caches
209
- # support auto expiring content after a specified number of seconds. This value can
210
- # be specified as an option to the construction in which call all entries will be
211
- # affected. Or it can be supplied to the +fetch+ or +write+ method for just one entry.
208
+ # Setting <tt>:expires_in</tt> will set an expiration time on the cache.
209
+ # All caches support auto-expiring content after a specified number of
210
+ # seconds. This value can be specified as an option to the constructor
211
+ # (in which case all entries will be affected), or it can be supplied to
212
+ # the +fetch+ or +write+ method to effect just one entry.
212
213
  #
213
214
  # cache = ActiveSupport::Cache::MemoryStore.new(:expires_in => 5.minutes)
214
215
  # cache.write(key, value, :expires_in => 1.minute) # Set a lower value for one entry
@@ -538,11 +539,11 @@ module ActiveSupport
538
539
  # Create an entry with internal attributes set. This method is intended to be
539
540
  # used by implementations that store cache entries in a native format instead
540
541
  # of as serialized Ruby objects.
541
- def create (raw_value, created_at, options = {})
542
+ def create(raw_value, created_at, options = {})
542
543
  entry = new(nil)
543
544
  entry.instance_variable_set(:@value, raw_value)
544
545
  entry.instance_variable_set(:@created_at, created_at.to_f)
545
- entry.instance_variable_set(:@compressed, !!options[:compressed])
546
+ entry.instance_variable_set(:@compressed, options[:compressed])
546
547
  entry.instance_variable_set(:@expires_in, options[:expires_in])
547
548
  entry
548
549
  end
@@ -555,15 +556,14 @@ module ActiveSupport
555
556
  @expires_in = options[:expires_in]
556
557
  @expires_in = @expires_in.to_f if @expires_in
557
558
  @created_at = Time.now.to_f
558
- unless value.nil?
559
- if should_compress?(value, options)
560
- @value = Zlib::Deflate.deflate(Marshal.dump(value))
559
+ if value.nil?
560
+ @value = nil
561
+ else
562
+ @value = Marshal.dump(value)
563
+ if should_compress?(@value, options)
564
+ @value = Zlib::Deflate.deflate(@value)
561
565
  @compressed = true
562
- else
563
- @value = value
564
566
  end
565
- else
566
- @value = nil
567
567
  end
568
568
  end
569
569
 
@@ -574,12 +574,11 @@ module ActiveSupport
574
574
 
575
575
  # Get the value stored in the cache.
576
576
  def value
577
- unless @value.nil?
578
- val = compressed? ? Marshal.load(Zlib::Inflate.inflate(@value)) : @value
579
- unless val.frozen?
580
- val.freeze rescue nil
581
- end
582
- val
577
+ # If the original value was exactly false @value is still true because
578
+ # it is marshalled and eventually compressed. Both operations yield
579
+ # strings.
580
+ if @value
581
+ Marshal.load(compressed? ? Zlib::Inflate.inflate(@value) : @value)
583
582
  end
584
583
  end
585
584
 
@@ -612,21 +611,16 @@ module ActiveSupport
612
611
  def size
613
612
  if @value.nil?
614
613
  0
615
- elsif @value.respond_to?(:bytesize)
616
- @value.bytesize
617
614
  else
618
- Marshal.dump(@value).bytesize
615
+ @value.bytesize
619
616
  end
620
617
  end
621
618
 
622
619
  private
623
- def should_compress?(value, options)
624
- if options[:compress] && value
625
- unless value.is_a?(Numeric)
626
- compress_threshold = options[:compress_threshold] || DEFAULT_COMPRESS_LIMIT
627
- serialized_value = value.is_a?(String) ? value : Marshal.dump(value)
628
- return true if serialized_value.size >= compress_threshold
629
- end
620
+ def should_compress?(serialized_value, options)
621
+ if options[:compress]
622
+ compress_threshold = options[:compress_threshold] || DEFAULT_COMPRESS_LIMIT
623
+ return true if serialized_value.size >= compress_threshold
630
624
  end
631
625
  false
632
626
  end