lib/cached_resource/caching.rb in cached_resource-2.0.1 vs lib/cached_resource/caching.rb in cached_resource-2.1.1a
- old
+ new
@@ -9,44 +9,94 @@
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
+ # 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
+ should_reload ? find_via_reload(key, *arguments) : find_via_cache(key, *arguments)
end
private
- # try to find a cached response for the given key. If
+ # 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)
- result = cached_resource.cache.read(key).try(:dup)
- result && cached_resource.logger.info("#{CachedResource::Configuration::LOGGER_PREFIX} READ #{key} for #{arguments.inspect}")
- result || find_via_reload(key, *arguments)
+ cache_read(key) || find_via_reload(key, *arguments)
end
- # re/send the request to fetch the resource. Cache the response
+ # Re/send the request to fetch the resource. Cache the response
# for the request.
def find_via_reload(key, *arguments)
- result = find_without_cache(*arguments)
- cached_resource.cache.write(key, result, :expires_in => cached_resource.ttl)
- cached_resource.logger.info("#{CachedResource::Configuration::LOGGER_PREFIX} WRITE #{key} for #{arguments.inspect}")
+ object = find_without_cache(*arguments)
+ cache_collection_synchronize(object, *arguments) if cached_resource.collection_synchronize
+ 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)
+ if object.is_a? Array
+ update_singles_cache(object)
+ # update the collection only if this is a subset of it
+ update_collection_cache(object) unless is_collection?(*arguments)
+ else
+ update_collection_cache(object)
+ end
+ end
+
+ # Update the cache of singles with an array of updates.
+ def update_singles_cache(updates)
+ updates = Array(updates)
+ updates.each { |object| cache_write(object.send(primary_key), object) }
+ end
+
+ # Update the "mother" collection with an array of updates.
+ def update_collection_cache(updates)
+ updates = Array(updates)
+ collection = cache_read(cached_resource.collection_arguments)
+
+ if collection && !updates.empty?
+ store = RUBY_VERSION.to_f < 1.9 ? ActiveSupport::OrderedHash.new : {}
+ index = collection.inject(store) { |hash, object| hash[object.send(primary_key)] = object; hash }
+ updates.each { |object| index[object.send(primary_key)] = object }
+ cache_write(cached_resource.collection_arguments, index.values)
+ end
+ end
+
+ # Determine if the given arguments represent
+ # the entire collection of objects.
+ def is_collection?(*arguments)
+ arguments == cached_resource.collection_arguments
+ end
+
+ # Read a entry from the cache for the given key.
+ # The 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
+ result = cached_resource.cache.write(key, object, :expires_in => cached_resource.ttl)
+ result && cached_resource.logger.info("#{CachedResource::Configuration::LOGGER_PREFIX} WRITE #{key}")
result
end
- # generate the request cache key
+ # Generate the request cache key.
def cache_key(*arguments)
"#{name.parameterize.gsub("-", "/")}/#{arguments.join('/')}".downcase
end
end
\ No newline at end of file