module Og # An 'active' collection that reflects a relation. # A collection stores entitities that participate in # a relation. class Collection # The owner of this collection. attr_accessor :owner # The members of this collection. Keeps the objects # that belong to this collection. attr_accessor :members # A method used to add insert objects in the collection. attr_accessor :insert_proc # A method used to remove objects from the collection. attr_accessor :remove_proc # A method used to find the objects that belong to the # collection. attr_accessor :find_proc # The default find options. attr_accessor :find_options # Is the collection in build mode? attr_accessor :building # Is the collection loaded? attr_accessor :loaded # Initialize the collection. def initialize(owner = nil, insert_proc = nil, remove_proc = nil, find_proc = nil, find_options = {}) @owner = owner @insert_proc = insert_proc @remove_proc = remove_proc @find_proc = find_proc @find_options = find_options @members = [] @loaded = false @building = false end # Load the members of the collection. def load_members unless @loaded @members = @owner.send(@find_proc, @find_options) @loaded = true end @members end # Reload the collection. def reload(options) # gmosx, NOOO: this was a bug! it corrupts the default options. # @find_options = options @members = @owner.send(@find_proc, options) end # Convert the collection to an array. def to_ary load_members @members end # Defined to avoid the method missing overhead. def each(&block) load_members @members.each(&block) end # Defined to avoid the method missing overhead. def [](idx) load_members @members[idx] end # Add a new member to the collection. def push(obj) @members.push(obj) unless @building or owner.unsaved? @owner.send(@insert_proc, obj) end end alias_method :<<, :push alias_method :add, :push # Remove a member from the collection, the actual object # is not deleted. def remove(*objects) objects = objects.flatten objects.reject! { |obj| @members.delete(obj) if obj.unsaved? } return if objects.empty? @owner.transaction do objects.each do |obj| @owner.send(@remove_proc, obj) @members.delete(obj) end end end # Delete a member from the collection AND the store. def delete(*objects) objects = objects.flatten objects.reject! { |obj| @members.delete(obj) if obj.unsaved? } return if objects.empty? @owner.transaction do objects.each do |obj| obj.delete @members.delete(obj) end end end # Remove all members from the collection. def remove_all @owner.transaction do @members.each { |obj| @owner.send(@remove_proc, obj) } end @members.clear end alias_method :clear, :remove_all # Delete all members of the collection. Also delete from the # store. def delete_all @owner.transaction do @members.each { |obj| obj.delete } end @members.clear end # Redirect all other methods to the members array. def method_missing(symbol, *args, &block) load_members @members.send(symbol, *args, &block) end private def check_type(obj) end end end # * George Moschovitis # * Julien Perrot