Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Text::Template and YAML

by rje (Deacon)
on Jun 21, 2005 at 17:18 UTC ( [id://468759]=CUFP: print w/replies, xml ) Need Help??

So I was browsing the Advanced Perl book, which has this nifty chapter on templating. I read over the text, and it looks like this guy had to (1) build a little template script language to populate his template data, and (2) hand-roll a parser for a toy version of an object model representation.

The first thing I thought was "that sounds like an awful lot of work to me".

I checked the book's copyright. 1997. Well, no wonder. This article was from the stone ages.

Anyhow, I browsed CPAN and came across plover's Text::Template module. It is so usefully clever to use Perl as the template script -- after a little reflection, it struck me as absurd to make up a new script language for template population... well, maybe not absurd, but there'd have to be a really, really good reason for someone to do that, anyway. OK, back end processing done.

Then I grabbed Ingy's YAML module, and had the front end, leaving me with the straightforward task of creating templates and populating the variables used by them.

Voila. In the time it took to research two modules, I cut my development time to nearly Zero, while that fellow in the AP book blathers on about hand-rolling 'toy parsers' and adding references to byacc. Granted, the book is copyright 1997, but still, I wonder if there's something I've missed. Am I on the right track?

plover, Thank you so much for Text::Template!

Here's the example code I drew up to use YAML and Text::Template -- it's only a proof of concept: a script that generates Perl classes. I know, there are better ways to build Perl classes.




spec.yaml
This is the YAML file that contains 'object descriptions'. It's more complete than necessary for this example, because I'm thinking of adding a SQL template for it, and expanding the Perl template I've already written to include database interaction. This is all pretty new to me: I'm using this as a learning exercise.

--- Objects: - Employee: fields: emp_id: int name: string[40] dept_id: Department salary: double key: emp_id - Department: fields: dept_id: int name: string[20] key: dept_id Relationships: - - Owner: name: Department count: 1 - Contains: name: Employee count: many



template.tmpl:
Here's the template that generates inside-out Perl classes. As you can see, it's extremely primitive, and I know there are Perl modules that make class-writing trivial, but again, this is a template-learning exercise for me.

{ @attrlist = keys %attrs; '' } package {$package}; use strict; \{ { ' my %' . join( ";\n my \%", @attrlist ) . ';'; } sub new \{ bless \{\}, shift \} {foreach my $attr ( @attrlist ) { my $v = '{ $' . $attr . '{+shift} }'; $OUT .= sprintf( " sub %-10s :lvalue " . $v . "\n", $attr ); } } sub DESTROY \{ my $sref = 0+shift; delete { join( "\n ,", map { '$' . $_ . '{$sref}' } +@attrlist); }; \} \} 1;



filler.pl:
And here's the script that ties it all together -- essentially, its job is to make sure the right data is loaded into the right Perl variables at the right time.

use YAML; use Text::Template; use strict; my $data = YAML::LoadFile( 'spec.yaml' ); my $text = new Text::Template ( TYPE => 'FILE', SOURCE => 'template.tmpl' ); my @objects = @{$data->{Objects}}; my @relationships = @{$data->{Relationships}}; foreach my $obj (@objects) { our ($package, $value) = %$obj; our %attrs = %{$value->{fields}}; my $out = $text->fill_in(); print $out; }



And here's the output from my examples:

package Employee; use strict; { my %dept_id; my %emp_id; my %name; my %salary; sub new { bless {}, shift } sub dept_id :lvalue { $dept_id{+shift} } sub emp_id :lvalue { $emp_id{+shift} } sub name :lvalue { $name{+shift} } sub salary :lvalue { $salary{+shift} } sub DESTROY { my $sref = 0+shift; delete $dept_id{$sref} ,$emp_id{$sref} ,$name{$sref} ,$salary{$sref}; } } 1; package Department; use strict; { my %dept_id; my %name; sub new { bless {}, shift } sub dept_id :lvalue { $dept_id{+shift} } sub name :lvalue { $name{+shift} } sub DESTROY { my $sref = 0+shift; delete $dept_id{$sref} ,$name{$sref}; } } 1;

Replies are listed 'Best First'.
Re: Text::Template and YAML
by perrin (Chancellor) on Jun 21, 2005 at 19:50 UTC
    In the context of the book, doing this the long way is pretty interesting reading. Many people have made their own versions with template tools though, and you can find some of them here and on CPAN. For one example, see this article on perl.com.
      Using templates is a good idea, but for marking up a Perl code template, I'd choose a syntax other than Text::Template's interpolation style, which requires a lot of back-slashing of braces and variable sigils. I think the templates would be easier to read if in the HTML::Mason or EmbPerl syntaxes, both of which are equally easy to fill in.

        It is possible (and even encouraged by the documentation) to change the delimiters that Text::Template looks for so that you don't have to backslash the braces. For instance:

        Text::Template->new(DELIMITERS => ['<<:', ':>>']);

        Good Day,
            Dean

Re: Text::Template and YAML
by wazoox (Prior) on Jun 22, 2005 at 08:35 UTC
    This is... Wow. It's astounding. I'm speechless. OK, now I need to do the same thing with standard objects :)
      I'm glad someone else out there thinks so. Sometimes I feel like I've been living under a rock.
        We need to receive some light from those who live far, far over our heads, poor worms we are, and someday we"ll grow wings too :)

        update : my off-topic rant : Everytime I post a silly useless joke (like this one), I get downvoted. I find it extremely surprising; after all, it's no use, perhaps stupid, perhaps not really funny, but it's completely harmless. So what the heck?
        (Yes, I'll probably get tons of downvotes for this rant, but never mind, la bave du crapaud n'atteint pas la blanche colombe). If for some reason you feel insulted by this joke, PLEASE do explain to me (even /msg me if you feel it this way), there's probably a huge cultural gap or something I don't get.

Re: Text::Template and YAML
by itub (Priest) on Jul 23, 2005 at 14:23 UTC
    Speaking of the Advanced Perl Programming book, a new edition just came out. It's a complete rewrite, and, as you would expect, advocates using existing CPAN modules for templating and other common tasks. In fact, most of the view can be seen as a survey of the CPAN. ;-)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: CUFP [id://468759]
Approved by Limbic~Region
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (7)
As of 2024-04-23 09:12 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found