public static function unrelate($options) {
        self::_normalizeOptionsForUnrelate($options);
        $modelA  = $options['modelA'];
        $modelB  = $options['modelB'];

        /**
         * If bindingModel is set, we can safely skip all those difficult checks below.
         */
        if (is_object($options['bindingModel'])) {
            return self::_unrelateHasAndBelongsToMany($options);
        }
        try {
            /**
             * If this succeeds, it's a regular relationship where the foreign key
             * resides inside modelA. Continue as usual.
             */
            $reference = $modelA->getReference(get_class($modelB), $options['rule']);
        } catch (Exception $e) {
            if (!self::isInvalidReferenceException($e)) {
                throw $e;
            }
            try {
                /**
                 * If this succeeds, the foreign key resides in the modelA.
                 * Flip modelA and modelB and keyA and keyB in order to normalize the
                 * given configuration.
                 * Call self::relate() recursively with these new options.
                 */
                $reference = $modelB->getReference(get_class($modelA), $options['rule']);

                $keyA = $options['keyA'];
                $keyB = $options['keyB'];
                $options['modelA'] = $modelB;
                $options['modelB'] = $modelA;
                $options['keyA'] = $keyB;
                $options['keyB'] = $keyA;
                return Garp_Content_Relation_Manager::unrelate($options);
            } catch (Exception $e) {
                if (!self::isInvalidReferenceException($e)) {
                    throw $e;
                }
                /**
                 * Goody, we're dealing with a hasAndBelongsToMany relationship here.
                 * Try to construct the intersection model and save the relation
                 * that way.
                 */
                return self::_unrelateHasAndBelongsToMany($options);
            }
        }

        /**
         * Figure out which model is leading. This depends on which of the two keys is provided.
         * This kind of flips the query around. For instance, when keyA is given, the query is
         * something like this:
         * UPDATE modelA SET foreignkey = NULL WHERE primarykey = keyA
         * When keyB is given however, the query goes something like this:
         * UPDATE modelA SET foreignkey = NULL WHERE foreignkey = keyB
         */
        $query = 'UPDATE `' . $modelA->getName() . '` SET ';
        $columnsToValues = array();
        foreach ($reference['columns'] as $column) {
            $columnsToValues[] = '`' . $column . '` = NULL';
        }
        $columnsToValues = implode(' AND ', $columnsToValues);
        $query .= $columnsToValues;
        $whereColumnsToValues = array();
        if ($options['keyA']) {
            $useColumns = 'refColumns';
            $useKeys = 'keyA';
        } else {
            $useColumns = 'columns';
            $useKeys = 'keyB';
        }
        foreach ($reference[$useColumns] as $i => $column) {
            $whereColumnsToValues[] = '`' . $column . '` = ' . $options[$useKeys][$i];
        }
        $whereColumnsToValues = implode(' AND ', $whereColumnsToValues);
        $query .= ' WHERE ';
        $query .= $whereColumnsToValues;

        return $modelA->getAdapter()->query($query);
    }