From a86d16a347b434bc61416a3c66ee10e4e57bd480 Mon Sep 17 00:00:00 2001
From: Alexandre Butynski <alexandre.butynski@neoxia.com>
Date: Sat, 8 Mar 2014 17:50:41 +0100
Subject: [PATCH] Add method dissociate to EmbedsMany and refactor destroy

---
 .../Mongodb/Relations/EmbedsMany.php          | 53 ++++++++++++++-----
 tests/RelationsTest.php                       | 20 ++++++-
 2 files changed, 57 insertions(+), 16 deletions(-)

diff --git a/src/Jenssegers/Mongodb/Relations/EmbedsMany.php b/src/Jenssegers/Mongodb/Relations/EmbedsMany.php
index 67d7eaa..0729ad9 100644
--- a/src/Jenssegers/Mongodb/Relations/EmbedsMany.php
+++ b/src/Jenssegers/Mongodb/Relations/EmbedsMany.php
@@ -273,22 +273,12 @@ class EmbedsMany extends Relation {
     /**
      * Destroy the embedded models for the given IDs.
      *
-     * @param  array|int  $ids
+     * @param  mixed  $ids
      * @return int
      */
     public function destroy($ids = array())
     {
-        // We'll initialize a count here so we will return the total number of deletes
-        // for the operation. The developers can then check this number as a boolean
-        // type value or get this total count of records deleted for logging, etc.
-        $count = 0;
-
-        if ($ids instanceof Model) $ids = (array) $ids->getKey();
-
-        // If associated IDs were passed to the method we will only delete those
-        // associations, otherwise all of the association ties will be broken.
-        // We'll return the numbers of affected rows when we do the deletes.
-        $ids = (array) $ids;
+        $ids = $this->getIdsArrayFrom($ids);
 
         $primaryKey = $this->related->getKeyName();
 
@@ -296,9 +286,23 @@ class EmbedsMany extends Relation {
         foreach ($ids as $id)
         {
             $this->query->pull($this->localKey, array($primaryKey => $this->getForeignKeyValue($id)));
-            $count++;
         }
 
+        return $this->dissociate($ids);
+    }
+
+    /**
+     * Dissociate the embedded models for the given IDs without persistence.
+     *
+     * @param  mixed  $ids
+     * @return int
+     */
+    public function dissociate($ids = array())
+    {
+        $ids = $this->getIdsArrayFrom($ids);
+
+        $primaryKey = $this->related->getKeyName();
+
         // Get existing embedded documents.
         $documents = $this->getEmbeddedRecords();
 
@@ -313,7 +317,28 @@ class EmbedsMany extends Relation {
 
         $this->setEmbeddedRecords($documents);
 
-        return $count;
+        // We return the total number of deletes for the operation. The developers
+        // can then check this number as a boolean type value or get this total count
+        // of records deleted for logging, etc.
+        return count($ids);
+    }
+
+    /**
+     * Transform single ID, single Model or array of Models into an array of IDs
+     *
+     * @param  mixed  $ids
+     * @return int
+     */
+    protected function getIdsArrayFrom($ids)
+    {
+        if (! is_array($ids)) $ids = array($ids);
+
+        foreach ($ids as &$id)
+        {
+            if ($id instanceof Model) $id = $id->getKey();
+        }
+
+        return $ids;
     }
 
     /**
diff --git a/tests/RelationsTest.php b/tests/RelationsTest.php
index 32ac426..8850bc7 100644
--- a/tests/RelationsTest.php
+++ b/tests/RelationsTest.php
@@ -383,8 +383,8 @@ class RelationsTest extends PHPUnit_Framework_TestCase {
         $user->addresses()->create(array('city' => 'Paris'));
         $user->addresses()->create(array('city' => 'San Francisco'));
 
-        $user = User::find($user->id);
-        $this->assertEquals(array('Bruxelles', 'Paris', 'San Francisco'), $user->addresses->lists('city'));
+        $freshUser = User::find($user->id);
+        $this->assertEquals(array('Bruxelles', 'Paris', 'San Francisco'), $freshUser->addresses->lists('city'));
 
         $ids = $user->addresses->lists('_id');
         $user->addresses()->destroy($ids);
@@ -392,6 +392,22 @@ class RelationsTest extends PHPUnit_Framework_TestCase {
 
         $freshUser = User::find($user->id);
         $this->assertEquals(array(), $freshUser->addresses->lists('city'));
+
+        list($london, $bristol, $bruxelles) = $user->addresses()->saveMany(array(new Address(array('city' => 'London')), new Address(array('city' => 'Bristol')), new Address(array('city' => 'Bruxelles'))));
+        $user->addresses()->destroy(array($london, $bruxelles));
+        $this->assertEquals(array('Bristol'), $user->addresses->lists('city'));
+    }
+
+    public function testEmbedsManyDissociate()
+    {
+        $user = User::create(array());
+        $cordoba = $user->addresses()->create(array('city' => 'Cordoba'));
+
+        $user->addresses()->dissociate($cordoba->id);
+
+        $freshUser = User::find($user->id);
+        $this->assertEquals(0, $user->addresses->count());
+        $this->assertEquals(1, $freshUser->addresses->count());
     }
 
     public function testEmbedsManyAliases()
-- 
2.18.1