[MKDoc-commit] Incremented VERSION and added Cookbook from William
McKee
bruno at mkdoc.demon.co.uk
bruno at mkdoc.demon.co.uk
Fri Jan 21 12:31:47 GMT 2005
Log Message:
-----------
Incremented VERSION and added Cookbook from William McKee
Modified Files:
--------------
Petal:
Changes
MANIFEST
META.yml
Petal/lib:
Petal.pm
Petal/lib/Petal:
Cookbook.pod
Added Files:
-----------
Petal/t:
084_Cookbook.t
Petal/t/data:
cookbook.html
-------------- next part --------------
Index: MANIFEST
===================================================================
RCS file: /var/spool/cvs/Petal/MANIFEST,v
retrieving revision 1.47
retrieving revision 1.48
diff -LMANIFEST -LMANIFEST -u -r1.47 -r1.48
--- MANIFEST
+++ MANIFEST
@@ -88,6 +88,7 @@
t/081_Petal_I18NProcessor.t
t/082_Petal_Gettext.t
t/083_test_attributes_chars.t
+t/084_Cookbook.t
t/benchmark.pl
t/data/access_obj_array.html
t/data/access_obj_hash.html
@@ -101,6 +102,7 @@
t/data/comment_does_not_die.xml
t/data/comments.xml
t/data/content_encoded.html
+t/data/cookbook.html
t/data/decl.xml
t/data/delete_attribute.xml
t/data/dummy_data.xml
Index: META.yml
===================================================================
RCS file: /var/spool/cvs/Petal/META.yml,v
retrieving revision 1.8
retrieving revision 1.9
diff -LMETA.yml -LMETA.yml -u -r1.8 -r1.9
--- META.yml
+++ META.yml
@@ -1,7 +1,7 @@
# http://module-build.sourceforge.net/META-spec.html
#XXXXXXX This is a prototype!!! It will change in the future!!! XXXXX#
name: Petal
-version: 2.15
+version: 2.16
version_from: lib/Petal.pm
installdirs: site
requires:
Index: Changes
===================================================================
RCS file: /var/spool/cvs/Petal/Changes,v
retrieving revision 1.124
retrieving revision 1.125
diff -LChanges -LChanges -u -r1.124 -r1.125
--- Changes
+++ Changes
@@ -1,5 +1,8 @@
Revision history for Petal.
+2.16
+ - Added Cookbook.pod documentation and associated tests from William McKee
+
2.15 Wed Jan 5 15:31:00 2005
- Fixed some 'used of uninitialized values' warnings
- Added support for non-alphanumeric xml attribute names in tal:attributes
Index: Petal.pm
===================================================================
RCS file: /var/spool/cvs/Petal/lib/Petal.pm,v
retrieving revision 1.124
retrieving revision 1.125
diff -Llib/Petal.pm -Llib/Petal.pm -u -r1.124 -r1.125
--- lib/Petal.pm
+++ lib/Petal.pm
@@ -101,7 +101,7 @@
# this is for CPAN
-our $VERSION = '2.15';
+our $VERSION = '2.16';
# The CodeGenerator class backend to use.
Index: Cookbook.pod
===================================================================
RCS file: /var/spool/cvs/Petal/lib/Petal/Cookbook.pod,v
retrieving revision 1.1
retrieving revision 1.2
diff -Llib/Petal/Cookbook.pod -Llib/Petal/Cookbook.pod -u -r1.1 -r1.2
--- lib/Petal/Cookbook.pod
+++ lib/Petal/Cookbook.pod
@@ -2,35 +2,57 @@
Petal::Cookbook - Recipes for building templates with Petal
-=head1 SYNOPSIS
-Not Applicable
=head1 DESCRIPTION
-This document contains some examples of L<Petal|Petal> template usage.
+This document contains some examples of L<Petal|Petal> template usage. Most of
+these examples deal with using Petal to generate HTML files from HTML
+templates.
-=head1 NOTES
-I tend to use Petal to generate HTML files from HTML templates. I name these templates with the .tmpl extension to help distinguish templates from static html. Nonetheless, the templates should be in a non-web accessible directory if you are using Petal for developing web applications.
-
=head1 BASICS
+
+=head2 Template location
+
+When using Petal for web application development, your templates should not
+need to be accessible by the webserver. In fact, it could be a security
+risk if they are available since there may be code or comments which users
+should not see prior to processing by Petal. Thus, you should strive to store
+your templates in a non-web accessible directory. Personally I prefer to place
+the directory outside of the web root but you could also use permissions or
+.htaccess files to control access to the directory. This directory path should
+go into the $Petal::BASE_DIR global setting or the 'base_dir' argument for the
+new() constructor.
+
+
+=head2 Template naming
+
+Although not necessary, I like to name my templates with the .tmpl extension
+to help myself and designers distinguish templates from static html.
+
+
=head2 Passing a hashreference to Petal::process
-An effective way to collate data to send to the Petal process command is via a hash reference. Used as follows, this technique allows you to build up your data to be passed to the template slowly:
- my $hash = { object => $some_object, number => 3 };
- $hash->{'foo'} = "bar";
- my $template = new Petal ( 'test.tmpl' );
- my $html = $template->process($hash);
- # Output the results
- print "Content-type: text/html\n\n";
- print $html;
+An effective way to collate data to send to the Petal process command is via a
+hash reference. Used as follows, this technique allows you to build up your
+data to be passed to the template slowly:
+
+ my $hash = { string => 'Three', 'number' => 3 };
+ $hash->{'foo'} = "bar";
+ my $template = new Petal ( 'test.tmpl' );
+ my $html = $template->process($hash);
+ # Output the results
+ print "Content-type: text/html\n\n";
+ print $html;
+
=head1 INTERMEDIATE TIPS
+
=head2 Assigning attributes (submitted by Warren Smith)
Up until now, if I wanted to use petal to pre-select an item in a selectbox, I
@@ -73,10 +95,12 @@
=head2 Generating even/odd rows (submitted by Warren Smith)
+
I developed a decode: modifier that works similar to Oracle's decode
-statement. It should be making it into the next release of Petal::Utils. So,
-making even/odd rows of a table different classes, which allows you to do
-things like alter color, font-size, etc, is relatively easy.
+statement. It provides an if/then/else construct and is part of the
+L<Petal::Utils|Petal::Utils> collection of modifiers. Using decode, it is
+possible to make even/odd rows of a table different classes, which allows you
+to do things like alter color, font-size, etc, is relatively easy.
Example:
@@ -85,16 +109,24 @@
</table>
-Thanks to Warren Smith for this tip.
+Thanks to Warren Smith for this tip. See L<Petal::Utils|Petal::Utils> for more information.
+
=head1 ADVANCED
+
=head2 Invoking methods on objects
+
Petal supports the ability to call an object's methods if passed in to Petal::process via the %hash. Say you wish to check whether a particular record is contained in a recordset returned from an SQL query. Using OO-Perl techniques, you could use the following technique as described by Jean-Michel:
-* all your records are hashrefs which come from some database
-* you have a list of them to display
+=over 4
+
+=item * all your records are hashrefs which come from some database
+
+=item * you have a list of them to display
+
+=back
Let's say that the database table looks like this:
@@ -105,6 +137,7 @@
use MyApplication::Record::Rater;
my @records = complicated_query_somewhere_else();
bless $_, "MyApplication::Record::Rater" for (@records);
+ $hash->{'records'} = \@records;
Your module could look like that:
@@ -129,20 +162,18 @@
Then on top of your existing data, you have a method which you can call
from Petal, i.e.
- <span petal:condition="true:record/is_current_id">
- blah blah blah...
- </span>
+ <ul petal:repeat="record records">
+ <li petal:condition="true:record/is_current_id" petal:content="string: Current id = $record/id">Current id</li>
+ </ul>
-This trick can also be used when you have foreign keys in database
-fields.
+This trick can also be used when you have foreign keys in database fields.
<fictious_scenario>
-For example, let's imagine that you have a column called
-'friend_id'. It references another 'rater' which is supposed to be a
-friend of that person.
+For example, let's imagine that you have a column called 'friend_id'. It
+references another 'rater' which is supposed to be a friend of that person.
-You could defined the following subroutine:
+You could define the following subroutine:
# give me the friend record for that person
sub friend
@@ -161,33 +192,36 @@
Then in your template, you could do:
- <?petal:if name="true:rater/friend"?>
- Your friend is:
- $encode:rater/friend/first_name
- $encode:rater/friend/last_name
- <?petal:end?>
+ <div petal:if="true:rater/friend">
+ Your friend is: <span petal:content="string: $rater/friend/first_name $rater/friend/last_name">First Last</span>
+ </div>
</fictious_scenario>
Thanks to Jean-Michel Hiver for this tip.
+If you are doing a lot of database manipulation via Petal, you probably should
+consider an object-relational mapping library . Personally, I recommend
+L<Class::DBI|Class::DBI>. There is a list of many of these tools at Perl
+Object Oriented Persistence (L<http://poop.sourceforge.net/>).
+
- NEEDS TO BE TESTED
- NEEDS TO BE TESTED
=head2 Using CGI.pm to build forms
- NEEDS TO BE TESTED
- NEEDS TO BE TESTED
-Be sure to call CGI with the -compile option as follows:
- use CGI(-compile [:all]);
Calling the HTML generating methods of CGI.pm from the Petal template provides
an extremely simple means to develop forms. For example, the ususal ratnest of
-loops used to populate a checkbox group can be replaced by the simple elegant
-construct below. You can put in a dummy checkbox to give the HTML designer
-something to look at.
-
-<span petal:replace="query/checkbox_group 'Choices' choices '' 'true'">
-<input name="Choices" type="checkbox" value="test">Test</input> </span>
+loops used to populate a checkbox group can be replaced by the simple and
+elegant construct below. You can put in a dummy checkbox to give the HTML
+designer something to look at. Be sure to call CGI with the -compile option as
+follows:
+
+ use CGI qw(-compile [:all]);
+ $hash->{'query'} = new CGI;
+ $hash->{'choices'} = [1, 2, 3, 4];
+
+ <span petal:replace="query/checkbox_group 'Choices' choices '' 'true'">
+ <input name="Choices" type="checkbox" value="test">Test</input>
+ </span>
Thanks to Kurt Stephens for this tip.
@@ -195,18 +229,29 @@
=head1 COPYRIGHT
-Copyright (c) 2002-2005 Knowmad Services Inc. All rights reserved.
-
This program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.
+All code examples in these files are hereby placed into the public domain. You
+are permitted and encouraged to use this code in your own programs for fun or
+for profit as you see fit. A simple comment in the code giving credit would be
+courteous but is not required.
+
+
+
=head1 AUTHOR
- William McKee <william at knowmad.com>.
+William McKee <william at knowmad.com>.
+
+Thanks to the following contributors: Jean-Michel Hiver, Kurt Stephens, Warren
+Smith, Fergal Daly.
+
+
=head1 SEE ALSO
-L<Petal|Petal>, L<Petal::Utils|Petal::Utils>
+L<Petal|Petal>, L<Petal::Utils|Petal::Utils>, the test file t/084_Cookbook.t
+and the test template t/data/cookbook.html.
=cut
--- /dev/null
+++ t/084_Cookbook.t
@@ -0,0 +1,114 @@
+#!/usr/bin/perl
+
+#
+# Tests for Petal::Cookbook recipes
+#
+# To view output, use DEBUG environment setting.
+# DEBUG=1 perl t/084_Cookbook.t
+# the output can be piped to w3m
+# DEBUG=1 perl t/084_Cookbook.t | w3m -T text/html
+# or redirected to a file for viewing with a browser
+# DEBUG=1 perl t/084_Cookbook.t > output.html
+
+use warnings;
+use strict;
+use lib ('lib');
+use Test::More 'no_plan';
+use Petal;
+use Data::Dumper;
+
+my $template_file = 'cookbook.html';
+$Petal::BASE_DIR = './t/data/';
+
+# Fixup path for taint support
+$ENV{PATH} = "/bin:/usr/bin";
+
+# Setup Petal environment
+$Petal::DISK_CACHE = 0;
+$Petal::MEMORY_CACHE = 0;
+$Petal::TAINT = 1;
+$Petal::INPUT = "XHTML";
+$Petal::OUTPUT = "XHTML";
+
+# Create object
+my $template = new Petal($template_file);
+
+
+# Basic - Passing a hashreference to Petal::process
+my $hash = { string => 'Three', 'number' => 3 };
+$hash->{'foo'} = "bar";
+$hash->{'arrayref'} = [ {foo => 'Craig'}, {foo => 'Jim'} ];
+$hash->{'arrayref'}->[2] = {'foo' => 'William'};
+
+
+# Advanced - Invoking methods on objects
+{
+ package MyApplication::Record::Rater;
+ use strict;
+ use warnings;
+ use CGI;
+ use Carp;
+
+ sub is_current_id {
+ my $self = shift;
+ return $self->{id} == 2;
+ # Alternative way to evaluate current_id
+ #my $cgi = CGI->new;
+ #my $id = $cgi->param('rater.id');
+ #return unless (defined $id and $id and $id =~ /^\d+$/);
+ #return $id == $self->{id};
+ }
+ 1;
+}
+package main;
+#use MyApplication::Record::Rater;
+# Raters (id, first_name, last_name, relation, phone, email)
+my @records = (
+{
+id => 1,
+first_name => 'George',
+last_name => 'Jetson',
+relation => 'father',
+phone => '411-232-3333',
+email => 'george at spacely.com',
+},
+{
+id => 2,
+first_name => 'Judy',
+last_name => 'Jetson',
+relation => 'mother',
+phone => '411-232-3333',
+email => 'judy at spacely.com',
+},
+{
+id => 3,
+first_name => 'Jane',
+last_name => 'Jetson',
+relation => 'daughter',
+phone => '411-232-3333',
+email => 'jane at spacely.com',
+},
+);
+bless $_, "MyApplication::Record::Rater" for (@records);
+$hash->{'records'} = \@records;
+
+
+# Advanced - Using CGI.pm to generate forms
+use CGI qw(-compile [:all]);
+$hash->{'query'} = new CGI;
+$hash->{'choices'} = [1, 2, 3, 4];
+
+
+my $out;
+eval {
+$out = $template->process($hash);
+};
+is($@, '', 'No errors during processing');
+ok($out, 'Output was received');
+
+print $out if $ENV{'DEBUG'};
+
+1;
+
+
+__END__
--- /dev/null
+++ t/data/cookbook.html
@@ -0,0 +1,86 @@
+<html>
+ <head>
+ <title>Petal Test</title>
+ <style type="text/css">
+ .active {
+ background-color: yellow;
+ }
+ </style>
+ </head>
+
+ <body>
+ <h1>Petal Test</h1>
+
+ <h2>Basic - Passing a hashreference to Petal::process</h2>
+ <table border="1">
+ <tr petal:if="false: arrayref">
+ <td>No elements</td>
+ </tr>
+ <tr petal:if="arrayref" petal:repeat="rec arrayref">
+ <td>$rec/foo</td>
+ </tr>
+ </table>
+
+ <p petal:content="string">String</p>
+ <p petal:content="number">#</p>
+ <p petal:content="foo">foo</p>
+
+
+
+ <h2>Advanced - Invoking methods on objects</h2>
+ <table border="1">
+ <tr>
+ <th>ID</th>
+ <th>Name</th>
+ <th>Phone</th>
+ <th>Active</th>
+ </tr>
+ <tr petal:if="false: records">
+ <td colspan="5">No elements</td>
+ </tr>
+ <tr petal:if="records" petal:repeat="record records" petal:attr="class $record/is_current_id '1' 'active'">
+ <td petal:content="record/id">ID</td>
+ <td petal:content="string:$record/first_name $record/last_name">First Last</td>
+ <td petal:content="record/phone">Phone</td>
+ <td petal:condition="true:record/is_current_id" align="center">x</td>
+ </tr>
+ </table>
+
+ <ul petal:repeat="record records">
+ <li petal:condition="true:record/is_current_id" petal:content="string: Current id = $record/id">Current id</li>
+ </ul>
+
+
+
+
+
+ <h2>Advanced - Using CGI.pm to generate forms</h2>
+ <table cellpadding="0" cellspacing="0" border="0" width="300">
+ <tr>
+ <th>Checkbox group</th>
+ <th>Select group</th>
+ <th>Radio button group</th>
+ </tr>
+ <tr>
+ <td width="100">
+ <span petal:replace="structure query/checkbox_group 'Choices' choices '' 'true'">
+ <input name="Choices" type="checkbox" value="test">Test</input>
+ </span>
+ </td>
+
+ <td width="100" valign="top">
+ <span petal:replace="structure query/popup_menu 'Choices' choices '' 'true'">
+ <input name="Choices" type="checkbox" value="test">Test</input>
+ </span>
+ </td>
+
+ <td valign="top">
+ <span petal:replace="structure query/radio_group 'Choices' choices '' 'true'">
+ <input name="Choices" type="checkbox" value="test">Test</input>
+ </span>
+ </td>
+ </tr>
+ </table>
+
+ </body>
+</html>
More information about the MKDoc-commit
mailing list