Continuity and templating

slanning on 2008-03-31T13:12:43

I like the idea of Continuity. I don't, however, want to go back to using CGI.pm (or printing strings directly) to generate HTML. That's probably what Brock has in mind with Continuity::Widget. However, sorry, I also don't want to use a widget system hacked up just for Continuity, and that module seems to only be a placeholder right now anyway.

What I'd really like to do is somehow integrate Continuity with my favorite templating system, HTML::Mason. Are these two too different conceptually, though? Mason is based on requests, while Continuity is trying to get rid of them? Not sure yet how Continuity's Mapper and Adapter objects fit with Mason's Request, Resolver, ApacheHandler, Interpret... Anyone have ideas?


templating

awwaiid on 2008-03-31T14:15:35

Yeah, Continuity::Widget is just a sketch, and separate from Continuity itself on purpose. Even if I get that going the way I like, I definitely don't expect it to be The Way to use Continuity. More like a demonstration of what can be done. Well... and for my own use :)

I unfortunately don't know the full HTML::Mason request cycle and how that all works. One thing you can do, I believe, is to just use Mason as a template engine. You could then use Mason components to organize your views, and outter Continuity structures to organize the control flow.

Another possibility (or maybe along with the above) is to take the Continuity request and turn it into a Mason request, so that the request-oriented features of Mason can be utilized.

One thing that I have no idea how to do (without research at least) would be the other way around -- allow for Continuity based control flow inside a Mason component.

what he said

hdp on 2008-04-01T00:29:14

use Mason's templating parts, not its web framework parts, like you would with Catalyst or Jifty. see the source of Catalyst::View::Mason, and the "using Mason in standalone scripts" part of HTML::Mason::Admin.

Re:what he said

slanning on 2008-04-01T08:00:38

(I'll be damned if I can get the code to format within <code> tags, so this is all Code format.)

I actually tried installing Jifty last night because I realized it might be more what I had in mind (continuations, Mason...), but I aborted the install after about a half hour of exciting CPAN action. (Maybe I should try Catalyst I guess, but it's never really felt right to me..)

Then I ended up doing just what you mentioned, using Mason as a standalone script. It wasn't very elegant, though. Unfortunately I didn't bring my laptop today so I can't copy what I have, but from memory it was something like this (based on the addtwo.pl example in Continuity):

my $server = Continuity->new(port => 65432);
$server->run;  # (or whatever it is)

sub main {
    my $request = shift;

    my $outbuf = '';
    my $interp = HTML::Mason::Interp->new(
        comp_root => '...',
        data_root => '...',
        out_method => \$outbuf,   # something like that
    );

    $interp->exec('/one.html');
    $request->print($outbuf);
    $request->next;
    my $num1 = $request->param('num');

    $outbuf = '';
    $interp->exec('/two.html');
    $request->print($outbuf);
    $request->next;
    my $num2 = $request->param('num');

    $outbuf = '';
    $interp->exec('/sum.html', num1 => $num1, num2 => $num2, sum => $num1 + $num2);
    $request->print($outbuf);
}

And there the components 'comp/num1.html' etc. are like:

Enter first number:
<input type=text name=num><input type=submit>

and

<h2>The sum of <% $num1 %> and <% $num2 %> is <% $sum %>!</h2>
<%args>
$num1 => 0
$num2 => 0
$sum  => 0
</%args>

and 'autohandler' is like:

<html><body><form>
% $m->call_next();
</form></body></html>

So I guess whatever I did would basically wrap around this tedious incantation:

    $interp->exec('/one.html');
    $request->print($outbuf);
    $request->next;

I guess it's not even a matter of subclassing a mapper/adapter of Continuity or whatever, just making an "exec + print" method on the application side.

Re:what he said

awwaiid on 2008-04-01T16:51:21

Yeah. In larger apps I usually end up putting $request into an instance variable so that I don't have to pass it around all the time. You can do the same thing with your Mason interpreter, I imagine your main body might look like:

sub main {
    my $request = shift;
    my $app = App->new(request => $request);
    $app->run;
}

package App.pm;
# ...

sub run {
    my $self = shift;
    $self->display('/one.html');
    my $num1 = $self->param('num');
    $self->display('/two.html');
    my $num2 = $self->param('num');
    $self->display('/sum.html',
        num1 => $num1,
        num2 => $num2,
         sum => $num1 + $num2);
}

Also, instead of explicitly getting and setting num1 num2 etc, maybe you can use $request->params, which returns a list of all name/value pairs (you can treat it like a hash if you like) -- take that and give the whole thing to each template. Or something.