[Grok-dev] Re: REST branch ready for review

Martijn Faassen faassen at startifact.com
Sun Oct 21 18:17:25 EDT 2007


Jan-Wijbrand Kolman wrote:
> Martijn Faassen wrote:
>> To actually issue REST requests over a URL, you need to define a REST 
>> protocol that uses this layer:
> 
> After reading and trying it is not clear to me what the relationship is 
> between the "layer" and the "protocol" components. Can you elaborate on 
> this?

My apologies taking a while getting back to you. Thank you for your review!

The terminology is perhaps not ideal, but it actually mimics 'layer' and 
'skin'.

In Grok, views can be layers, indicated by grok.layer(). A layer is just 
an interface that derives from a particular layer. Since you can use 
inheritance (including multiple inheritance), you can combine multiple 
layers into a single one this way.

A skin turns a layer into something that is available on a url, giving 
it a name, like ++skin++foo. It might also add other information 
eventually, like a title and a description, that could aid a UI.

For REST, I've retained the concept of layer, but made a base layer for 
REST instead. I've introduce something very skin-like which is a REST 
protocol, and that appears like this in a URL: ++rest++foo.

This way, you could compose a single REST protocols out of multiple 
protocols should you so desire. Might not be very common (it's hard to 
tell), but since all concepts from layers and skins are reused, it 
shouldn't be hard to learn once you know the former. It's also not a lot 
of overhead to just work with a single layer (or even use the default 
REST layer).

> For example, I played around with this code:
> 
>   import grok
> 
>   class TestRest(grok.Application, grok.Container):
>       pass
> 
>   class Index(grok.View):
>       pass # see app_templates/index.pt
> 
>   class FirstLayer(grok.IRESTLayer):
>       pass
> 
>   class SecondLayer2(grok.IRESTLayer):
>       pass
> 
>   class FirstREST(grok.REST):
>       grok.context(TestRest)
> 
>       def GET(self):
>           return 'GET' + repr(self)
> 
>   class SecondREST(grok.REST):
>       grok.context(TestRest)
> 
>       def GET(self):
>           return 'SECOND GET' + repr(self)
> 
>   class FirstProtocol(grok.RESTProtocol):
>       grok.layer(FirstLayer)
>       grok.name('foobar')
> 
> And now if I go to
> 
>   http://localhost:8080/++rest++foobar/mytestrestinstance
> 
> I get:
> 
>   SECOND GET<grok.meta.SecondREST object at ...>
> 
> Why do I get to the "SecondREST" view here?

This is indeed surprising. It's because if you *don't* assign a 
grok.REST class to a particular layer, it'll use the IRESTLayer by 
default. This means that *all* REST skins will share this.

I wonder whether this is really analogous to the behavior of skins and 
layers? Does anyone know off the top of their head what happens if you 
don't put a grok.View subclass into a particular layer? Does it then 
exist in all skins?

We could decide to make the default REST layer be a very particular 
layer instead that never shows up automatically... Alternatively it 
could simply complain if no layer is found. What do people think? (also 
for skins).

> And shouldn't Grok complain about the fact that I have created two 
> layers, but I do not have explicit use a grok.layer() directive in my 
> grok.REST subclasses?

There is nothing going on like automatic context association for layers. 
Should there be? The situation is somewhat different from context, as 
layers are almost always reused across modules. It is possible to use 
the grok.layer() directive on a module-level basis to provide a 
module-level default.

Regards,

Martijn



More information about the Grok-dev mailing list