beatrichartz/exchange

View on GitHub
lib/exchange/cache/redis.rb

Summary

Maintainability
A
1 hr
Test Coverage
# -*- encoding : utf-8 -*-
module Exchange
  module Cache
    # @author Beat Richartz
    # A class that cooperates with the redis gem and the redis key value store to cache the data from the exchange api in redis
    # 
    # @version 0.1
    # @since 0.1
    # @example Activate caching via redis by setting the cache in the configuration to :redis
    #   Exchange::Configuration.define do |c| 
    #     c.cache = :redis
    #     c.cache_host = 'Your redis host' 
    #     c.cache_port = 'Your redis port (an Integer)'
    #   end
    class Redis < Base
      
      # delegate the client and wiping the client to the instance
      #
      def_delegators :instance, :client, :wipe_client!
      
      # instantiates a redis client and memoizes it in a class variable.
      # Use this client to access redis data. For further explanation of use visit the redis gem documentation
      # @example
      #   Exchange::Cache::Redis.client.set('FOO', 'BAR')
      # @return [::Redis] an instance of the redis client gem class
      #
      def client
        Exchange::GemLoader.new('redis').try_load unless defined?(::Redis)
        @client ||= ::Redis.new(:host => config.host, :port => config.port)
      end
      
      # Wipe the client instance variable
      #
      def wipe_client!
        @client = nil
      end
      
      # returns either cached data from the redis client or calls the block and caches it in redis.
      # This method has to be the same in all the cache classes in order for the configuration binding to work
      # @param [Exchange::ExternalAPI::Subclass] api The API class the data has to be stored for
      # @param [Hash] opts the options to cache with
      # @option opts [Time] :at the historic time of the exchange rates to be cached
      # @yield [] This method takes a mandatory block with an arity of 0 and calls it if no cached result is available
      # @raise [CachingWithoutBlockError] an Argument Error when no mandatory block has been given
      #
      def cached api, opts={}, &block         
        if result = client.get(key(api, opts))
          result = opts[:plain] ? result : result.decachify
        else
          result = super
          if result && !result.to_s.empty?
            client.set key(api, opts), result.cachify
            client.expire key(api, opts), config.expire == :daily ? 86400 : 3600
          end
        end
        
        result
      end
      
    end
  end
end