[Zope] Reversing acquisition?

Stephen Harrison stephen@nipltd.com
Thu, 20 Jul 2000 10:36:53 +0100


Luciano Ramalho wrote:
> 
> zoper@creative.isquare-asia.com wrote:
> > The effect I would like to achieve is:
> > when user access http://myserver/,
> > content of /text_object_1 and /text_object_2 will be shown
> > while user access http://myserver/subfolder/,
> > content of /subfolder/text_object_1 and /subfolder/text_object_2
> >
> > The point is that there's no index_html in /subfolder
> > so /index_html will be acquested and by default it displays
> > content of /text_object_1 and /text_object_2
> >
> > The question is: we got text_object_1 and text_object_2 in /subfolder
> > how could I let the acquested index_html in subfolder to use the
> > objects inside the subfolder?
> 
> What you want is what Zope already does!
> 
> That is how acquisition works: if /subfolder has no index_html, it will
> acquire that object from the root. But the DTML inside index_html will
> be rendered in the context (namespace) of the subfolder, so the desired
> effect will be achieved.

Unfortunately it is not quite as simple as that.  Infact, to say that
that is how acquisition works is misleading.  It is not how acquisition
works, but if you are using DTML Methods then you can create the effect
of that being the way it works.

Let me explain.  When you acquire an object, the acquisition method used
is to first look at the containment of the object before the context of
the object.  So if you have the scenario described above, when you call
/subfolder/ it fist looks for index_html inside subfolder, but it isn't
there, so it looks in subfolders containing object, /, where it does
find index_html.  Now it executes index_html and finds a call to
text_object_1.  So it first looks inside index_html for text_object_1,
but it can't find it, so it looks in the _containing_ object of
index_html, /, and finds text_object_1.

However, if index_html is a DTML Method then things are different,
because a DTML Method does not have it's own namespace and isn't an
object in it's own right - rather it is a method of the calling object.

The problem with this *containment before context* is that in most cases
it goes against what is trying to be achieved.  In the example above,
there may be very good reasons why index_html needs to be a document
rather than a method - maybe it needs it's own properties, etc.  The
point is that most often, the important thing when calling an object is
the *context* in which it is called, not the location in the object
store where it happens to be located.

As I have mentioned several times now on the list, I can't see any good
reason why acquisition should use the containment before context method
(refered to as Simplified Acquisition) and in my opinion it should be
changed to use context before containment (refered to as Natural
Acquisition).

See http://www.zope.org/Wikis/zope-dev/AcquisitionUsage for some
explanation of the different types of acquisiton, and
http://www.zope.org/Wikis/zope-dev/AcquisitionFeedback for a summary of
the problem as I see it - if you have opinions then do add them.

Also, Patrick Lewis wrote:
> 
> Try changing /index_html as follows:
> 
> <dtml-var standard_html_header>
> <table>
> <tr><td><dtml-var "PARENTS[0].text_object_1" fmt=structured-text>
>     </td></tr>
> <tr><td><dtml-var "PARENTS[0].text_object_2" fmt=structured-text>
>     </td></tr>
> </table>
> <dtml-var standard_html_footer>
> 
> Basically force Zope to look in the current folder first.

That is all well and good for solving this particular problem, but it
crosses a threshold in terms of accessability to the person writing the
code.  For a 'non-programmer', writing <dtml-var object> is not too
difficult or scary, but <dtml-var "PARENTS[0].object"> is a world apart
and quite a scary place to be.  It's complicated, it doesn't make a lot
of sense and it makes doing what should be quite simple things
inaccessible.

I work with a variety of people here, some of whom have no problem at
all with any of the above, but others for whom there is a definite
barrier between the first and second snippets of code.  It's like the
old "function(_, _.None) thing, which just shouldn't be necessary, but
that's a different story.

Anyway, in this particular case, if acquisition worked in a more useful
way (see above) then this problem would be avoided.

Cheers,
Stephen

-- 
Stephen Harrison            stephen@nipltd.com
New Information Paradigms   www.nipltd.com