[Zope-dev] AttributeError validate using the Visitor pattern
Itai Tavor
itai@optusnet.com.au
Mon, 19 Feb 2001 11:33:10 +1100
Hi David,
You posted your questions 3 days ago, so maybe you found a solution
by now... but this might still be useful to you.
I just implemented a visitor similar to yours, with a few changes. It
involves the following objects: Order and OrderLineItem. I created a
Folder named 'displayItemVisitor' in Order containing:
Order.displayItemsVisitor.displayItem (Python Script):
<params>item</params>
return item.accept(container, _)
Order.displayItemsVisitor.visitLineItem (DTML Method):
<td>&dtml-qty;</td>
<td class="price"><dtml-var "getRetailAmount(qty,
in_basket_date)" fmt=dollars-and-cents></td>
The 'accept' method of OrderLineItem is:
<params>visitor, _</params>
return visitor.visitLineItem(container, _)
And the whole thing gets used in the DTML method that displays an order, using:
<dtml-in line_items>
<dtml-var "displayItemsVisitor.displayItem(_['sequence-item'], _)">
</dtml-in>
Interesting points:
- I'm passing _ explicitly instead of relying on binding. I vaguely
recall reading something about a problem binding the namespace. It
might be fixed in the latest Python Scripts, I haven't tried the CVS
version yet.
- visitLineItem is called in the context of an OrderLineItem, so no
<dtml-with item> is needed.
- If you wanted the visitor to implement looping over the items
(which is how the GoF do it) you could easily make something like:
Order.displayItemsVisitor.displayItems (DTML Method):
<dtml-in line_items>
<tr>
<dtml-var "_['sequence-item'].accept(container, _)">
</tr>
</dtml-in>
BTW, I never thought of using a visitor for this until you brought it
up, so thanks! What I really like about it is that the same 'accept'
method can be used by multiple visitors, each one implementing a
different view of the object. So I can have displayItemsVisitor,
displayItemsCompactVisitor, and displayItemsEditableVisitor, all
calling item.accept(), and I avoid polluting my OrderLineItem class
with multiple view methods. OTOH, it requires adding public access
methods to OrderLineItem, because a view method in OrderLineItem can
do <dtml-var price>, while the visitor must do <dtml-var
"getPrice()">. Oh well, there's always a price to pay ;-)
HTH, Itai
R. David Murray wrote:
>OK, having helped me figure out how to work around the bug in accessing
>ZPatterns objects from a catalog, I've got a new challenge for you all.
>
>Now that I've got my list of objects, I want to generate a web page displaying
>them. The page has the structure of a series of table rows. Inside each
>row data about a single object is displayed, using a common format but
>with certain differences depending on the type of object. To implement this,
>I am trying to use the Visitor pattern from the Gang of Four book.
>
>So, I have a Folder displayItemList. This folder contains (at the moment)
>three methods: displayTable, visitAuthor, and visitBook. displayTable
>generates the html for the outer table, down to the <tr></tr> tags.
>Between those tags, it calls <dtml-var "accept(me)">, where me is
>this() for the displayTable method, and accept is a pythonscript method
>defined on each of the object type's Specialist. Each accept method
>is of the form:
>
>return visitor.visitBook(None,_,item=context)
>
>with _ bound to namespace on the bindings tab and 'visitor' being listed
>in the arguments line.
>
>visitBook begins with the line:
>
><dtml-with item>
>
>Trying to display my list, I get an AttributeError on 'validate', and
>ZDebug flags the 'with' line as the error location. validate
>appears nowhere in my code, so from all I can figure from a certain
>amount of inspection of the source, Zope is looking for this method
>on the DTMLMethod and not finding it.
>
>ZDebug says the namespace stack consists of a single entry, which looks like
>the DTMLMethod itself (visitBook, presumably). Seems to me the namespace
>stack should be deeper than that.
>
>I've been poking at this for a couple hours now without making any more
>progress, so I'm going to quit for the day and come back to it tomorrow.
>If anybody has any bright ideas, or sees something obvious I'm doing wrong,
>please clue me in. Thanks!
>
>By the way, I also tried making accept be visitor.visitBook(context,_),
>but that produced the same error and ZDebug could only point to the
>call to accept as the error location.
>
>--RDM
--
--
Itai Tavor -- "Je sautille, donc je suis." --
itai@optusnet.com.au -- - Kermit the Frog --
-- --
-- "If you haven't got your health, you haven't got anything" --