module HashPersistent module Collection def self.included(base) base.extend ClassMethods_Initial base.module_eval do include HashPersistent::Resource end end module ClassMethods_Initial def attach(resource_class, collection_basis) raise "You must create a persistent subclass before attaching this collection class. Use HashPersistent::persist_to()" unless included_modules.include?(HashPersistent::Resource::InstanceMethods) raise "You can attach this collection class only to a class that has been created with HashPersistent::Resource.persist_to()" unless resource_class.included_modules.include?(HashPersistent::Resource::InstanceMethods) raise "Did not find the specified basis attribute (#{collection_basis}) in the given resource class" unless resource_class.instance_methods.include?(collection_basis.to_s) extend ClassMethods include InstanceMethods @collection_basis = collection_basis @resource_class = resource_class resource_class.on_save do |resource| collected_resource_saved(resource) end resource_class.on_delete do |resource| collected_resource_deleted(resource) end end end module ClassMethods attr_reader :resource_class def collected_resource_saved(resource) collection = find(resource.send(@collection_basis)) unless collection collection = new collection.collected_keys = [] collection.key = resource.send(@collection_basis) end collection.collected_keys << resource.key collection.collected_keys.uniq! collection.save end def collected_resource_deleted(resource) collection = find(resource.send(@collection_basis)) collection.collected_keys.delete(resource.key) if collection.collected_keys.empty? collection.delete else collection.save end end end module InstanceMethods attr_accessor :collected_keys def collected_resources collected_keys.collect do |key| self.class.resource_class.send(:find, key) end end end end end