module HashPersistent class Store attr_reader :key_value_store, :key_prefix, :cached_to def initialize(key_value_store, key_prefix) raise ArgumentError unless key_value_store.respond_to?(:has_key?) and key_prefix.respond_to?(:to_s) @key_value_store = key_value_store @key_prefix = key_prefix yield self if block_given? end def cached_to=(cache) raise ArgumentError unless cache.is_a?(HashPersistent::Store) if cache @cached_to = cache end def save(object) store_this = object.dup store_this.store = nil if store_this.respond_to?(:store) @key_value_store[@key_prefix + store_this.key] = store_this @cached_to.save(object) if @cached_to object.store = self if object.respond_to?(:store) self end def delete(object) @key_value_store.delete(@key_prefix + object.key) @cached_to.delete(object) if @cached_to object.store = self if object.respond_to?(:store) self end def find(key) if @cached_to found = @cached_to.find(key) unless found found = @key_value_store[@key_prefix + key] @cached_to.save(found) if found end else found = @key_value_store[@key_prefix + key] end return nil unless found object = found.dup object.store = self if object.respond_to?(:store) object end def create(key, class_to_create, *args, &block) object = class_to_create.new(*args, &block) object.key = key object.store = self if object.respond_to?(:store) object end def find_or_create(key, class_to_create, *args, &block) #TODO: Lock? save(create(key, class_to_create, *args, &block)) unless find(key) find(key) end end end