   set: (key, value) ->
     @_object ?= {}
     if @getRelationships()?[key]?
-      return e "Not inserted object should not be able to set up relationship, please fix this" unless @isInserted()
-      relationship = @getRelationships()[key]
-
+      throw "Attempt to set a value to a '#{@getRelationships()[key].type.replace('_', ':')}'" if _.contains(['many_one', 'many_many'], @getRelationships()[key].type)
+      @_pendingRelationships ?= {}
+      @_pendingRelationships[key] = {value: value, add: if value? then yes else no}
     else
       @_object[key] = value
     @_needsUpdate = yes
 
   remove: (key, value) ->
+    unless value?
+      return @set(key, null)
+    if @getRelationships()?[key]?
+      throw "Attempt to remove a value to a '#{@getRelationships()[key].type.replace('_', ':')}'" if _.contains(['one_one', 'one_many'], @getRelationships()[key].type)
+      @_pendingRelationships ?= {}
+      @_pendingRelationships[key] ?= []
+      @_pendingRelationships[key].push {value: value, add: yes}
+    else if _.isArray(@_object[key])
+      if _.contains(@_object[key], value)
+        @_object[key] = _.without(@_object[key], value)
+        return true
+      else
+        return false
 
   add: (key, value) ->
+    if @getRelationships()?[key]?
+      throw "Attempt to add a value to a '#{@getRelationships()[key].type.replace('_', ':')}'" if _.contains(['one_one', 'one_many'], @getRelationships()[key].type)
+      @_pendingRelationships ?= {}
+      @_pendingRelationships[key] ?= []
+      @_pendingRelationships[key].push {value: value, add: yes}
+    else if not @_object[key]? or _.isArray(@_object[key])
+      @_object[key] ?= []
+      if _.contains(@_object[key], value)
+        return false
+      else
+        @_object[key].push value
+        return true
 
   save: () ->
-    if @isInserted() and @hasChange()
-      @_collection.update @_object
-    else
-      @_object ?= {}
-      @_collection.insert()
+    if @isInserted() and @hasChange() and @onUpdate() isnt false
+      @_commitPendingRelationship()
+      @_collection.update this
+    else if @onInsert() isnt false
+      @_collection.insert this
+      @_commitPendingRelationship()
       @_needsUpdate = no
 
   delete: () ->
-    unless @_deleted
+    if not @_deleted and @onDelete() isnt false
       @_deleted = true
       @_collection.remove @_object
 
+  # Called before insertion
+  # @return Return false if you want to cancel the insertion
+  onInsert: () ->
+
+  # Called before delete
+  # @return Return false if you want to cancel the deletion
+  onDelete: () ->
+
+  # Called before update
+  # @return Return false if you want to cancel the update
+  onUpdate: () ->
+
+  # Called before a model is added to another model as a many_* relationship
+  onAdd: () ->
+
+  # Called before a model is removed from another model as a many_* relationship
+  onRemove: () ->
+
+
   isInserted: () -> if @_object?.meta? then yes else no
 
   isDeleted: () -> @_deleted

    sort = null
    if relationshipDeclaration['sortBy']?
      sort = relationshipDeclaration['sortBy']
      sort = [sort, false] unless _.isArray(sort)
    onDelete = 'nullify' unless relationshipDeclaration['onDelete']?
    relationship = name: r[0], type: "#{myType}_#{i[1]}", inverse: i[0], Class: r[1], inverseType: "#{i[1]}_#{myType}", sort: sort, onDelete: onDelete
    @_relationships ?= {}
    @_relationships[relationship.name] = relationship

          continue
        else if not InverseClass._relationships?[relationship.inverse]
          InverseClass._relationships ?= {}
          InverseClass._relationships[relationship.inverse] = name: relationship.inverse, type: relationship.inverseType, inverse:relationship.name, Class: ClassName, inverseType: relationship.type, onDelete: 'nullify'
        else
          e "Bad relationship #{relationship.name} <-> #{relationship.inverse}. You must absolutely check for errors for classes #{ClassName} and #{relationship.Class}"

