Froze rails gems
[depot.git] / vendor / rails / activesupport / lib / active_support / cache.rb
1 require 'benchmark'
2
3 module ActiveSupport
4 # See ActiveSupport::Cache::Store for documentation.
5 module Cache
6 # Creates a new CacheStore object according to the given options.
7 #
8 # If no arguments are passed to this method, then a new
9 # ActiveSupport::Cache::MemoryStore object will be returned.
10 #
11 # If you pass a Symbol as the first argument, then a corresponding cache
12 # store class under the ActiveSupport::Cache namespace will be created.
13 # For example:
14 #
15 # ActiveSupport::Cache.lookup_store(:memory_store)
16 # # => returns a new ActiveSupport::Cache::MemoryStore object
17 #
18 # ActiveSupport::Cache.lookup_store(:drb_store)
19 # # => returns a new ActiveSupport::Cache::DRbStore object
20 #
21 # Any additional arguments will be passed to the corresponding cache store
22 # class's constructor:
23 #
24 # ActiveSupport::Cache.lookup_store(:file_store, "/tmp/cache")
25 # # => same as: ActiveSupport::Cache::FileStore.new("/tmp/cache")
26 #
27 # If the first argument is not a Symbol, then it will simply be returned:
28 #
29 # ActiveSupport::Cache.lookup_store(MyOwnCacheStore.new)
30 # # => returns MyOwnCacheStore.new
31 def self.lookup_store(*store_option)
32 store, *parameters = *([ store_option ].flatten)
33
34 case store
35 when Symbol
36 store_class_name = (store == :drb_store ? "DRbStore" : store.to_s.camelize)
37 store_class = ActiveSupport::Cache.const_get(store_class_name)
38 store_class.new(*parameters)
39 when nil
40 ActiveSupport::Cache::MemoryStore.new
41 else
42 store
43 end
44 end
45
46 def self.expand_cache_key(key, namespace = nil)
47 expanded_cache_key = namespace ? "#{namespace}/" : ""
48
49 if ENV["RAILS_CACHE_ID"] || ENV["RAILS_APP_VERSION"]
50 expanded_cache_key << "#{ENV["RAILS_CACHE_ID"] || ENV["RAILS_APP_VERSION"]}/"
51 end
52
53 expanded_cache_key << case
54 when key.respond_to?(:cache_key)
55 key.cache_key
56 when key.is_a?(Array)
57 key.collect { |element| expand_cache_key(element) }.to_param
58 when key
59 key.to_param
60 end.to_s
61
62 expanded_cache_key
63 end
64
65 # An abstract cache store class. There are multiple cache store
66 # implementations, each having its own additional features. See the classes
67 # under the ActiveSupport::Cache module, e.g.
68 # ActiveSupport::Cache::MemCacheStore. MemCacheStore is currently the most
69 # popular cache store for large production websites.
70 #
71 # ActiveSupport::Cache::Store is meant for caching strings. Some cache
72 # store implementations, like MemoryStore, are able to cache arbitrary
73 # Ruby objects, but don't count on every cache store to be able to do that.
74 #
75 # cache = ActiveSupport::Cache::MemoryStore.new
76 #
77 # cache.read("city") # => nil
78 # cache.write("city", "Duckburgh")
79 # cache.read("city") # => "Duckburgh"
80 class Store
81 cattr_accessor :logger
82
83 def silence!
84 @silence = true
85 self
86 end
87
88 # Fetches data from the cache, using the given key. If there is data in
89 # the cache with the given key, then that data is returned.
90 #
91 # If there is no such data in the cache (a cache miss occurred), then
92 # then nil will be returned. However, if a block has been passed, then
93 # that block will be run in the event of a cache miss. The return value
94 # of the block will be written to the cache under the given cache key,
95 # and that return value will be returned.
96 #
97 # cache.write("today", "Monday")
98 # cache.fetch("today") # => "Monday"
99 #
100 # cache.fetch("city") # => nil
101 # cache.fetch("city") do
102 # "Duckburgh"
103 # end
104 # cache.fetch("city") # => "Duckburgh"
105 #
106 # You may also specify additional options via the +options+ argument.
107 # Setting <tt>:force => true</tt> will force a cache miss:
108 #
109 # cache.write("today", "Monday")
110 # cache.fetch("today", :force => true) # => nil
111 #
112 # Other options will be handled by the specific cache store implementation.
113 # Internally, #fetch calls #read, and calls #write on a cache miss.
114 # +options+ will be passed to the #read and #write calls.
115 #
116 # For example, MemCacheStore's #write method supports the +:expires_in+
117 # option, which tells the memcached server to automatically expire the
118 # cache item after a certain period. We can use this option with #fetch
119 # too:
120 #
121 # cache = ActiveSupport::Cache::MemCacheStore.new
122 # cache.fetch("foo", :force => true, :expires_in => 5.seconds) do
123 # "bar"
124 # end
125 # cache.fetch("foo") # => "bar"
126 # sleep(6)
127 # cache.fetch("foo") # => nil
128 def fetch(key, options = {})
129 @logger_off = true
130 if !options[:force] && value = read(key, options)
131 @logger_off = false
132 log("hit", key, options)
133 value
134 elsif block_given?
135 @logger_off = false
136 log("miss", key, options)
137
138 value = nil
139 seconds = Benchmark.realtime { value = yield }
140
141 @logger_off = true
142 write(key, value, options)
143 @logger_off = false
144
145 log("write (will save #{'%.2f' % (seconds * 1000)}ms)", key, nil)
146
147 value
148 end
149 end
150
151 # Fetches data from the cache, using the given key. If there is data in
152 # the cache with the given key, then that data is returned. Otherwise,
153 # nil is returned.
154 #
155 # You may also specify additional options via the +options+ argument.
156 # The specific cache store implementation will decide what to do with
157 # +options+.
158 def read(key, options = nil)
159 log("read", key, options)
160 end
161
162 # Writes the given value to the cache, with the given key.
163 #
164 # You may also specify additional options via the +options+ argument.
165 # The specific cache store implementation will decide what to do with
166 # +options+.
167 #
168 # For example, MemCacheStore supports the +:expires_in+ option, which
169 # tells the memcached server to automatically expire the cache item after
170 # a certain period:
171 #
172 # cache = ActiveSupport::Cache::MemCacheStore.new
173 # cache.write("foo", "bar", :expires_in => 5.seconds)
174 # cache.read("foo") # => "bar"
175 # sleep(6)
176 # cache.read("foo") # => nil
177 def write(key, value, options = nil)
178 log("write", key, options)
179 end
180
181 def delete(key, options = nil)
182 log("delete", key, options)
183 end
184
185 def delete_matched(matcher, options = nil)
186 log("delete matched", matcher.inspect, options)
187 end
188
189 def exist?(key, options = nil)
190 log("exist?", key, options)
191 end
192
193 def increment(key, amount = 1)
194 log("incrementing", key, amount)
195 if num = read(key)
196 write(key, num + amount)
197 else
198 nil
199 end
200 end
201
202 def decrement(key, amount = 1)
203 log("decrementing", key, amount)
204 if num = read(key)
205 write(key, num - amount)
206 else
207 nil
208 end
209 end
210
211 private
212 def log(operation, key, options)
213 logger.debug("Cache #{operation}: #{key}#{options ? " (#{options.inspect})" : ""}") if logger && !@silence && !@logger_off
214 end
215 end
216 end
217 end
218
219 require 'active_support/cache/file_store'
220 require 'active_support/cache/memory_store'
221 require 'active_support/cache/drb_store'
222 require 'active_support/cache/mem_cache_store'
223 require 'active_support/cache/compressed_mem_cache_store'