Commits the current change set information to the database,
        or inserts this object as a new record into the database.
        This method will only update the database if the record
        has any local changes to it, otherwise, no commit will
        take place.  If the dryRun flag is set, then the SQL
        will be logged but not executed.

        :param values: None or dictionary of values to update before save
        :param after: <orb.Model> || None (optional)
                      if provided, this save call will be delayed
                      until after the given record has been saved,
                      triggering a PostSaveEvent callback
        :param before: <orb.Model> || None (optional)
                      if provided, this save call will be delayed
                      until before the given record is about to be
                      saved, triggering a PreSaveEvent callback


        :note       From version 0.6.0 on, this method now accepts a mutable
                    keyword dictionary of values.  You can supply any member
                    value for either the <orb.LookupOptions> or
                    <orb.Context>, 'options' for
                    an instance of the <orb.Context>

        :return     <bool> success

def save(self, values=None, after=None, before=None, **context):
        """
        Commits the current change set information to the database,
        or inserts this object as a new record into the database.
        This method will only update the database if the record
        has any local changes to it, otherwise, no commit will
        take place.  If the dryRun flag is set, then the SQL
        will be logged but not executed.

        :param values: None or dictionary of values to update before save
        :param after: <orb.Model> || None (optional)
                      if provided, this save call will be delayed
                      until after the given record has been saved,
                      triggering a PostSaveEvent callback
        :param before: <orb.Model> || None (optional)
                      if provided, this save call will be delayed
                      until before the given record is about to be
                      saved, triggering a PreSaveEvent callback


        :note       From version 0.6.0 on, this method now accepts a mutable
                    keyword dictionary of values.  You can supply any member
                    value for either the <orb.LookupOptions> or
                    <orb.Context>, 'options' for
                    an instance of the <orb.Context>

        :return     <bool> success
        """
        # specify that this save call should be performed after the save of
        # another record, useful for chaining events
        if after is not None:
            callback = orb.events.Callback(self.save, values=values, **context)
            after.addCallback(orb.events.PostSaveEvent, callback, record=after, once=True)
            return callback

        # specify that this save call should be performed before the save
        # of another record, useful for chaining events
        elif before is not None:
            callback = orb.events.Callback(self.save, values=values, **context)
            after.addCallback(orb.events.PreSaveEvent, callback, record=after, once=True)
            return callback

        if values is not None:
            self.update(values, **context)

        # create the commit options
        context = self.context(**context)
        new_record = not self.isRecord()

        # create the pre-commit event
        changes = self.changes(columns=context.columns)
        event = orb.events.PreSaveEvent(record=self, context=context, newRecord=new_record, changes=changes)
        if self.processEvent(event):
            self.onPreSave(event)

        if event.preventDefault:
            return event.result

        # check to see if we have any modifications to store
        if not (self.isModified() and self.validate()):
            return False

        conn = context.db.connection()
        if not self.isRecord():
            records, _ = conn.insert([self], context)
            if records:
                event = orb.events.LoadEvent(record=self, data=records[0])
                self._load(event)
        else:
            conn.update([self], context)

        # mark all the data as committed
        cols = [self.schema().column(c).name() for c in context.columns or []]
        with WriteLocker(self.__dataLock):
            for col_name, (_, value) in self.__values.items():
                if not cols or col_name in cols:
                    self.__values[col_name] = (value, value)

        # create post-commit event
        event = orb.events.PostSaveEvent(record=self, context=context, newRecord=new_record, changes=changes)
        if self.processEvent(event):
            self.onPostSave(event)
        return True