[TransWarp] peak.web and forms

Phillip J. Eby pje at telecommunity.com
Tue Aug 5 14:47:09 EDT 2003

At 08:15 PM 8/5/03 +0200, Roché Compaan wrote:
>* Phillip J. Eby <pje at telecommunity.com> [2003-08-05 16:32]:
> > Now that I've explained all that,
>Thank you very much, I really appreciate it. There are a lot classes in
>the web mix at the moment and to get one's head around - an updated web
>example will really help ground the concepts and make more feedback

It's coming.  I'm just trying to get everything finished, first.

> > Of course, I'm not sure that this really saves anything.  It may be that I
> > should just work out how to easily invoke a template from inside a method
> > on an object.
>At the moment they can only be invoked from a TraversalContext, right?

Well, it's more correct to say that a DOMlet needs a traversal context in 
order to run.  renderTo() now takes a context and a state.  (Hm, I should 
update the interface, which I think still says 'data' is a 
traversable.  Now it's a context.)

>And a WebTraversable has access to the traversal context so one should
>be able to instruct a template to render itself from there as well?

No, traversables don't have access to a context, they always take it as a 
parameter.  This is important for traversables to be reusable in different 
contexts.  Consider a traversable that wraps a "Contact" object...  it 
can't/shouldn't know if the Contact was accessed by traversing from an 
"Order", or by direct access from a specialist.

Before last weekend, traversables did know this, and things were too 
complicated and variable.  Now, there are three objects involved in any 

1. The traversal context, which knows how you got to where you are, what 
interaction this is part of, and also holds the next two items...

2. A traversable, which knows how to traverse the..

3. Current domain object being traversed.  If the domain object is 
traversable, then #2 above is the same object as this.

So, the traversal context holds everything you need to do 
anything.  context.contextFor('name') returns the context that results from 
traversing to 'name'.  It does this by asking the traversable (#2 above) to 
traverseTo('name',interaction), and then it wraps a new context around the 
result, using self.subcontext('name',result).

> > One thing that talking about this scenario has brought up,
> > is that there's currently no way to get at the traversal context from
> > inside a method like this, so that makes things harder.
>Inside methods of which other objects should a template be accessible?
>It sounds convenient to have access to the context all over the place
>but on the other hand if one only has access to the traversal context
>from within a web traversable or a decorator won't this enforce a modular
>design? Anyway, it feels like I might be missing the point again,
>or lacking context  ;-)

Well, the problem is equivalent, because it might be that the method we're 
talking about is on the traversable, or it might be on the domain object, 
or the domain object might be traversable.  So that issue isn't really 
important.  :)

> > Otherwise, you
> > could just say something like:
> >
> >         return context.subcontext('addForm', self.addForm).render()
> >
> > or:
> >         return context.contextFor('addForm').render()
>What is the difference between just "context" and
>"contextFor('addForm')" in the line above.

If you're actually asking here about the difference between 
'subcontext(name,ob)' and 'contextFor(name)', it's that 'contextFor(name)' 
does the work of figuring out for you, what 'ob' should be in the call to 
'subcontext()'.  :)

>  I know the interface says
>contextFor returns a new traversal context but why would you want one?

Because contexts want to be immutable.  That way, if I pass a context 
through to a method I call, I don't have to worry about that method 
modifying my context.  It's a bad idea to divorce allocation from usage in 
this fashion.  If I always create a new object when I need new data, then 
the management burden doesn't propagate all over the code.  Think of it as 
making the code that wants something, pay the price for getting it.

Another convenient side effect, is that because contexts chain to one 
another, they get the caching benefit of their use of bindings.  For 
example, a given context will compute its absolute or traversed URL at most 
once, and any child contexts spun off from it will  get the benefit of this 
in how long it takes for them to compute their own URLs.  E.g.:

        Traversal ('/')
      TraversalContext ('/foo')

If I start with the root traversal object, and do 'contextFor("foo")', and 
then take that object and get its 'contextFor("bar")', I will have a 
component tree as shown above.  Asking for a 'contextFor("..")' will go 
back up the tree and reuse the previous traversal context, which also 
contributes to caching effects.

More information about the PEAK mailing list