forked from mhgbrown/cached_resource
/
caching.rb
84 lines (72 loc) · 3.09 KB
/
caching.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
module CachedResource
# The Caching module is included in ActiveResource and
# handles caching and recaching of responses.
module Caching
extend ActiveSupport::Concern
included do
class << self
alias_method_chain :find, :cache
end
end
module ClassMethods
# Find a resource using the cache or resend the request
# if :reload is set to true or caching is disabled.
def find_with_cache(*arguments)
arguments << {} unless arguments.last.is_a?(Hash)
should_reload = arguments.last.delete(:reload) || !cached_resource.enabled
arguments.pop if arguments.last.empty?
key = cache_key(arguments)
begin
(should_reload ? find_via_reload(key, *arguments) : find_via_cache(key, *arguments))
rescue ActiveResource::ServerError, ActiveResource::ConnectionError, SocketError => e
raise(e)
end
end
private
# Try to find a cached response for the given key. If
# no cache entry exists, send a new request.
def find_via_cache(key, *arguments)
cache_read(key) || find_via_reload(key, *arguments)
end
# Re/send the request to fetch the resource. Cache the response
# for the request.
def find_via_reload(key, *arguments)
object = find_without_cache(*arguments)
cache_collection_synchronize(object, *arguments)
cache_write(key, object)
object
end
# If this is a pure, unadulterated "all" request
# write cache entries for all its members
# otherwise update an existing collection if possible.
def cache_collection_synchronize(object, *arguments)
return unless cached_resource.collection_synchronize
if arguments.length == 1 && arguments[0] == :all
object.each {|r| cache_write(cached_resource.get_resource_id(r), r)}
elsif !arguments.include?(:all) && (collection = cache_read(:all))
collection.each_with_index {|member, i| collection[i] = object if cached_resource.get_resource_id(member) == cached_resource.get_resource_id(object)}
cache_write(:all, collection)
end
end
# Read a entry from the cache for the given key.
# Rhe key is processed to make sure it is valid.
def cache_read(key)
key = cache_key(Array(key)) unless key.is_a? String
object = cached_resource.cache.read(key).try(:dup)
object && cached_resource.logger.info("#{CachedResource::Configuration::LOGGER_PREFIX} READ #{key}")
object
end
# Write an entry to the cache for the given key and value.
# The key is processed to make sure it is valid.
def cache_write(key, object)
key = cache_key(Array(key)) unless key.is_a? String
cached_resource.logger.info("#{CachedResource::Configuration::LOGGER_PREFIX} WRITE #{key}")
cached_resource.cache.write(key, object, :expires_in => cached_resource.ttl)
end
# generate the request cache key
def cache_key(*arguments)
"#{name.parameterize.gsub("-", "/")}/#{arguments.join('/')}".downcase
end
end
end
end