Skip to content

Instantly share code, notes, and snippets.

@justinko
Created March 1, 2013 20:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save justinko/5067346 to your computer and use it in GitHub Desktop.
Save justinko/5067346 to your computer and use it in GitHub Desktop.
class AppCache
def initialize
@store = Store.new
end
def cache(*keys, &block)
options = keys.extract_options!
@store.cache(keys, options[:expires_in], &block)
end
class Store
def initialize
@cached_objects = CachedObjects.new
end
def cache(keys, expires_in, &block)
cached_object = @cached_objects.find(keys)
return nil if not cached_object and not block
if not cached_object or cached_object.expired?
block = block || cached_object.block
cached_object = CachedObject.new(block, expires_in)
@cached_objects.add keys, cached_object
end
cached_object.object
end
class CachedObjects
def initialize(cached_objects = {})
@cached_objects = cached_objects
end
def find(keys)
keys.inject(@cached_objects) {|memo, key| Hash === memo ? memo[convert_key(key)] : return }
end
def add(keys, cached_object)
@cached_objects.merge! keys.reverse.inject(cached_object) {|memo, key| {convert_key(key) => memo} }
end
private
def convert_key(key)
Symbol === key ? key.to_s : key
end
end
class CachedObject
attr_reader :object, :block
def initialize(block, expires_in)
@expires_in = expires_in.try(:to_f)
@created_at = Time.now.to_f
@object = block.call
@block = block
end
def expired?
@expires_in && @created_at + @expires_in <= Time.now.to_f
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment