Module: ActsAsCached::ClassMethods
- Defined in:
- lib/acts_as_cached/cache_methods.rb
Constant Summary collapse
- @@nil_sentinel =
:_nil
Instance Method Summary collapse
- #cache_config ⇒ Object
- #cache_key(cache_id) ⇒ Object
- #cache_keys(*cache_ids) ⇒ Object
- #cache_name ⇒ Object
- #cache_namespace ⇒ Object
- #cache_options ⇒ Object
- #cached?(cache_id = nil) ⇒ Boolean (also: #is_cached?)
-
#caches(method, options = {}) ⇒ Object
(also: #cached)
Encapsulates the pattern of writing custom cache methods which do nothing but wrap custom finders.
- #expire_cache(cache_id = nil) ⇒ Object (also: #clear_cache)
- #fetch_cachable_data(cache_id = nil) ⇒ Object
- #fetch_cache(cache_id) ⇒ Object
- #get_cache(*args) ⇒ Object
-
#get_caches(*args) ⇒ Object
This method accepts an array of cache_ids which it will use to call get_multi on your cache store.
-
#get_caches_as_list(*args) ⇒ Object
simple wrapper for get_caches that returns the items as an ordered array.
-
#max_key_length ⇒ Object
Memcache-client automatically prepends the namespace, plus a colon, onto keys, so we take that into account for the max key length.
- #reset_cache(cache_id = nil) ⇒ Object
- #set_cache(cache_id, value, options = nil) ⇒ Object
Instance Method Details
#cache_config ⇒ Object
5 6 7 |
# File 'lib/acts_as_cached/cache_methods.rb', line 5 def cache_config @cache_config ||= {} end |
#cache_key(cache_id) ⇒ Object
184 185 186 |
# File 'lib/acts_as_cached/cache_methods.rb', line 184 def cache_key(cache_id) [cache_name, cache_config[:version], cache_id].compact.join('/').gsub(' ', '_')[0..(max_key_length - 1)] end |
#cache_keys(*cache_ids) ⇒ Object
180 181 182 |
# File 'lib/acts_as_cached/cache_methods.rb', line 180 def cache_keys(*cache_ids) cache_ids.flatten.map { |cache_id| cache_key(cache_id) } end |
#cache_name ⇒ Object
176 177 178 |
# File 'lib/acts_as_cached/cache_methods.rb', line 176 def cache_name @cache_name ||= respond_to?(:model_name) ? model_name.cache_key : name end |
#cache_namespace ⇒ Object
162 163 164 |
# File 'lib/acts_as_cached/cache_methods.rb', line 162 def cache_namespace Rails.cache.respond_to?(:namespace) ? Rails.cache.namespace : ActsAsCached.config[:namespace] end |
#cache_options ⇒ Object
9 10 11 |
# File 'lib/acts_as_cached/cache_methods.rb', line 9 def cache_config[:options] ||= {} end |
#cached?(cache_id = nil) ⇒ Boolean Also known as: is_cached?
144 145 146 |
# File 'lib/acts_as_cached/cache_methods.rb', line 144 def cached?(cache_id = nil) Rails.cache.exist?(cache_key(cache_id)) end |
#caches(method, options = {}) ⇒ Object Also known as: cached
Encapsulates the pattern of writing custom cache methods which do nothing but wrap custom finders.
=> Story.caches(:find_popular)
is the same as
def self.cached_find_popular
get_cache(:find_popular) { find_popular }
end
The method also accepts both a :ttl and/or a :with key.
Obviously the :ttl value controls how long this method will
stay cached, while the :with key's value will be passed along
to the method. The hash of the :with key will be stored with the key,
making two near-identical #caches calls with different :with values utilize
different caches.
=> Story.caches(:find_popular, :with => :today)
is the same as
def self.cached_find_popular
get_cache("find_popular:today") { find_popular(:today) }
end
If your target method accepts multiple parameters, pass :withs an array.
> Story.caches(:find_popular, :withs => [ :one, :two ])
is the same as
def self.cached_find_popular
get_cache("find_popular:onetwo") { find_popular(:one, :two) }
end
132 133 134 135 136 137 138 139 140 141 |
# File 'lib/acts_as_cached/cache_methods.rb', line 132 def caches(method, = {}) if .keys.include?(:with) with = .delete(:with) get_cache("#{method}:#{with}", ) { send(method, with) } elsif withs = .delete(:withs) get_cache("#{method}:#{withs}", ) { send(method, *withs) } else get_cache(method, ) { send(method) } end end |
#expire_cache(cache_id = nil) ⇒ Object Also known as: clear_cache
86 87 88 89 |
# File 'lib/acts_as_cached/cache_methods.rb', line 86 def expire_cache(cache_id = nil) Rails.cache.delete(cache_key(cache_id)) true end |
#fetch_cachable_data(cache_id = nil) ⇒ Object
153 154 155 156 157 158 159 160 |
# File 'lib/acts_as_cached/cache_methods.rb', line 153 def fetch_cachable_data(cache_id = nil) finder = cache_config[:finder] || :find return send(finder) unless cache_id args = [cache_id] args << .dup unless .blank? send(finder, *args) end |
#fetch_cache(cache_id) ⇒ Object
149 150 151 |
# File 'lib/acts_as_cached/cache_methods.rb', line 149 def fetch_cache(cache_id) Rails.cache.read(cache_key(cache_id)) end |
#get_cache(*args) ⇒ Object
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# File 'lib/acts_as_cached/cache_methods.rb', line 13 def get_cache(*args) = args.last.is_a?(Hash) ? args.pop : {} args = args.flatten ## # head off to get_caches if we were passed multiple cache_ids if args.size > 1 return get_caches(args, ) else cache_id = args.first end if (item = fetch_cache(cache_id)).nil? set_cache(cache_id, block_given? ? yield : fetch_cachable_data(cache_id), ) else @@nil_sentinel == item ? nil : item end end |
#get_caches(*args) ⇒ Object
This method accepts an array of cache_ids which it will use to call get_multi on your cache store. Any misses will be fetched and saved to the cache, and a hash keyed by cache_id will ultimately be returned.
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/acts_as_cached/cache_methods.rb', line 37 def get_caches(*args) = args.last.is_a?(Hash) ? args.pop : {} cache_ids = args.flatten.map(&:to_s) keys = cache_keys(cache_ids) # Map memcache keys to object cache_ids in { memcache_key => object_id } format keys_map = Hash[*keys.zip(cache_ids).flatten] # Call get_multi and figure out which keys were missed based on what was a hit hits = Rails.cache.read_multi(*keys) || {} # Misses can take the form of key => nil hits.delete_if { |key, value| value.nil? } misses = keys - hits.keys hits.each { |k, v| hits[k] = nil if v == @@nil_sentinel } # Return our hash if there are no misses return hits.values.index_by(&:cache_id) if misses.empty? # Find any missed records needed_ids = keys_map.values_at(*misses) missed_records = Array(fetch_cachable_data(needed_ids)) # Cache the missed records missed_records.each { |missed_record| missed_record.set_cache() } # Return all records as a hash indexed by object cache_id (hits.values + missed_records).index_by(&:cache_id) end |
#get_caches_as_list(*args) ⇒ Object
simple wrapper for get_caches that returns the items as an ordered array
70 71 72 73 74 75 76 77 78 |
# File 'lib/acts_as_cached/cache_methods.rb', line 70 def get_caches_as_list(*args) cache_ids = args.last.is_a?(Hash) ? args.first : args cache_ids = [cache_ids].flatten hash = get_caches(*args) cache_ids.map do |key| hash[key] end end |
#max_key_length ⇒ Object
Memcache-client automatically prepends the namespace, plus a colon, onto keys, so we take that into account for the max key length. Rob Sanheim
168 169 170 171 172 173 174 |
# File 'lib/acts_as_cached/cache_methods.rb', line 168 def max_key_length unless @max_key_length key_size = cache_config[:key_size] || 250 @max_key_length = cache_namespace ? (key_size - cache_namespace.length - 1) : key_size end @max_key_length end |
#reset_cache(cache_id = nil) ⇒ Object
92 93 94 |
# File 'lib/acts_as_cached/cache_methods.rb', line 92 def reset_cache(cache_id = nil) set_cache(cache_id, fetch_cachable_data(cache_id)) end |
#set_cache(cache_id, value, options = nil) ⇒ Object
80 81 82 83 84 |
# File 'lib/acts_as_cached/cache_methods.rb', line 80 def set_cache(cache_id, value, = nil) v = value.nil? ? @@nil_sentinel : value Rails.cache.write(cache_key(cache_id), v, ) value end |