Test, test, again ...

Of course, tweaking the Person List display is not going to be the end of it. Clients always want more, and now ours wants to edit, add, or delete records. Let's write some tests for these new tasks, as shown in the following.

function testPersonUpdate() { $expect = "wei"; $edited = "Nah"; //get it; $person = TMapper::instance()->queryForObject("Select", 1); //test it $this->assertNotNull($person); $this->assertEqual($expect, $person->FirstName); //change it $person->FirstName = $edited; TMapper::instance()->update("Update", $person); //get it again $person = TMapper::instance()->queryForObject("Select", 1); //test it $this->assertEqual($edited, $person->FirstName); //change it back $person->FirstName = $expect; TMapper::instance()->update("Update", $person); } function testPersonDelete() { //insert it $person = new Person; $person->ID = -1; TMapper::instance()->insert("Insert", $person); //delte it $count = TMapper::instance()->delete("Delete", -1); $this->assertEqual(1, $count); }

Not the best tests ever written, but for now, they will do :)

To make the new tests work, we'll need some new mapping statements. The following sample shows the complete mapper document that we've called personHelper.xml.

insert into PERSON (PER_ID, PER_FIRST_NAME, PER_LAST_NAME, PER_BIRTH_DATE, PER_WEIGHT_KG, PER_HEIGHT_M) values (#ID#, #FirstName#, #LastName#, #BirthDate#, #WeightInKilograms#, #HeightInMeters#) update PERSON set PER_FIRST_NAME = #FirstName#, PER_LAST_NAME = #LastName#, PER_BIRTH_DATE = #BirthDate#, PER_WEIGHT_KG = #WeightInKilograms#, PER_HEIGHT_M = #HeightInMeters# where PER_ID = #ID# delete from PERSON where PER_ID = #value#

Well, waddya know, if run our tests now, we are favored with a green bar!. It all works!

Note: Though, of course, things usually do not work perfectly the first time! We have to fix this and that, and try, try, again. But SimpleTest makes trying again quick and easy. You can changes to the XML mapping documents and rerun the tests! No muss, no fuss.

Turning back to our Prado page, we can revamp the TDataGrid to allow in-place editing and deleting. To add records, we provide a button after the grid that inserts a blank person for client to edit. The page code is shown as: <com:TDataGrid id="personList" DataKeyField="ID" AutoGenerateColumns="False" OnEditCommand="editPerson" OnUpdateCommand="updatePerson" OnCancelCommand="refreshList" OnDeleteCommand="deletePerson"> <com:TBoundColumn DataField="FirstName" HeaderText="First Name" /> <com:TBoundColumn DataField="LastName" HeaderText="Last Name" /> <com:TBoundColumn DataField="HeightInMeters" HeaderText="Height" /> <com:TBoundColumn DataField="WeightInKilograms" HeaderText="Weight" /> <com:TEditCommandColumn HeaderText="Edit" UpdateText="Save" /> <com:TButtonColumn HeaderText="Delete" Text="Delete" CommandName="delete"/> </com:TDataGrid> <com:TButton Text="Add" OnClick="addNewPerson" />

The following sample shows the corresponding methods from page PHP class.

private function sqlmap() { return $this->Application->getModule('SQLMap')->getClient(); } private function loadData() { $this->personList->DataSource = $this->sqlmap()->queryForList('SelectAll'); $this->personList->dataBind(); } public function onLoad($param) { if(!$this->IsPostBack) $this->loadData(); } protected function editPerson($sender,$param) { $this->personList->EditItemIndex=$param->Item->ItemIndex; $this->loadData(); } protected function deletePerson($sender, $param) { $id = $this->getKey($sender, $param); $this->sqlmap()->update("Delete", $id); $this->loadData(); } protected function updatePerson($sender, $param) { $person = new Person(); $person->FirstName = $this->getText($param, 0); $person->LastName = $this->getText($param, 1); $person->HeightInMeters = $this->getText($param, 2); $person->WeightInKilograms = $this->getText($param, 3); $person->ID = $this->getKey($sender, $param); $this->sqlmap()->update("Update", $person); $this->refreshList($sender, $param); } protected function addNewPerson($sender, $param) { $person = new Person; $person->FirstName = "-- New Person --"; $this->sqlmap()->insert("Insert", $person); $this->loadData();; } protected function refreshList($sender, $param) { $this->personList->EditItemIndex=-1; $this->loadData(); } private function getText($param, $index) { $item = $param->Item; return $item->Cells[$index]->Controls[0]->Text; } private function getKey($sender, $param) { return $sender->DataKeys[$param->Item->DataSourceIndex]; }

OK, we are CRUD complete! There's more we could do here. In particular, we should add validation methods to prevent client from entering alphabetic characters where only numbers can live. But, that's a different Prado tutorial, and this is an SQLMap DataMapper tutorial.

class="figure" />
Figure 4: Person List CRUD