def add_lazy_loader(loader, attributes=nil)
      # guard against invalid call
      if identifier.nil? then raise ValidationError.new("Cannot add lazy loader to an unfetched domain object: #{self}") end
      # the attributes to lazy-load
      attributes ||= loadable_attributes
      return if attributes.empty?
      # define the reader and writer method overrides for the missing attributes
      pas = attributes.select { |pa| inject_lazy_loader(pa) }
      logger.debug { "Lazy loader added to #{qp} attributes #{pas.to_series}." } unless pas.empty?
    end
def add_lazy_loader(loader, attributes=nil)
      # guard against invalid call
      if identifier.nil? then raise ValidationError.new("Cannot add lazy loader to an unfetched domain object: #{self}") end
      # the attributes to lazy-load
      attributes ||= loadable_attributes
      return if attributes.empty?
      # define the reader and writer method overrides for the missing attributes
      pas = attributes.select { |pa| inject_lazy_loader(pa) }
      logger.debug { "Lazy loader added to #{qp} attributes #{pas.to_series}." } unless pas.empty?
    end
Lazy loads the attributes. If a block is given to this method, then the attributes are determined
 by calling the block with this Persistable as a parameter. Otherwise, the default attributes
 are the unfetched domain attributes.

 Each of the attributes which does not already hold a non-nil or non-empty value
 will be loaded from the database on demand.
 This method injects attribute value initialization into each loadable attribute reader.
 The initializer is given by either the loader Proc argument.
 The loader takes two arguments, the target object and the attribute to load.
 If this Persistable already has a lazy loader, then this method is a no-op.

 Lazy loading is disabled on an attribute after it is invoked on that attribute or when the
 attribute setter method is called.

 @param loader [LazyLoader] the lazy loader to add