Refactoring methods, adding self join association detection.

Test cases updated.
This commit is contained in:
mark_story 2009-05-09 23:32:22 -04:00
parent 4b4875e0a9
commit 5c48603bd0
2 changed files with 124 additions and 53 deletions

View file

@ -78,6 +78,15 @@ class ModelTask extends Shell {
**/
var $__validations = array();
/**
* startup method
*
* @return void
**/
function startup() {
App::import('Core', 'Model');
}
/**
* Execution method always used for tasks
*
@ -127,13 +136,8 @@ class ModelTask extends Shell {
* @param string $className Name of class you want model to be.
* @return object Model instance
**/
function _getModelObject($className) {
if (App::import('Model', $className)) {
$object = new $className();
} else {
App::import('Model');
$object = new Model(array('name' => $className, 'ds' => $this->connection));
}
function &_getModelObject($className) {
$object = new Model(array('name' => $className, 'ds' => $this->connection));
return $object;
}
/**
@ -159,7 +163,6 @@ class ModelTask extends Shell {
$fullTableName = $db->fullTableName($useTable);
if (in_array($useTable, $this->__tables)) {
App::import('Model');
$tempModel = new Model(array('name' => $currentModelName, 'table' => $useTable, 'ds' => $this->connection));
$fields = $tempModel->schema();
if (!array_key_exists('id', $fields)) {
@ -387,7 +390,6 @@ class ModelTask extends Shell {
if (!is_object($model)) {
return false;
}
App::import('Model');
$this->out(__('One moment while the associations are detected.', true));
$fields = $model->schema();
@ -415,38 +417,7 @@ class ModelTask extends Shell {
} else {
$this->out(__('Please confirm the following associations:', true));
$this->hr();
foreach ($associations as $type => $settings) {
if (!empty($associations[$type])) {
$count = count($associations[$type]);
$response = 'y';
for ($i = 0; $i < $count; $i++) {
$prompt = "{$model->name} {$type} {$associations[$type][$i]['alias']}";
$response = $this->in("{$prompt}?", array('y','n'), 'y');
if ('n' == low($response) || 'no' == low($response)) {
unset($associations[$type][$i]);
} else {
if ($model->name === $associations[$type][$i]['alias']) {
if ($type === 'belongsTo') {
$alias = 'Parent' . $associations[$type][$i]['alias'];
}
if ($type === 'hasOne' || $type === 'hasMany') {
$alias = 'Child' . $associations[$type][$i]['alias'];
}
$alternateAlias = $this->in(sprintf(__('This is a self join. Use %s as the alias', true), $alias), array('y', 'n'), 'y');
if ('n' == low($alternateAlias) || 'no' == low($alternateAlias)) {
$associations[$type][$i]['alias'] = $this->in(__('Specify an alternate alias.', true));
} else {
$associations[$type][$i]['alias'] = $alias;
}
}
}
}
$associations[$type] = array_merge($associations[$type]);
}
}
$associations = $this->confirmAssociations($model, $associations);
}
$wannaDoMoreAssoc = $this->in(__('Would you like to define some additional model associations?', true), array('y','n'), 'n');
@ -534,13 +505,19 @@ class ModelTask extends Shell {
$fields = $model->schema();
foreach ($fields as $fieldName => $field) {
$offset = strpos($fieldName, '_id');
if ($fieldName != $model->primaryKey && $offset !== false) {
if ($fieldName != $model->primaryKey && $fieldName != 'parent_id' && $offset !== false) {
$tmpModelName = $this->_modelNameFromKey($fieldName);
$associations['belongsTo'][] = array(
'alias' => $tmpModelName,
'className' => $tmpModelName,
'foreignKey' => $fieldName,
);
} elseif ($fieldName == 'parent_id') {
$associations['belongsTo'][] = array(
'alias' => 'Parent' . $model->name,
'className' => $model->name,
'foreignKey' => $fieldName,
);
}
}
return $associations;
@ -561,16 +538,29 @@ class ModelTask extends Shell {
$pattern = '/_' . preg_quote($model->table, '/') . '|' . preg_quote($model->table, '/') . '_/';
$possibleJoinTable = preg_match($pattern , $otherTable);
if ($possibleJoinTable == true) {
continue;
}
foreach ($modelFieldsTemp as $fieldName => $field) {
if ($fieldName != $model->primaryKey && $fieldName == $foreignKey && $possibleJoinTable == false) {
$assoc = false;
if ($fieldName != $model->primaryKey && $fieldName == $foreignKey) {
$assoc = array(
'alias' => $tempOtherModel->name,
'className' => $tempOtherModel->name,
'foreignKey' => $fieldName
);
} elseif ($otherTable == $model->table && $fieldName == 'parent_id') {
$assoc = array(
'alias' => 'Child' . $model->name,
'className' => $model->name,
'foreignKey' => $fieldName
);
}
if ($assoc) {
$associations['hasOne'][] = $assoc;
$associations['hasMany'][] = $assoc;
}
}
}
return $associations;
@ -615,6 +605,33 @@ class ModelTask extends Shell {
}
return $associations;
}
/**
* Interact with the user and confirm associations.
*
* @param array $model Temporary Model instance.
* @param array $associations Array of associations to be confirmed.
* @return array Array of confirmed associations
**/
function confirmAssociations(&$model, $associations) {
foreach ($associations as $type => $settings) {
if (!empty($associations[$type])) {
$count = count($associations[$type]);
$response = 'y';
for ($i = 0; $i < $count; $i++) {
$prompt = "{$model->name} {$type} {$associations[$type][$i]['alias']}";
$response = $this->in("{$prompt}?", array('y','n'), 'y');
if ('n' == low($response)) {
unset($associations[$type][$i]);
} elseif ($type == 'hasMany') {
unset($associations['hasOne'][$i]);
}
}
$associations[$type] = array_merge($associations[$type]);
}
}
return $associations;
}
/**
* Assembles and writes a Model file.

View file

@ -39,6 +39,7 @@ if (!class_exists('ShellDispatcher')) {
if (!class_exists('ModelTask')) {
require CAKE . 'console' . DS . 'libs' . DS . 'tasks' . DS . 'model.php';
require CAKE . 'console' . DS . 'libs' . DS . 'tasks' . DS . 'fixture.php';
}
Mock::generatePartial(
@ -54,6 +55,10 @@ Mock::generatePartial(
Mock::generate(
'Model', 'MockModelTaskModel'
);
Mock::generate(
'FixtureTask', 'MockModelTaskFixtureTask'
);
/**
* ModelTaskTest class
*
@ -66,7 +71,7 @@ class ModelTaskTest extends CakeTestCase {
*
* @var array
**/
var $fixtures = array('core.article', 'core.comment', 'core.articles_tag', 'core.tag');
var $fixtures = array('core.article', 'core.comment', 'core.articles_tag', 'core.tag', 'core.category_thread');
/**
* setUp method
@ -99,20 +104,22 @@ class ModelTaskTest extends CakeTestCase {
function testListAll() {
$this->Task->expectAt(1, 'out', array('1. Article'));
$this->Task->expectAt(2, 'out', array('2. ArticlesTag'));
$this->Task->expectAt(3, 'out', array('3. Comment'));
$this->Task->expectAt(4, 'out', array('4. Tag'));
$this->Task->expectAt(3, 'out', array('3. CategoryThread'));
$this->Task->expectAt(4, 'out', array('4. Comment'));
$this->Task->expectAt(5, 'out', array('5. Tag'));
$result = $this->Task->listAll('test_suite');
$expected = array('articles', 'articles_tags', 'comments', 'tags');
$expected = array('articles', 'articles_tags', 'category_threads', 'comments', 'tags');
$this->assertEqual($result, $expected);
$this->Task->expectAt(6, 'out', array('1. Article'));
$this->Task->expectAt(7, 'out', array('2. ArticlesTag'));
$this->Task->expectAt(8, 'out', array('3. Comment'));
$this->Task->expectAt(9, 'out', array('4. Tag'));
$this->Task->expectAt(7, 'out', array('1. Article'));
$this->Task->expectAt(8, 'out', array('2. ArticlesTag'));
$this->Task->expectAt(9, 'out', array('3. CategoryThread'));
$this->Task->expectAt(10, 'out', array('4. Comment'));
$this->Task->expectAt(11, 'out', array('5. Tag'));
$this->Task->connection = 'test_suite';
$result = $this->Task->listAll();
$expected = array('articles', 'articles_tags', 'comments', 'tags');
$expected = array('articles', 'articles_tags', 'category_threads', 'comments', 'tags');
$this->assertEqual($result, $expected);
}
@ -133,7 +140,7 @@ class ModelTaskTest extends CakeTestCase {
$expected = 'Article';
$this->assertEqual($result, $expected);
$this->Task->setReturnValueAt(2, 'in', 3);
$this->Task->setReturnValueAt(2, 'in', 4);
$result = $this->Task->getName('test_suite');
$expected = 'Comment';
$this->assertEqual($result, $expected);
@ -319,6 +326,20 @@ class ModelTaskTest extends CakeTestCase {
)
);
$this->assertEqual($result, $expected);
$model = new Model(array('ds' => 'test_suite', 'name' => 'CategoryThread'));
$result = $this->Task->findBelongsTo($model, array());
$expected = array(
'belongsTo' => array(
array(
'alias' => 'ParentCategoryThread',
'className' => 'CategoryThread',
'foreignKey' => 'parent_id',
),
)
);
$this->assertEqual($result, $expected);
}
/**
@ -348,6 +369,27 @@ class ModelTaskTest extends CakeTestCase {
),
);
$this->assertEqual($result, $expected);
$model = new Model(array('ds' => 'test_suite', 'name' => 'CategoryThread'));
$result = $this->Task->findHasOneAndMany($model, array());
$expected = array(
'hasOne' => array(
array(
'alias' => 'ChildCategoryThread',
'className' => 'CategoryThread',
'foreignKey' => 'parent_id',
),
),
'hasMany' => array(
array(
'alias' => 'ChildCategoryThread',
'className' => 'CategoryThread',
'foreignKey' => 'parent_id',
),
)
);
$this->assertEqual($result, $expected);
}
/**
@ -373,5 +415,17 @@ class ModelTaskTest extends CakeTestCase {
);
$this->assertEqual($result, $expected);
}
/**
* Ensure that the fixutre object is correctly called.
*
* @return void
**/
function testFixture() {
$this->Task->Fixture =& new MockModelTaskFixtureTask();
$this->Task->Fixture->expectAt(0, 'bake', array('Article', 'articles'));
$this->Task->fixture('Article', 'articles');
}
}
?>