I cannot get nested views to work, what's wrong

> I am trying to use a nested view. I can't get this example to work.

 // TEST NESTED VIEW !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 //
 // This does not work!!!!
 //
 c4_View vAddress;
 c4_View nestedview;
    c4_ViewProp pPhone ("phone");
 c4_StringProp pFirst ("first");
 c4_StringProp pLast ("last");
 c4_StringProp pType ("type");
 c4_StringProp pNum ("num");
 // add row to address book
 vAddress.Add(pFirst ["Ted"] + pLast["Christiansen"]);
    nestedview.Add(pType ["work"] + pNum ["+44 (1) 123 4567"]);
    nestedview.Add(pType ["home"] + pNum ["+44 (1) 123 6789"]);
 // Store nested view in row 0
    pPhone (vAddress[0]) = nestedview;
    c4_Storage storage ("myfile.dat", true);
    storage.Store("address", vAddress);
    storage.Commit();
 // This causes an error in table.cpp, Line 851:
 // if (Field(col).IsRepeating())

The assertion failure is very bad, of course. What Store does, is try to deduce the structure of a view, then restructure Metakit accordingly, then it stores the data. I've been having trouble with this function before, and intend to get rid of it in the future because there are known cases where it fails, and because it's actually quite inefficient: you create a memory-based data structure in views, and then in fact create a complete copy of it again while storing it in the datafile.

Try this:

> // TEST NESTED VIEW !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

 #include "mk4.h"
 #include "mk4str.h"
 int main()
 {
    // TEST NESTED VIEW !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    c4_Storage storage ("myfile.dat", true);
    const char* format = "address[first:S,last:S,phone[type:S,num:S]]";
    c4_View vAddress = storage.GetAs(format);
    c4_ViewProp pPhone ("phone");
    c4_StringProp pFirst ("first");
    c4_StringProp pLast ("last");
    c4_StringProp pType ("type");
    c4_StringProp pNum ("num");
    // add row to address book
    int n = vAddress.Add(pFirst ["Ted"] + pLast["Christiansen"]);
    // Get nested view in row 0
    c4_View nestedview = pPhone (vAddress[n]);
    nestedview.Add(pType ["work"] + pNum ["+44 (1) 123 4567"]);
    nestedview.Add(pType ["home"] + pNum ["+44 (1) 123 6789"]);
    storage.Commit();
    return 0;
 }

The logic is to not create "unattached" views as much, but to get a view which is attached to the storage right from the start. Changes you make to the view directly affect that storage, without having to copy it in later. In other words: avoid "c4_View name;" statements.

What I also had to do to make this possible, is to describe the structure up front, and have Metakit adjust to it in he beginning. This is slightly more work, but will probably be the only supported mechanism in a future version (again, due to Store's weaknesses).

-- JC


It would be nice to have this example in the distribution, as it goes into this more than the DEMO.CPP does.

I also added this to the example to be able to add a phone number without putting in the name first.

    //  Suppose I want to add a phone number but don't yet know the name to go with it.
    //  I need the row number to get the nestedview. How do I get it?
    c4_IntProp dummyProp ("dummy");
    c4_Row row;
    dummyProp(row) = 0;
    n = vAddress.Add(row);
    nestedview = pPhone (vAddress[n]);
    nestedview.Add(pType ["home"] + pNum ["+44 (1) 987 6789"]);

John Fletcher 16th May 2000 and 23rd May