.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.32
.\"
.\" Standard preamble:
.\" ========================================================================
.de Sh \" Subsection heading
.br
.if t .Sp
.ne 5
.PP
\fB\\$1\fR
.PP
..
.de Sp \" Vertical space (when we can't use .PP)
.if t .sp .5v
.if n .sp
..
.de Vb \" Begin verbatim text
.ft CW
.nf
.ne \\$1
..
.de Ve \" End verbatim text
.ft R
.fi
..
.\" Set up some character translations and predefined strings. \*(-- will
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
.\" double quote, and \*(R" will give a right double quote. | will give a
.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to
.\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C'
.\" expand to `' in nroff, nothing in troff, for use with C<>.
.tr \(*W-|\(bv\*(Tr
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
.ie n \{\
. ds -- \(*W-
. ds PI pi
. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
. ds L" ""
. ds R" ""
. ds C` ""
. ds C' ""
'br\}
.el\{\
. ds -- \|\(em\|
. ds PI \(*p
. ds L" ``
. ds R" ''
'br\}
.\"
.\" If the F register is turned on, we'll generate index entries on stderr for
.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index
.\" entries marked with X<> in POD. Of course, you'll have to process the
.\" output yourself in some meaningful fashion.
.if \nF \{\
. de IX
. tm Index:\\$1\t\\n%\t"\\$2"
..
. nr % 0
. rr F
.\}
.\"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.hy 0
.if n .na
.\"
.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
.\" Fear. Run. Save yourself. No user-serviceable parts.
. \" fudge factors for nroff and troff
.if n \{\
. ds #H 0
. ds #V .8m
. ds #F .3m
. ds #[ \f1
. ds #] \fP
.\}
.if t \{\
. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
. ds #V .6m
. ds #F 0
. ds #[ \&
. ds #] \&
.\}
. \" simple accents for nroff and troff
.if n \{\
. ds ' \&
. ds ` \&
. ds ^ \&
. ds , \&
. ds ~ ~
. ds /
.\}
.if t \{\
. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
.\}
. \" troff and (daisy-wheel) nroff accents
.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
.ds ae a\h'-(\w'a'u*4/10)'e
.ds Ae A\h'-(\w'A'u*4/10)'E
. \" corrections for vroff
.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
. \" for low resolution devices (crt and lpr)
.if \n(.H>23 .if \n(.V>19 \
\{\
. ds : e
. ds 8 ss
. ds o a
. ds d- d\h'-1'\(ga
. ds D- D\h'-1'\(hy
. ds th \o'bp'
. ds Th \o'LP'
. ds ae ae
. ds Ae AE
.\}
.rm #[ #] #H #V #F C
.\" ========================================================================
.\"
.IX Title "Bigtop::Docs::Cookbook 3"
.TH Bigtop::Docs::Cookbook 3 "2008-01-18" "perl v5.8.8" "User Contributed Perl Documentation"
.SH "Name"
.IX Header "Name"
Bigtop::Docs::Cookbook \- Bigtop syntax by example
.SH "Intro"
.IX Header "Intro"
This document is meant to be like the Perl Cookbook with short wishes
you might long for, together with syntax to type in your bigtop file
and what that produces. In addition, many sections start
with a simple question about what gets built by the backend in question.
.PP
This document assumes you will be editing your bigtop file with a text
editor (it was written before tentmaker). You may also choose to
maintain your bigtop file with tentmaker. Generally, the advice here
governs what values you put in the boxes at the far right side of the
Backends tab in tentmaker. Some of the other advice must be applied
on the App Body tab. See Bigtop::Docs::TentTut to get started with
tentmaker or Bigtop::Docs::TentRef for full details on using it.
.PP
For full syntax consult Bigtop::Docs::AutoKeywords and/or
Bigtop::Docs::Syntax along with Bigtop::Docs::AutoBackends.
You could also run tentmaker which displays the same things as the
Auto Docs, but in an organized way in a browser.
.PP
The questions are in sections. Here is a complete list of sections and
questions:
.IP "\(bu" 4
Quick Starts for the Lazy
.RS 4
.IP "\(bu" 4
\&\*(L"I'm lazy, what's the quickest way to get started?\*(R"
.IP "\(bu" 4
\&\*(L"How can I just as easily add to an existing bigtop file?\*(R"
.RE
.RS 4
.RE
.IP "\(bu" 4
Init
.RS 4
.IP "\(bu" 4
\&\*(L"What does Init::Std build?\*(R"
.IP "\(bu" 4
\&\*(L"How can I regenerate some of those files but not others?\*(R"
.IP "\(bu" 4
\&\*(L"I don't like the bigtop defaults how can I change them before building?\*(R"
.RE
.RS 4
.RE
.IP "\(bu" 4
Stand Alone Server
.RS 4
.IP "\(bu" 4
\&\*(L"How do I make a stand alone server for my app?\*(R"
.IP "\(bu" 4
\&\*(L"How do I change databases with the generated stand alone server?\*(R"
.RE
.RS 4
.RE
.IP "\(bu" 4
\&\s-1SQL\s0
.RS 4
.IP "\(bu" 4
\&\*(L"What do \s-1SQL\s0 backends make?\*(R"
.IP "\(bu" 4
\&\*(L"How do I make a table?\*(R"
.IP "\(bu" 4
\&\*(L"How do I make a primary key column?\*(R"
.IP "\(bu" 4
\&\*(L"What all can I put in a table block?\*(R"
.IP "\(bu" 4
\&\*(L"How can I include data for initial population into a table?\*(R"
.IP "\(bu" 4
\&\*(L"How do I put extra things into schema.*?\*(R"
.IP "\(bu" 4
\&\*(L"How do I make a sequence\*(R"
.RE
.RS 4
.Sp
\&\s-1CGI\s0
.IP "\(bu" 4
\&\*(L"What do \s-1CGI\s0 backends make?\*(R"
.IP "\(bu" 4
\&\*(L"How do I specify configuration values?\*(R"
.IP "\(bu" 4
\&\*(L"How do I specify Gantry::Conf configuration values?\*(R"
.IP "\(bu" 4
\&\*(L"How do I control \s-1CGI\s0 locations?\*(R"
.RE
.RS 4
.RE
.IP "\(bu" 4
httpd.conf
.RS 4
.IP "\(bu" 4
\&\*(L"What do HttpdConf backends make?\*(R"
.IP "\(bu" 4
\&\*(L"How do I specify PerlSetVar values for mod_perl?\*(R"
.IP "\(bu" 4
\&\*(L"How do I use Gantry::Conf for mod_perl?\*(R"
.IP "\(bu" 4
\&\*(L"How do I put extra statements into my Apache Perl block?\*(R"
.IP "\(bu" 4
\&\*(L"How do I put extra directives into httpd.conf?\*(R"
.RE
.RS 4
.RE
.IP "\(bu" 4
Gantry conrollers
.RS 4
.IP "\(bu" 4
\&\*(L"What does the Gantry Control backend make?\*(R"
.IP "\(bu" 4
\&\*(L"How do I associate a controller with a table?\*(R"
.IP "\(bu" 4
\&\*(L"How do I get a stub method in my controller?\*(R"
.IP "\(bu" 4
\&\*(L"How do I use Gantry's AutoCRUD?\*(R"
.IP "\(bu" 4
\&\*(L"How do I use Gantry's \s-1CRUD\s0?\*(R"
.RE
.RS 4
.RE
.IP "\(bu" 4
Using Gantry's \s-1ORM\s0 Help
.RS 4
.IP "\(bu" 4
\&\*(L"What does the GantryDBIxClass Model backend make?\*(R"
.IP "\(bu" 4
\&\*(L"What does the GantryCDBI Model backend make?\*(R"
.IP "\(bu" 4
\&\*(L"How do I specify a primary key for my model?\*(R"
.IP "\(bu" 4
\&\*(L"How can I make my model inherit from a class of my choice?\*(R"
.IP "\(bu" 4
\&\*(L"How can I alter the generated models behavior?\*(R"
.RE
.RS 4
.RE
.IP "\(bu" 4
Gantry's home made models
.RS 4
.IP "\(bu" 4
\&\*(L"What does the Gantry Model backend make?\*(R"
.IP "\(bu" 4
\&\*(L"How do I specify a primary key for my model?\*(R"
.IP "\(bu" 4
\&\*(L"How can I make my model inherit from a class of my choice?\*(R"
.IP "\(bu" 4
\&\*(L"How can I alter the generated models behavior?\*(R"
.RE
.RS 4
.RE
.IP "\(bu" 4
Other
.RS 4
.IP "\(bu" 4
\&\*(L"How can I change what a backend generates?\*(R"
.IP "\(bu" 4
\&\*(L"What if the backend isn't giving enough data to the template?\*(R"
.RE
.RS 4
.RE
.SH "Quick Starts for the Lazy"
.IX Header "Quick Starts for the Lazy"
.Sh "I'm lazy, what's the quickest way to get started?"
.IX Subsection "I'm lazy, what's the quickest way to get started?"
The two main paths to laziness are tentmaker (see Bigtop::Docs::TentTut)
and the bigtop script itself \*(-- with the proper command line parameters.
.PP
Suppose you have a little data model:
.PP
.Vb 3
\& +--------+ +--------+ +-------------+
\& | child |----->| family |<-----| anniversary |
\& +--------+ +--------+ +-------------+
.Ve
.PP
You could start your app like this:
.PP
.Vb 3
\& bigtop --new Contacts \e
\& 'child(name,birth_day:date)->family(name,phone,+email)
\& anniversary(anniv_date:date,preferred_gift=money)->family'
.Ve
.PP
The string in single quotes is a 'kickstart' description of the data model.
Column names go in parentheses. Types default to strings, if you need
something else use a colon as for \f(CW\*(C`birth_day\*(C'\fR in the child table. Indicate
optional fields with a leading plus sign. Specify literal defaults with
an equal sign as for anniversary \f(CW\*(C`preferred_gift\*(C'\fR.
.PP
In addition to the columns listed, each table will have an integer
primary key called id and two dates fields: created and modified.
You may remove those after initial generation is you like, but eliminating
the integer id makes using an Object Relational Mapper (\s-1ORM\s0) harder.
.PP
For slightly different discussion and instructions for on building an
app directly from an existing PostgreSQL 8 database, see
\&\f(CW\*(C`Bigtop::Docs::QuickStart\*(C'\fR.
.Sh "How can I just as easily add to an existing bigtop file?"
.IX Subsection "How can I just as easily add to an existing bigtop file?"
Suppose that you want to add some tables to the app from the previous
question, here's all you need to do (from the Contacts directory):
.PP
.Vb 1
\& bigtop --add docs/contacts.bigtop 'family<->job(title,description)'
.Ve
.PP
So, you can use a 'kickstart' even if you have already started. Then
it will kick start the addition of tables.
.PP
This will add a new table for jobs and a many-to-many relationship
between it and the existing family table. It will also rebuild the
app. Specify columns for new table as in the previous question. Existing
tables will get new foreign keys, but can't be changed in any other way
from the command line. Note that you will need to alter your database
before restarting the application. Use the new table(s) and foreign key(s)
in docs/schema.YOUR_DB_NAME to make the additions.
.Sh "I don't like the bigtop defaults how can I change them before building?"
.IX Subsection "I don't like the bigtop defaults how can I change them before building?"
This question could talk about two things. If you are using bigtop with
the \-\-new (\-n) or \-\-add (\-a) flags, you might want to provide table names
and their relationships while listing table columns and their \s-1SQL\s0 types.
To control these defaults use the kickstart syntax described in
Bigtop::ScriptHelp::Style::Kickstart.
.PP
To control defaults like author names or copyright statements, keep reading
here.
.PP
In normal use, I invoke the bigtop script to build new applications with
the \-n flag:
.PP
.Vb 1
\& bigtop -n NewApp file.kickstart
.Ve
.PP
Again, see Bigtop::ScriptHelp::Style::Kickstart for what to put in
the kickstart file.
.PP
When bigtop builds an application like this, it uses a default bigtop stub
so that the result will run once the SQLite database is in place. You
may replace the default stub with one of your own. Simply put a file
called \f(CW\*(C`.bigtopdef\*(C'\fR in your home directory. Your .bigtopdef file must
be a valid bigtop file, but you may put any valid bigtop commands in it.
This allows you to control defaults like authors and copyright statements.
You can use it to specify \f(CW\*(C`mod_perl 2\*(C'\fR as the default engine. You
could even include a default table in every app.
.PP
Bigtop will use .bigtopdef if it is present in your home directory. Then,
it will augent it based on the command line request given to \-n flags.
The same .bigtopdef is used when you start tentmaker with the \-n flag.
.SH "Init"
.IX Header "Init"
.Sh "What does Init::Std build?"
.IX Subsection "What does Init::Std build?"
If your config includes:
.PP
.Vb 3
\& config {
\& Init Std {}
\& }
.Ve
.PP
bigtop will generate the following regular files:
.PP
.Vb 5
\& Build.PL
\& Changes
\& MANIFEST
\& MANIFEST.SKIP
\& README
.Ve
.PP
It also makes the following directories:
.PP
.Vb 3
\& docs
\& lib
\& t
.Ve
.PP
It will try to put the bigtop file into the docs directory (but it
won't overwrite it, if its already there). Note that Init doesn't put
things into the lib or t directories.
.PP
Everything Init::Std builds is a stub (and will never be overwritten),
except the \s-1MANIFEST\s0.
.Sh "How can I regenerate some of those files but not others?"
.IX Subsection "How can I regenerate some of those files but not others?"
Once upon a time, Init Std was kind of stupid. It would rewrite all of
its files everytime, unless you asked it not to. Now, it thinks of all
of its files, except the \s-1MANIFEST\s0, as stubs. That means, it will no longer
write \s-1README\s0, Changes, Build.PL, or \s-1MANIFEST\s0.SKIP, unless they are missing
from the disk.
.PP
Because of history, there are now two ways to turn off \s-1MANIFEST\s0 updating.
As with all backends, you can prevent all regeneration:
.PP
.Vb 1
\& Init Std { no_gen 1; }
.Ve
.PP
But you may also be explicit:
.PP
.Vb 1
\& Init Std { MANIFEST no_gen; }
.Ve
.PP
When the \s-1MANIFEST\s0 is regenerated, Init Std uses the same method as both
MakeMaker and Module::Build. So, you could do it yourself with:
.PP
.Vb 1
\& ./Build manifest
.Ve
.PP
That is independent of whether bigtop updates \s-1MANIFEST\s0.
.SH "Stand Alone Server"
.IX Header "Stand Alone Server"
There is no special backend for making stand alone servers, but there
is a way to generate them for Gantry:
.Sh "How do I make a stand alone server for my app?"
.IX Subsection "How do I make a stand alone server for my app?"
To get a stand alone server, do just what you would for a \s-1CGI\s0 app,
but add the with_server statement to the \s-1CGI\s0 backend block in the config
section:
.PP
.Vb 15
\& config {
\& engine CGI;
\& Init Std {}
\& CGI Gantry { with_server 1; }
\& }
\& app Name {
\& config {
\& variable_1 value;
\& variable_2 `multi-word value`;
\& overriden global;
\& }
\& controller SubPage {
\& rel_location subpage;
\& }
\& }
.Ve
.PP
This yields a \s-1CGI\s0 script as normal and app.server which can be executed
directly (it requires HTTP::Server::Simple). Here is a simplified version
of what you get:
.PP
.Vb 2
\& #!/usr/bin/perl
\& use strict;
.Ve
.PP
.Vb 1
\& use CGI::Carp qw( fatalsToBrowser );
.Ve
.PP
.Vb 1
\& use Name qw{ -Engine=CGI -TemplateEngine= };
.Ve
.PP
.Vb 1
\& use Gantry::Server;
.Ve
.PP
.Vb 1
\& use Gantry::Engine::CGI;
.Ve
.PP
.Vb 11
\& my $cgi = Gantry::Engine::CGI->new( {
\& config => {
\& variable_1 => 'value',
\& variable_2 => 'multi-word value',
\& overriden => 'global',
\& },
\& locations => {
\& '/' => 'Name',
\& '/subpage' => 'Name::SubPage',
\& },
\& } );
.Ve
.PP
.Vb 1
\& my $port = shift || 8080;
.Ve
.PP
.Vb 3
\& my $server = Gantry::Server->new( $port );
\& $server->set_engine_object( $cgi );
\& $server->run();
.Ve
.PP
The actual version includes option handling to allow command line control
of which \s-1DBD\s0, database user, and database password.
.PP
This server binds to port 8080 by default. To change the port, add the
server_port statement:
.PP
.Vb 2
\& CGI Gantry { with_server 1;
\& server_port 9999; }
.Ve
.PP
This will change the script in only one place:
.PP
.Vb 1
\& my $port = shift || 9999;
.Ve
.PP
As you can see, users can supply a port on the command line when they start
it.
.Sh "How do I change databases with the generated stand alone server?"
.IX Subsection "How do I change databases with the generated stand alone server?"
While you could edit your stand alone server, that removes the fun of
letting bigtop keep it up to date. Here's how to switch databases. There
are really two approaches: (1) specify the database connection info with
command line flags or (2) put the database connection info into a named
config block and choose that with command line flags.
.PP
The first approach is for those with more impatience than laziness. But,
remember that laziness is the chief virtue. If you have a database built,
you can specify it (even if Bigtop wouldn't support \s-1SQL\s0 generation for it):
.PP
.Vb 1
\& ./app.server -d DBDName -n dbname -u username -p password
.Ve
.PP
To make that specific, suppose I have a PostgreSQL database called 'littledb'
which a user called 'bobby' is allowed to access with password 'valentine':
.PP
.Vb 1
\& ./app.server -d Pg -n littledb -u bobby -p valentine
.Ve
.PP
Yes, that is a lot of typing. Usually, you do it once and use up arrow
to find the command again every time you need a restart. Still, the other
way is cheaper on the keystrokes. It just requires a bit of up front work.
.PP
In Bigtop files, you may have as many config blocks as you like. Among
other things, these include database connection information. To specify the
last example database add a config block like this:
.PP
.Vb 5
\& config littledb {
\& dbconn dbi:Pg:dbname=littledb
\& dbuser bobby
\& dbpass valentine
\& }
.Ve
.PP
Note that the name of the config block is arbitrary, except that 'base' is
reserved as the internal name for the (normally) unnamed block. With that
config block in place, you may regen:
.PP
.Vb 1
\& bigtop docs/yourapp.bigtop all
.Ve
.PP
and then start the app server, asking it to use the new config block:
.PP
.Vb 1
\& ./app.server -t littledb
.Ve
.PP
The main idea behind the named config blocks is to allow this sort of quick
shift. It also works well for dev vs. qual vs. prod.
.SH "SQL"
.IX Header "SQL"
.Sh "What do \s-1SQL\s0 backends make?"
.IX Subsection "What do SQL backends make?"
\&\s-1SQL\s0 backends make docs/schema.* (where * is for your database engine,
like postgres) in the build directory. It should be ready for direct use
to create your database.
.PP
Note that unlike other backend types, you can build with all of the \s-1SQL\s0
backends concurrently. They write different files. They also do a
bit of interpretation to handle differences in their \s-1SQL\s0 syntax.
.Sh "How do I make a table?"
.IX Subsection "How do I make a table?"
Tables are made with blocks:
.PP
.Vb 3
\& table name {
\& #...
\& }
.Ve
.PP
Inside the braces you need may specify the table's sequence and
its fields:
.PP
.Vb 5
\& table name {
\& sequence name_seq;
\& field id { is int4, primary_key, auto; }
\& field name { is varchar; }
\& }
.Ve
.Sh "How do I make a primary key column?"
.IX Subsection "How do I make a primary key column?"
Include \f(CW\*(C`primary_key\*(C'\fR as one of the attributes of the is statement for the
field (see above or below). This will add \f(CW\*(C`PRIMARY KEY\*(C'\fR in the schema.*,
but will also show Model backends that the field is primary.
.Sh "What all can I put in a table block?"
.IX Subsection "What all can I put in a table block?"
Here is a table with several types of fields:
.PP
.Vb 3
\& table invoices {
\& sequence invoices_seq;
\& foreign_display `%number`;
.Ve
.PP
.Vb 41
\& field id { is int4, primary_key, assign_by_sequence; }
\& field number {
\& is int4;
\& label `Number (example: COM-12)`;
\& html_form_type text;
\& html_form_constraint `qr{^\ew\ew\ew-\ed+$}`;
\& }
\& field status_id {
\& is int4;
\& label Status;
\& refers_to status;
\& html_form_type select;
\& }
\& field paid {
\& is date;
\& label `Paid On`;
\& date_select_text `Popup Calendar`;
\& html_form_type text;
\& html_form_optional 1;
\& }
\& field customer_id {
\& is int4;
\& label Customer;
\& refers_to customers;
\& html_form_type select;
\& }
\& field has_good_default {
\& is varchar;
\& label `Replace as Desired`;
\& html_form_type text;
\& html_form_default_value `avalue`;
\& }
\& field notes {
\& is text;
\& label `Notes to Customer`;
\& html_form_type textarea;
\& html_form_optional 1;
\& html_form_rows 4;
\& html_form_cols 50;
\& }
\& }
.Ve
.PP
Note that int4 will be converted into a reasonable integer type for
your database, even if it doesn't use that as a keyword.
.PP
The foreign_display statement controls how rows from this table
appear when other tables refer to them. This is available through
the model's foreign_display method:
.PP
.Vb 1
\& my $show_to_user = $invoice_row_object->foreign_display();
.Ve
.PP
Each field that might appear on the screen should have a label which
the user will see above or next to the values. It becomes the column
label when the field appears in a table. It appears next to the entry
field when the user is entering or updating it.
.PP
Including the refers_to statement implies that the field is a foreign
key. Whether this generates \s-1SQL\s0 indicating that is up to the backend.
None of the current backends (Bigtop::SQL::Postgres, Bigtop::SQL::MySQL,
or Bigtop::SQL::SQLite) generate foreign key \s-1SQL\s0. But, using refers_to
always affects the model. For instance, Bigtop::Model::DBIxClass generates
a belongs_to call for each field with a refers_to statement. Other Model
backends do the analogous things.
.PP
The date_select_text is shown by Gantry templates as the text for
a popup calendar link. See the discussion of the LineItem controller in
Bigtop::Docs::Tutorial for details. You might also want to check 'How can I
let my users pick dates easily?' in Gantry::Docs::FAQ to see
what bigtop generates.
.PP
All of the statements which begin with html_form_ are passed through
to the template (with html_form_ stripped). Consult your template
for details. The Gantry template is form.tt. Note that html_form_constraint
is actually used by Gantry plugins which rely on Gantry::Utils::CRUDHelp.
This includes at least Gantry::Plugins::AutoCRUD and Gantry::Plugins::CRUD.
These constraints are enforced by Data::FormValidator.
.PP
Use html_form_default_value if you want a default when the user and the
database row haven't provided one.
.Sh "How can I include initial data in a table?"
.IX Subsection "How can I include initial data in a table?"
Sometimes it's useful to put some data into the database during creation.
Two types that spring to mind are test data and standard constants.
To include such data add data statements to the table block:
.PP
.Vb 6
\& table status_code {
\& #...
\& data name => `Begun`, descr => `work in progress`;
\& data name => `Billed`, descr => `invoice sent to customer`;
\& data name => `Paid`, descr => `payment received`;
\& }
.Ve
.PP
Notes: (1) you should not set the id if your table has a sequence or is
auto-incrementing the primary key (and it should one do or the other).
(2) remember to surround the values with backquotes if they
have any characters Perl wouldn't like in a variable name (it's always
safe to have backquotes around values, even if they aren't strictly needed,
think of them like the comma after the last item in a Perl list). (3) you
can use as many data statments as you like, each one makes an \s-1SQL\s0 statement:
.PP
.Vb 2
\& INSERT INTO status_code ( name, descr )
\& VALUES ( 'begun', 'work in progress' );
.Ve
.PP
Note that tentmaker cannot insert, update, or delete data statements. But,
if you have them in your file, it will not harm them. To get around this
tentmaker limitation, you need to create literal \s-1SQL\s0 blocks with \s-1INSERT\s0
statements in them. See the next question, for a discussion of literal
\&\s-1SQL\s0 blocks.
.Sh "How do I put extra things into schema.*?"
.IX Subsection "How do I put extra things into schema.*?"
At any point in the app section, you may include a literal \s-1SQL\s0 statement:
.PP
.Vb 1
\& literl SQL `CREATE INDEX name_ind ON some_table ( some_field );`;
.Ve
.PP
There are a couple of things to notice here. First, enclose all of your
literal content in backquotes. It will only be modified in one way. If
it doesn't end in whitespace, one new line will be added to it. Otherwise,
you are on your own.
.PP
Second, there are two semi-colons here. The one inside the backquotes is
for \s-1SQL\s0, the one outside is for Bigtop. The later semi-colon is always
required. It's up to you to make sure the syntax of your literal \s-1SQL\s0 code
is correct (including determining whether it needs a semi\-colon).
.PP
If you want a trailing empty line, do this:
.PP
.Vb 1
\& literl SQL `CREATE INDEX name_ind ON some_table ( some_field );
.Ve
.PP
.Vb 1
\& `;
.Ve
.PP
All trailing whitespace is taken literally. If you include any, no extra
new line will be added.
.PP
The order of \s-1SQL\s0 generation is the same as the order in your Bigtop file.
For example, since the index creation above must come after some_table
is defined, put the literal statement after some_table's block.
.PP
You may use literal \s-1SQL\s0 statements as a way to work around tentmaker's
inability to handle table level data statements. Simply put your \s-1INSERT\s0
statements into a literal \s-1SQL\s0 statement after the table's block.
.Sh "How do I make a sequence?"
.IX Subsection "How do I make a sequence?"
Use a sequence block:
.PP
.Vb 1
\& sequence name_seq {}
.Ve
.PP
This will generate:
.PP
.Vb 1
\& CREATE SEQUENCE name_seq;
.Ve
.PP
in schema.*. Note that blocks for sequences must currently be empty.
Eventually they should support min and max values, etc.
.PP
Most databases don't use sequences. Of the databases supported by
bigtop, only Postgres has them. Even for Postgres, we don't typically
use them any more.
.SH "CGI"
.IX Header "CGI"
.Sh "What do \s-1CGI\s0 backends make?"
.IX Subsection "What do CGI backends make?"
\&\s-1CGI\s0 backends make a single \s-1CGI\s0 based dispatching script called app.cgi
directly in the build directory. You will have to copy it to your
cgi-bin directory and make sure the copy there is executable.
If you use the with_server statement in the \s-1CGI\s0 backend block, they
will also make app.server. You may run it as a stand alone web server,
which is especially useful during testing.
.Sh "How do I specify configuration values?"
.IX Subsection "How do I specify configuration values?"
This question does not represent best practice any more. See the next
question which explains you to use Gantry::Conf.
.PP
Specify \s-1CGI\s0 configuration values with config blocks as you would for
mod_perl apps:
.PP
.Vb 8
\& app SomeApp {
\& config {
\& dbconn `dbi:Pg:dbname=appdb` => no_accessor;
\& dbuser `someone` => no_accessor;
\& dbpass `not_tellin` => no_accessor;
\& page_size 15;
\& }
\& }
.Ve
.PP
These become config hash members:
.PP
.Vb 8
\& my $cgi = Gantry::Engine::CGI->new(
\& config => {
\& dbconn => 'dbi:Pg:dbname=appdb',
\& dbuser => 'someone',
\& dbpass => 'not_tellin',
\& page_size => 15,
\& }
\& );
.Ve
.PP
Note: if you don't use Gantry::Conf, all config parameters for your
\&\s-1CGI\s0 script must be at the app level and they will only appear in the
config hash of the Gantry::Engine::CGI object.
.Sh "How do I specify Gantry::Conf configuration values?"
.IX Subsection "How do I specify Gantry::Conf configuration values?"
To use Gantry::Conf with \s-1CGI\s0 scripts, do two things. First, use the Conf
Gantry backend, telling it the instance name of your app. Second, set
gantry_conf in the \s-1CGI\s0 backend block:
.PP
.Vb 5
\& config {
\& #...
\& Conf Gantry { instacne `your_name`; }
\& CGI Gantry { gantry_conf 1; }
\& }
.Ve
.PP
The instance will be the name of the app's instance in your
/etc/gantry.conf. If your master conf lives in a different file, use
a block like this instead:
.PP
.Vb 11
\& config {
\& #...
\& Conf Gantry {
\& instance `your_name`;
\& conffile `/etc/my_hidden_conf/master.conf`;
\& gen_root 1;
\& }
\& CGI Gantry {
\& gantry_conf 1;
\& }
\& }
.Ve
.PP
If you use a SiteLook backend, you probably want to set \f(CW\*(C`gen_root\*(C'\fR in the Conf
Gantry backend, so it will manufacture a path to your wrapper and
other templates.
.PP
Many times config info varies depending on environment. For instance,
in production you may need to connect to a different database. Named
config blocks help with that. Example:
.PP
.Vb 12
\& config {
\& # all common config here
\& rows_per_page 25;
\& }
\& config dev {
\& dbconn `dbi:SQLite:dbname=app.db`;
\& }
\& config prod {
\& dbconn `dbi:Pg:dbname=proddb;host=db.example.com`;
\& dbuser someuser;
\& dbpass `$ecr3t`;
\& }
.Ve
.PP
With the Conf Gantry backend, this will lead to a single config file with
three instances. Each will begin with the instance prefix from the Conf
Gantry backend config block ('your_name' in the example above). The unnamed
block will have that instance name. The others will have it as a prefix
with their config block name (a.k.a. their config type) as a suffix.
So the instance names will be 'your_name', 'your_name_dev', and
\&'your_name_prod'.
.PP
How you access these depends on how you deploy the app. In the stand alone
server (as we saw in a previous question), you can use the \-t flag:
.PP
.Vb 1
\& ./app.server -t dev
.Ve
.PP
In \s-1CGI\s0, the script uses the config block named \s-1CGI\s0 or cgi without
additional help, though you might want to edit the generated \s-1CGI\s0 script
to alter where it looks for the master conf file. For mod_perl, see below.
.Sh "How do I control \s-1CGI\s0 locations?"
.IX Subsection "How do I control CGI locations?"
The locations your \s-1CGI\s0 script can manage will come from your controllers.
Each controller should have either a location or a rel_location directive.
locations are used as is, rel_locations have the location for the app
prepended. Note that the app location is optional and defaults to '/'.
Do not start or end locations or rel_locations with / (except that the
app level location can be '/').
.PP
.Vb 10
\& app MyAppName {
\& location `/mysubsite`;
\& #... table definitions here
\& controller SomeTable {
\& rel_location `sometable`;
\& }
\& controller Odd {
\& location `/pretends/to_be/part_of/other/app/odd`;
\& }
\& }
.Ve
.PP
For the Gantry \s-1CGI\s0 backend, this leads to the following excerpt in app.cgi:
.PP
.Vb 7
\& my $cgi = Gantry::Endgin::CGI->new(
\& locations => {
\& '/mysubsite' => 'MyAppName',
\& '/mysubsite/sometable' => 'MyAppName::SomeTable',
\& '/pretends/to_be/part_of/other/app/odd' => 'MyAppName::Odd',
\& },
\& );
.Ve
.SH "httpd.conf"
.IX Header "httpd.conf"
.Sh "What do HttpdConf backends make?"
.IX Subsection "What do HttpdConf backends make?"
HttpdConf backends make docs/httpd.conf suitable for use in a mod_perl
apache conf file or as the value of an Include statement there.
.Sh "How do I specify PerlSetVar values for mod_perl?"
.IX Subsection "How do I specify PerlSetVar values for mod_perl?"
The answer to this question no longer represents best practices. See
the next question for how to use Gantry::Conf instead.
.PP
Use config blocks to specify PerlSetVars:
.PP
.Vb 19
\& config {
\& engine MP13;
\& # You could use MP20 instead of MP13.
\& Init Std {}
\& HttpdConf Gantry {}
\& }
\& app Name {
\& config {
\& variable_1 value;
\& variable_2 `multi-word value`;
\& overriden global;
\& }
\& controller SubPage {
\& rel_location subpage;
\& config {
\& overriden subpage;
\& }
\& }
\& }
.Ve
.PP
Note that the SubPage controller includes its own value for the overriden
variable. This results in a PerlSetVar statement in the location block
for this controller. The app level config block results in three
PerlSetVars appearing in the root location block. Output in docs/httpd.conf:
.PP
.Vb 2
\&
\& #!/usr/bin/perl
.Ve
.PP
.Vb 3
\& use Name;
\& use Name::SubPage;
\&
.Ve
.PP
.Vb 5
\&
\& PerlSetVar variable_1 value
\& PerlSetVar variable_2 multi-word value
\& PerlSetVar overriden global
\&
.Ve
.PP
.Vb 4
\&
\& SetHandler perl-script
\& PerlHandler Name::SubPage
\& PerlSetVar overriden subpage
.Ve
.PP
.Vb 1
\&
.Ve
.PP
The Control backend will include these in site object initialization
(in the init method) and make accessors for them. Marking them
no_accessor prevents both of those things (see Controllers below).
.Sh "How do I use Gantry::Conf for mod_perl?"
.IX Subsection "How do I use Gantry::Conf for mod_perl?"
Gantry::Conf allows for all sorts of applications to be configured in
all sorts of ways in one place. It allows multiple apps to share
configuration information, even if they run on different servers.
It allows multiple instances of the same app to use different configuration
information, even if they run in the same apache server. See the docs on
Gantry::Conf for details on its use.
.PP
.Vb 19
\& config {
\& engine MP13;
\& Init Std {}
\& Conf Gantry { instance `your_instance`; }
\& HttpdConf Gantry { skip_config 1; gantry_conf 1; }
\& }
\& app Name {
\& config {
\& variable_1 value;
\& variable_2 `multi-word value`;
\& overriden global;
\& }
\& controller SubPage {
\& rel_location subpage;
\& config {
\& overriden subpage;
\& }
\& }
\& }
.Ve
.PP
The process is very similar for Gantry::Conf as for PerlSetVars. There
are a couple of key differences. First, you should add the Conf Gantry
backend. Second, you should mark the HttpdConf Gantry backend with
gantry_conf, so it won't write PerlSetVars. Finally, you should include
the instance statement in the Conf Gantry backend, whose value is the
name of your instance in /etc/gantry.conf. If your master config file
lives somewhere else, also include conffile in the Conf Gantry backend block:
.PP
.Vb 10
\& config {
\& #...
\& Conf Gantry {
\& instance `your_instance`;
\& conffile `/etc/exotic/location/master.conf`;
\& }
\& HttpdConf Gantry {
\& gantry_conf 1;
\& }
\& }
.Ve
.PP
This yields two output files: a shorter httpd.conf and a new Name.conf.
Here's docs/httpd.conf:
.PP
.Vb 2
\&
\& #!/usr/bin/perl
.Ve
.PP
.Vb 3
\& use Name;
\& use Name::SubPage;
\&
.Ve
.PP
.Vb 3
\&
\& PerlSetVar GantryConfInstance your_instance
\&
.Ve
.PP
.Vb 4
\&
\& SetHandler perl-script
\& PerlHandler Name::SubPage
\&
.Ve
.PP
Here's docs/Name.gantry.conf:
.PP
.Vb 4
\&
\& variable_1 value
\& variable_2 multi-word value
\& overriden global
.Ve
.PP
.Vb 4
\&
\& overriden subpage
\&
\&
.Ve
.PP
You may need to have a variety of different config setups. For instance, you
might need one for dev and a different one for prod. As explained in
\&\*(L"How do I specify Gantry::Conf configuration values?\*(R", you can have
one config block for each deployment. One of them is unnamed (but is
called 'base' internally). The others have names you choose. Each becomes
and instance. The unnamed one has the instance you chose in the
Conf Gantry backend block. The others have that as a prefix and the
config block name as a suffix.
.PP
You will need to edit the generated httpd.conf to switch configs. Just
change the GantryConfInstance PerlSetVar to match the name of the proper
instance in the generated docs/App\-Name.conf.
.Sh "How do I put extra statements into my Apache Perl block?"
.IX Subsection "How do I put extra statements into my Apache Perl block?"
There are two ways to put extra things into the generated Perl block,
depending on where things should appear. If you need something to come
immediately after the #!/usr/bin/perl line (like a use lib), do this:
.PP
.Vb 1
\& literal PerlTop ` use lib '/home/myuser/src/lib';`;
.Ve
.PP
As with all literals, you must enclose your content in backquotes and mind
your own syntax inside those quotes. You are responsible for whitespace
management, except that one new line will be added at the end, if your literal
text does \s-1NOT\s0 have trailing whitespace. So the above will get one new
line added to it.
.PP
PerlTop blocks always appear in the generated httpd.conf in the order
they appear in the Bigtop file and start immediately after the shebang line.
.PP
Note that PerlTop may not be soon enough, for statments like
\&\f(CW\*(C`use Apache::DBI\*(C'\fR, if your httpd.conf has an earlier Perl block.
In that case, you must work manually.
.PP
If you don't care where the statements fall, you can use a literal PerlBlock
statement:
.PP
.Vb 1
\& literal PerlBlock `use SomeModule;`;
.Ve
.PP
These and your controller blocks produce output in the order they appear
in the bigtop file.
.Sh "How do I put extra directives into httpd.conf?"
.IX Subsection "How do I put extra directives into httpd.conf?"
You may include arbitrary things outside of the generated blocks like this:
.PP
.Vb 1
\& literal HttpdConf `Include /some/file.conf`;
.Ve
.PP
These appear intermixed with location blocks in the same order as in the
bigtop file. All of these come after the block.
.PP
You may include additional directives in the base location for the app with
literal Location statements:
.PP
.Vb 6
\& literal Location
\& ` AuthType Basic
\& AuthName "Your Realm"
\& PerlAuthenHandler Gantry::Control::C::Authen
\& PerlAuthzHandler Gantry::Control::C::Authz
\& require valid-user`;
.Ve
.PP
These appear literally immediately below any PerlSetVar statements.
.PP
You may include directives in other location blocks by putting literal
Location statments inside your controller's block:
.PP
.Vb 4
\& controller SecureSubLocation {
\& # ...
\& literal Location ` require group SecretAgent`;
\& }
.Ve
.SH "Gantry conrollers"
.IX Header "Gantry conrollers"
.Sh "What does the Gantry Control backend make?"
.IX Subsection "What does the Gantry Control backend make?"
Gantry controllers usually make two pieces: a stub and a \s-1GEN\s0 module
(but the \s-1GEN\s0 module will not be made if there are no methods to put in
it). The \s-1GEN\s0 module is designed to be regenerated as changes to the
app arise. For this reason, you should not edit the \s-1GEN\s0 module.
Rather, put your code in the stub.
.PP
.Vb 6
\& app Apps::Name {
\& #...
\& controller SomeModule {
\& #...
\& }
\& }
.Ve
.PP
This will make Apps/Name/SomeModule.pm and Apps/Name/GEN/SomeModule.pm.
You shouldn't need to edit the \s-1GEN\s0 module. If it is wrong, update your
Bigtop file and regenerate.
.Sh "How do I associate a controller with a table?"
.IX Subsection "How do I associate a controller with a table?"
Use a controls_table statment to associate your controller with a table:
.PP
.Vb 3
\& controller SomeTableController {
\& controls_table sometable;
\& }
.Ve
.PP
This has one basic effect: it includes a use statement for the
table's model module in your stub and \s-1GEN\s0 modules. That use statement
will import the abbreviated model name. In the example the table has
a name like:
.PP
.Vb 1
\& package Apps::Name::Model::sometable;
.Ve
.PP
But, it exports \f(CW$SOMETABLE\fR as an abbreviation for that package name.
So, the generated statement (repeated in the stub and \s-1GEN\s0 modules) is:
.PP
.Vb 1
\& use Apps::Name::Model::sometable qw( $SOMETABLE );
.Ve
.PP
In addition to the basic effect of controls_table, it is also used
by methods of type AutoCRUD_form and CRUD_form to make sure the
requested fields are available in the controlled table and to find their
labels, etc.
.PP
Note, that a controller will only control one table as generated.
If you need to work with other tables, you'll have to write some code.
.Sh "How do I get a stub method in my controller?"
.IX Subsection "How do I get a stub method in my controller?"
If you need a method stubbed in without useful code, you can say:
.PP
.Vb 5
\& controller Name {
\& method empty is stub {
\& extra_args `$id`;
\& }
\& }
.Ve
.PP
This will make:
.PP
.Vb 6
\& #-------------------------------------------------
\& # $self->empty( $id )
\& #-------------------------------------------------
\& sub empty {
\& my ( $self, $id ) = @_;
\& }
.Ve
.PP
(Note that extra_args is optional.)
.PP
You then fill in the operative bits.
.PP
Note that adding stub methods to your Bigtop file once your stub module
exists will have no effect, since regeneration never alters existing stubs.
To force generation rename or delete the stub module.
.Sh "How do I use Gantry's AutoCRUD?"
.IX Subsection "How do I use Gantry's AutoCRUD?"
Gantry's AutoCRUD supplies do_add, do_edit, and do_delete for simple
tables. To use it say
.PP
.Vb 8
\& controller Simple is AutoCRUD {
\& method form is AutoCRUD_form {
\& form_name simple
\& fields name, address;
\& extra_keys
\& legend => `$self->path_info =~ /edit/i ? 'Edit' : 'Add'`;
\& }
\& }
.Ve
.PP
This makes the following stub:
.PP
.Vb 1
\& package Apps::AppName::Simple;
.Ve
.PP
.Vb 1
\& use strict;
.Ve
.PP
.Vb 4
\& use base 'Apps::AppName';
\& use Apps::AppName::GEN::Simple qw(
\& form
\& );
.Ve
.PP
.Vb 6
\& use Gantry::Plugins::AutoCRUD qw(
\& do_add
\& do_edit
\& do_delete
\& form_name
\& );
.Ve
.PP
.Vb 4
\& #-----------------------------------------------------------------
\& # $self->form( $row )
\& #-----------------------------------------------------------------
\& # This method supplied by Apps::Checkbook::GEN::Trans
.Ve
.PP
Bigtop makes a note in the stub for each method it is mixing in from
the \s-1GEN\s0 module.
.PP
Note that both the \s-1GEN\s0 module and Gantry::Plugins::AutoCRUD are mixins (they
export methods). If you don't want their standard methods, don't include
them in the import lists. But, if you don't want the ones from
Gantry::Plugins::AutoCRUD, you probably want real \s-1CRUD\s0 (see below).
.Sh "How do I use Gantry's \s-1CRUD\s0?"
.IX Subsection "How do I use Gantry's CRUD?"
Gantry's AutoCRUD has quite a bit of flexibility (e.g. it has pre and post
callbacks for add, edit, and delete), but sometimes it isn't enough.
Even when it is enough, some people prefer explicit schemes to implicit
ones. \s-1CRUD\s0 is more explicit. To use it do this:
.PP
.Vb 9
\& controller NotSoSimple is CRUD {
\& text_description `Not So Simple Item`;
\& method my_crud_form is CRUD_form {
\& form_name simple
\& fields name, address;
\& extra_keys
\& legend => `$self->path_info =~ /edit/i ? 'Edit' : 'Add'`;
\& }
\& }
.Ve
.PP
There are only a couple of differences from the AutoCRUD version above. The
controller type is just \s-1CRUD\s0; the form method is called my_crud_form and
has type CRUD_form.
.PP
Note that it is important to use a method name that ends in _form, but
don't use just _form. The backend says:
.PP
.Vb 1
\& my ( $crud_name = $method_name ) =~ s/_form$//;
.Ve
.PP
So using _form as the name (which is required for AutoCRUD) will make
Bad Things happen for \s-1CRUD\s0.
.PP
The above produces a lot of code. I'll show it a piece at a time with
running commentary interspersed. It makes a \s-1CRUD\s0 object:
.PP
.Vb 8
\& my $my_crud = Gantry::Plugins::CRUD->new(
\& add_action => \e&my_crud_add,
\& edit_action => \e&my_crud_edit,
\& delete_action => \e&my_crud_delete,
\& form => \e&my_crud_form,
\& redirect => \e&my_crud_redirect,
\& text_descr => 'Not So Simple Item',
\& );
.Ve
.PP
It makes do_add, do_edit, and do_delete. For example:
.PP
.Vb 5
\& #-------------------------------------------------
\& # $self->do_add( )
\& #-------------------------------------------------
\& sub do_add {
\& my $self = shift;
.Ve
.PP
.Vb 2
\& $my_crud->add( $self, { data => \e@_ } );
\& }
.Ve
.PP
(do_edit and do_delete are similar.)
.PP
Finally, it provides the callbacks. For example:
.PP
.Vb 5
\& #-------------------------------------------------
\& # $self->my_crud_add( $id )
\& #-------------------------------------------------
\& sub my_crud_add {
\& my ( $self, $params, $data ) = @_;
.Ve
.PP
.Vb 3
\& # make a new row in the $YOUR_TABLE table using data from $params
\& # remember to commit
\& }
.Ve
.PP
It also makes my_crud_edit, my_crud_delete, and my_crud_redirect.
Note that you don't get actual code for updating your database, just
comments telling you what normal people do. Of course, abnormality is
one of the main reasons for using \s-1CRUD\s0 instead of AutoCRUD, so take
the comments with a grain of salt.
.PP
Note that if you have more than one method of type CRUD_form, the bigtop
backend will make multiple crud objects (each named for its form)
and the callbacks for those objects. But it will also make multiple
do_add, do_edit, and do_delete methods. They will make their calls through
the proper crud object, but their names will be duplicated. In that
case, you are on your own to change them to reasonable (i.e. non\-clashing)
names.
.SH "Using Gantry's ORM Help"
.IX Header "Using Gantry's ORM Help"
.Sh "What does the GantryDBIxClass Model backend make?"
.IX Subsection "What does the GantryDBIxClass Model backend make?"
The Model GantryDBIxClass backend makes a pair of modules for each table.
One is the stub module, the other is the \s-1GEN\s0 module. Once made, the
stub is never regenerated, so put your code in it. The \s-1GEN\s0 module
will be regenerated when you run bigtop.
.PP
.Vb 9
\& config {
\& #...
\& Model GantryDBIxClass {}
\& }
\& app Apps::Name {
\& table some_table {
\& #...
\& }
\& }
.Ve
.PP
This makes Apps::Name::Model::some_table (the stub) and
Apps::Name::Model::GEN::some_table (the \s-1GEN\s0 module). Note that the
names are exactly the same as the table name. If you want capital
letters, use them to name the table.
.PP
Due to the way that DBIx::Class binds the methods it makes on the fly, the \s-1GEN\s0
module mixes in to the stub by using this to start its file:
.PP
.Vb 1
\& package Apps::Name::Model::some_table;
.Ve
.PP
So, the disk file is named Apps/Name/Model/GEN/some_table.pm, but
the package statement is the same as the one in the stub. This will cause
sub redefinition warnings, if you put a sub in the stub with the same
name as one in the \s-1GEN\s0 module. Models generated by Model Gantry inherit
from Gantry::Utils::Model, which allows inheritence instead of mixing in.
These are the native models.
.PP
In addition to regular tables, the Model GantryDBIxClass backend understands
the join_table block (which became available in version 0.15). Join tables
are needed to support many-to-many relationships like this:
.PP
.Vb 7
\& +-----+ +-------+
\& | job |<-+ +->| skill |
\& +-----+ | | +-------+
\& | |
\& +-----------+
\& | job_skill |
\& +-----------+
.Ve
.PP
To express this, add:
.PP
.Vb 3
\& join_table job_skill {
\& joins job => skill;
\& }
.Ve
.PP
This will have serveral effects. First, all \s-1SQL\s0 backends will make the
job_skill table with three fiels: id and columns to hold ids for the job
and skill tables. Second, the Model GantryDBIxClass backend will make
has_many relationships in both the job and skill model modules and put
belongs_to relationships for the job and skill tables into the model
module for the job_skill table.
.Sh "What does the GantryCDBI Model backend make?"
.IX Subsection "What does the GantryCDBI Model backend make?"
The Model GantryCDBI backend makes modules exactly analogous to
the Model GantryDBIxClass backend, but for use with Class::DBI.
All of the same caveats apply.
.PP
We now prefer DBIx::Class over Class::DBI, since the later has difficultly
sharing database handles with our older apps, which don't use ORMs.
.Sh "How do I specify a primary key for my model?"
.IX Subsection "How do I specify a primary key for my model?"
Each table should have a single column primary key:
.PP
.Vb 4
\& table name {
\& sequence name_seq;
\& field id { is int4, primary_key, auto; }
\& }
.Ve
.PP
This will put \s-1PRIMARY\s0 \s-1KEY\s0 in the sql for the column and tell the
Model backend to make the column primary. This generates:
.PP
.Vb 1
\& Apps::Name::Model::name->set_primary_key( 'id' );
.Ve
.PP
or the appropriate analog for your \s-1ORM\s0.
.Sh "How can I make my model inherit from a class of my choice?"
.IX Subsection "How can I make my model inherit from a class of my choice?"
Normally Model modules inherit from a Gantry::Utils:: module appropriate
for their \s-1ORM\s0. You can change that with the model_base_class statement:
.PP
.Vb 3
\& table name {
\& model_base_class Gantry::Utils::AuthCDBI;
\& }
.Ve
.PP
The generated output will be the same, except for the base class.
The model_base_class need not be in the Gantry::Utils:: namespace.
.PP
If most or all your tables need to inherit from a single base class,
put it in the backend block:
.PP
.Vb 4
\& config {
\& #...
\& Model GantryDBIxClass { model_base_class Exotic::Base; }
\& }
.Ve
.PP
Individual tables can still use the model_base_class statement to override
this replacement global default.
.Sh "How can I alter the generated model's behavior?"
.IX Subsection "How can I alter the generated model's behavior?"
To change the behavior of the generated model, put code in the stub
or use model_base_class to change what it inherits from.
.SH "Gantry's home made models"
.IX Header "Gantry's home made models"
.Sh "What does the Gantry Model backend make?"
.IX Subsection "What does the Gantry Model backend make?"
The Gantry Model backend is simlar to the GantryDBIxClass Model backend.
It makes two modules for each table. For example:
.PP
.Vb 3
\& table name {
\& #...
\& }
.Ve
.PP
will yield App::Name::Model::name and App::Name::Model::GEN::name. Since
these inherit from Gantry::Utils::Model, they don't have problems with
binding run time generated methods to the proper package. This leaves
them free to use inheritence instead of mixing in. The stub inherits from
the \s-1GEN\s0 module which inherits from Gantry::Utils::Model, so the \s-1GEN\s0 module
begins:
.PP
.Vb 1
\& package Apps::Name::Model::GEN::name;
.Ve
.PP
.Vb 1
\& use base 'Gantry::Utils::Model;
.Ve
.PP
while the stub begins:
.PP
.Vb 1
\& package Apps::Name::Model::name;
.Ve
.PP
.Vb 1
\& use base 'Apps::Name::Model::GEN::name';
.Ve
.PP
(actually the stub is also an exporter so it can provide an abbreviated name).
.PP
This means that you can safely override methods in the \s-1GEN\s0 module by
simply writing a sub of the same name in the stub.
.PP
Summary of inheritence
.PP
.Vb 3
\& Gantry::Utils::Model
\& Apps::Name::Model::GEN::name
\& Apps::Name::Model::name
.Ve
.Sh "How do I specify a primary key for my model?"
.IX Subsection "How do I specify a primary key for my model?"
As for the other Model backends, include primary_key in the is statement
for the primary column:
.PP
.Vb 3
\& table name {
\& field id { is int4, primary_key, auto; }
\& }
.Ve
.PP
This will make an implicit sequence for the id field.
.PP
You could use a sequence with the table:
.PP
.Vb 4
\& table name {
\& sequence name_seq;
\& field id { is int4, primary_key, auto; }
\& }
.Ve
.PP
Then the auto-increment values will be drawn from the explicit sequence
\&\f(CW\*(C`name_seq\*(C'\fR.
.Sh "How can I make my model inherit from a class of my choice?"
.IX Subsection "How can I make my model inherit from a class of my choice?"
To change what the \s-1GEN\s0 model inherits from use the model_base_class statement:
.PP
.Vb 4
\& table name {
\& model_base_class Gantry::Utils::Model::Auth;
\& #...
\& }
.Ve
.PP
The base class you specify should respond to the same api as
Gantry::Utils::Model (which is a subset of Class::DBI).
.PP
You can put this in the backend block if you want to make it the
default:
.PP
.Vb 4
\& config {
\& #...
\& Model Gantry { model_base_class Exotic::Base; }
\& }
.Ve
.PP
Even if you do that, individual tables can still requset a special
base class by supplying the model_base_class statement.
.Sh "How can I alter the generated models behavior?"
.IX Subsection "How can I alter the generated models behavior?"
To alter the generated behavior, override the offending method in your
stub.
.SH "Other"
.IX Header "Other"
.Sh "How can I change what a backend generates?"
.IX Subsection "How can I change what a backend generates?"
Most backends use \s-1TT\s0 to generate their output. Those that do default to
Inline::TT. That means there is a hard coded template inside their module.
To change what these generate, copy the template out of the module.
Change whatever you want, except the names of the blocks. Save the result.
Then add a template statement to the backend's config block, with its value
set to a path to your newly saved template.
.Sh "What if the backend isn't giving enough data to the template?"
.IX Subsection "What if the backend isn't giving enough data to the template?"
If you code your own template and it needs addtional information from the
backend, you'll have to modify the backend or write your own. It is not
easy to inherit from backends. Rather, you need to copy the backend and
rename it. Keep in mind that all backends are sharing the syntax
tree package namespaces. This means that your methods need to be uniquely
named to avoid redefining methods supplied by other backends.
.PP
See Bigtop::Docs::Modules for advice on writing your own backends.