Permalink
Browse files

Updating CRUD integration test, and fixing CRUD operations for CouchD…

…B. Refactoring casting in MongoDB adapter. Adding notes on related objects in `\data\Model`.
  • Loading branch information...
1 parent eaa5770 commit 39e131a829d523887bf5a22a2e35708ea2bcd5ed @nateabele nateabele committed Jan 9, 2011
@@ -37,6 +37,8 @@ class Entity extends \lithium\core\Object {
/**
* Associative array of the entity's fields and values.
+ *
+ * @var array
*/
protected $_data = array();
@@ -163,6 +165,9 @@ public function &__get($name) {
}
}
}
+ if (isset($this->_updated[$name])) {
+ return $this->_updated[$name];
+ }
if (isset($this->_data[$name])) {
return $this->_data[$name];
}
@@ -48,14 +48,16 @@
* Post::count(array('published' => true));
* }}}
*
- * The actual objects returned from `find()` calls will depend on the type of datasource in use.
- * MongoDB, for example, will return results as a `Document`, while MySQL will return results
- * as a `RecordSet`. Both of these classes extend a common `data\Collection` class, and provide
- * the necessary abstraction to make working with either type completely transparent.
+ * The actual objects returned from `find()` calls will depend on the type of data source in use.
+ * MongoDB, for example, will return results as a `Document` (as will CouchDB), while MySQL will
+ * return results as a `RecordSet`. Both of these classes extend a common `lithium\data\Collection`
+ * class, and provide the necessary abstraction to make working with either type completely
+ * transparent.
*
* For data mutation (saving/updating/deleting), the `Model` class acts as a broker to the proper
- * objects. When creating a new record, for example, a call to `Post::create()` will return a
- * `data\model\Record` object, which can then be acted upon.
+ * objects. When creating a new record or document, for example, a call to `Post::create()` will
+ * return an instance of `lithium\data\entity\Record` or `lithium\data\entity\Document`, which can
+ * then be acted upon.
*
* Example:
* {{{
@@ -41,6 +41,9 @@ public function &__get($name) {
}
}
}
+ if (isset($this->_updated[$name])) {
+ return $this->_updated[$name];
+ }
if (isset($this->_data[$name])) {
return $this->_data[$name];
}
@@ -766,7 +766,7 @@ public function order($order, $context) {
}
public function cast($entity, array $data, array $options = array()) {
- $defaults = array('schema' => null, 'first' => false, 'pathKey' => null, 'arrays' => true);
+ $defaults = array('schema' => null, 'first' => false, 'pathKey' => null);
$options += $defaults;
$model = null;
@@ -786,49 +786,10 @@ public function cast($entity, array $data, array $options = array()) {
}
$schema = $options['schema'] ?: array('_id' => array('type' => 'id'));
unset($options['schema']);
+ $exporter = $this->_classes['exporter'];
+ $options += compact('model') + array('handlers' => $this->_handlers);
- $typeMap = array(
- 'MongoId' => 'id',
- 'MongoDate' => 'date',
- 'MongoCode' => 'code',
- 'MongoBinData' => 'binary',
- 'datetime' => 'date',
- 'timestamp' => 'date',
- 'int' => 'integer',
- );
-
- foreach ($data as $key => $value) {
- if (is_object($value)) {
- continue;
- }
- $path = $options['pathKey'] ? "{$options['pathKey']}.{$key}" : $key;
- $field = (isset($schema[$path]) ? $schema[$path] : array());
- $field += array('type' => null, 'array' => null);
- $type = isset($typeMap[$field['type']]) ? $typeMap[$field['type']] : $field['type'];
- $isObject = ($type == 'object');
- $isArray = (is_array($value) && $field['array'] !== false && !$isObject);
-
- if (isset($this->_handlers[$type])) {
- $handler = $this->_handlers[$type];
- $value = $isArray ? array_map($handler, $value) : $handler($value);
- }
- if (!$options['arrays']) {
- $data[$key] = $value;
- continue;
- }
- $pathKey = $path;
-
- if (is_array($value)) {
- $arrayType = !$isObject && (array_keys($value) === range(0, count($value) - 1));
- $opts = $arrayType ? array('class' => 'array') + $options : $options;
- $value = $this->item($model, $value, compact('pathKey') + $opts);
- } elseif ($field['array']) {
- $opts = array('class' => 'array') + $options;
- $value = $this->item($model, array($value), compact('pathKey') + $opts);
- }
- $data[$key] = $value;
- }
- return $options['first'] ? reset($data) : $data;
+ return parent::cast($entity, $exporter::cast($data, $schema, $this, $options), $options);
}
protected function _checkConnection() {
@@ -12,6 +12,16 @@
class Exporter extends \lithium\core\StaticObject {
+ protected static $_map = array(
+ 'MongoId' => 'id',
+ 'MongoDate' => 'date',
+ 'MongoCode' => 'code',
+ 'MongoBinData' => 'binary',
+ 'datetime' => 'date',
+ 'timestamp' => 'date',
+ 'int' => 'integer',
+ );
+
public static function get($type, $export, array $options = array()) {
$defaults = array('whitelist' => array());
$options += $defaults;
@@ -22,6 +32,49 @@ public static function get($type, $export, array $options = array()) {
return static::$method($export, array('finalize' => true) + $options);
}
+ public static function cast($data, $schema, $database, array $options = array()) {
+ $defaults = array(
+ 'pathKey' => null, 'handlers' => array(), 'model' => null, 'arrays' => true
+ );
+ $options += $defaults;
+ $typeMap = static::$_map;
+
+ foreach ($data as $key => $value) {
+ if (is_object($value)) {
+ continue;
+ }
+ $path = $options['pathKey'] ? "{$options['pathKey']}.{$key}" : $key;
+ $field = (isset($schema[$path]) ? $schema[$path] : array());
+ $field += array('type' => null, 'array' => null);
+ $type = isset($typeMap[$field['type']]) ? $typeMap[$field['type']] : $field['type'];
+ $isObject = ($type == 'object');
+ $isArray = (is_array($value) && $field['array'] !== false && !$isObject);
+
+ if (isset($options['handlers'][$type]) && $handler = $options['handlers'][$type]) {
+ $value = $isArray ? array_map($handler, $value) : $handler($value);
+ }
+ if (!$options['arrays']) {
+ $data[$key] = $value;
+ continue;
+ }
+ $pathKey = $path;
+
+ if (!is_array($value) && !$field['array']) {
+ $data[$key] = $value;
+ continue;
+ }
+ if (is_array($value)) {
+ $arrayType = !$isObject && (array_keys($value) === range(0, count($value) - 1));
+ $opts = $arrayType ? array('class' => 'array') + $options : $options;
+ } elseif ($field['array']) {
+ $opts = array('class' => 'array') + $options;
+ $value = array($value);
+ }
+ $data[$key] = $database->item($options['model'], $value, compact('pathKey') + $opts);
+ }
+ return $data;
+ }
+
public static function toCommand($changes) {
$map = array(
'create' => null,
@@ -244,6 +244,7 @@ public function testSimpleFindList() {
public function testFilteredFind() {
MockComment::applyFilter('find', function($self, $params, $chain) {
$result = $chain->next($self, $params, $chain);
+
if ($result != null) {
$result->filtered = true;
}
@@ -10,7 +10,7 @@
use Exception;
use lithium\data\Connections;
-use lithium\tests\mocks\data\Company;
+use lithium\tests\mocks\data\Companies;
class CrudTest extends \lithium\test\Integration {
@@ -24,9 +24,9 @@ class CrudTest extends \lithium\test\Integration {
);
public function setUp() {
+ Companies::config();
+ $this->_key = Companies::key();
$this->_connection = Connections::get('test');
- Company::config();
- $this->_key = Company::meta('key');
}
/**
@@ -49,42 +49,77 @@ public function skip() {
* @return void
*/
public function testCreate() {
- $new = Company::create(array($this->_key => 12345, 'name' => 'Acme, Inc.'));
+ Companies::all()->delete();
+ $this->assertIdentical(0, Companies::count());
- $result = $new->data();
- $expected = array($this->_key => 12345, 'name' => 'Acme, Inc.');
- $this->assertEqual($expected[$this->_key], $result[$this->_key]);
- $this->assertEqual($expected['name'], $result['name']);
+ $new = Companies::create(array('name' => 'Acme, Inc.', 'active' => true));
+ $this->assertEqual($new->data(), array('name' => 'Acme, Inc.', 'active' => true));
- $this->assertFalse($new->exists());
- $this->assertTrue($new->save());
- $this->assertTrue($new->exists());
+ $this->assertEqual(
+ array(false, true, true),
+ array($new->exists(), $new->save(), $new->exists())
+ );
+ $this->assertIdentical(1, Companies::count());
}
public function testRead() {
- $existing = Company::find(12345);
- $expected = array($this->_key => 12345, 'name' => 'Acme, Inc.');
- $result = $existing->data();
- $this->assertEqual($expected[$this->_key], $result[$this->_key]);
- $this->assertEqual($expected['name'], $result['name']);
+ $existing = Companies::first();
+
+ foreach (Companies::key($existing) as $val) {
+ $this->assertTrue($val);
+ }
+ $this->assertEqual('Acme, Inc.', $existing->name);
+ $this->assertTrue($existing->active);
$this->assertTrue($existing->exists());
}
public function testUpdate() {
- $existing = Company::find(12345);
+ $existing = Companies::first();
+ $this->assertEqual($existing->name, 'Acme, Inc.');
$existing->name = 'Big Brother and the Holding Company';
$result = $existing->save();
$this->assertTrue($result);
- $existing = Company::find(12345);
- $result = $existing->data();
- $expected = array($this->_key => 12345, 'name' => 'Big Brother and the Holding Company');
- $this->assertEqual($expected[$this->_key], $result[$this->_key]);
- $this->assertEqual($expected['name'], $result['name']);
+ $existing = Companies::first();
+ foreach (Companies::key($existing) as $val) {
+ $this->assertTrue($val);
+ }
+ $this->assertTrue($existing->active);
+ $this->assertEqual('Big Brother and the Holding Company', $existing->name);
}
public function testDelete() {
- $existing = Company::find(12345);
+ $existing = Companies::first();
+ $this->assertTrue($existing->exists());
$this->assertTrue($existing->delete());
+ $this->assertNull(Companies::first(array('conditions' => Companies::key($existing))));
+ $this->assertIdentical(0, Companies::count());
+ }
+
+ public function testCrudMulti() {
+ $large = Companies::create(array('name' => 'BigBoxMart', 'active' => true));
+ $medium = Companies::create(array('name' => 'Acme, Inc.', 'active' => true));
+ $small = Companies::create(array('name' => 'Ma & Pa\'s', 'active' => true));
+
+ foreach (array('large', 'medium', 'small') as $key) {
+ $this->assertFalse(${$key}->exists());
+ $this->assertTrue(${$key}->save());
+ $this->assertTrue(${$key}->exists());
+ }
+ $this->assertEqual(3, Companies::count());
+
+ $all = Companies::all();
+ $this->assertEqual(3, $all->count());
+
+ $match = 'BigBoxMart';
+ $filter = function($entity) use (&$match) { return $entity->name == $match; };
+
+ foreach (array('BigBoxMart', 'Acme, Inc.', 'Ma & Pa\'s') as $match) {
+ $this->assertTrue($all->first($filter)->exists());
+ }
+ $this->assertEqual(array(true, true, true), array_values($all->delete()));
+ $this->assertEqual(0, Companies::count());
}
-}
+}
+
+?>
@@ -8,7 +8,7 @@
namespace lithium\tests\mocks\data;
-class Company extends \lithium\data\Model {
+class Companies extends \lithium\data\Model {
public $hasMany = array('Employees');
@@ -10,7 +10,7 @@
class Employee extends \lithium\data\Model {
- public $belongsTo = array('Company');
+ public $belongsTo = array('Companies');
protected $_meta = array('connection' => 'test');

0 comments on commit 39e131a

Please sign in to comment.