Building A Zinc App

From Deep Thought

Jump to: navigation, search

Contents


How to build a Zinc Application.

These instructions assume your are on a linux server with standard access to CPAN and a recent version of Perl installed.

Prepare The Application Workspace

Get Zinc.

cpan -i Zinc::Director
cpan -i Zinc::Act
cpan -i Zinc::Memory
cpan -i Zinc::View

Create your custom extension placeholders.

The custom extensions are where you'll put in any custom functionality that is not part of the base Zinc modules. Normally you'll want to have some custom view and action items.

 mkdir zincmods 
 cd zincmods
 vi MyView.pm
 vi MyAct.pm
 vi MyMemory.pm

MyAct.pm

package MyAct;
use strict;
use base('Zinc::Act');

MyMemory.pm

package MyMemory;
use strict;
use base('Zinc::Memory');

MyView.pm

package MyView;
use strict;
use base('Zinc::View');


Create your templates directory.

This is where your HTML templates, CSS, and other static pages for the application view module will live. The default template for a Zinc application is called "plainjane".

 mkdir templates
 mkdir templates/plainjane
 vi templates/plainjane/wireframe.html

wireframe.html

<!DOCTYPE html
	PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
	 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US">
<head>
    <title>Crowd Keeper</title>
    <link rev="made" href="mailto:info%40cybersprocket.com" />
    <link rel="stylesheet" type="text/css" href="<%SELF(TemplateDir)%>site.css" />
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
</head>
<body>
My first Zinc Application.
</body>
</html>

Build the launcher

The launcher is your index.pl file that defines whether you'll use the default Act, Memory, and View classes of Zinc or your extended (custom) versions of each. It also kicks off any action processing as well as rendering your pages. A simple launcher is listed below:

#!/usr/bin/perl -w
use lib './';
use Zinc::Director;
use lib './zincmods/';
use MyView;
use MyAct;
my $Director    = new Zinc::Director(
                            CodeStart   => '<<',
                            CodeEnd     => '>>',
                            DBName      => 'my_postgres_db',
                            DBUser      => 'my_username',
                            ViewModule  => 'MyView',
                            ActModule   => 'MyAct'
                            );
print $Director->{WebIO}->header;
$Director->Act;
$Director->Display('wireframe');
exit;

Create Your Data Structures

Rather than just jump right into PostgreSQL and start building your data structures, we prefer to take a more structured approach. Our approach stores the data definitions in a text file containing SQL commands. This allows us to easily modify our data structure and start over from scratch when we are done with our develompent.

Our naming convention is to create a file named current_schema.sql that always contains the data structure and initial data seeding elements for the CURRENT VERSION of the application. As the application ages we relegate the current_schema.sql to a relevant name such as v0.1.1_schema.sql to allow people to follow along with the ugprades.

Sometimes we include the "stepping stone" files that migrate people between versions. These files are often names things like "upgrade_v01.1_v0.1.2.sql" and contains all the SQL necessary to move an existing v0.1.1 installation to the v0.1.2 release.

Create The Data Structure Builder

mkdir ./data
vi ./current_schema.sql

current_schema.sql

--- Project: Crowd Keeper
--- Author: Cyber Sprocket Labs (www.cybersprocket.com), Lance Cleveland
--- Version: 0.1
--- (c) 2008 - All right reserved, worldwide.
--
--- Clean install schema
---

--- =======================================================================
--- Primary Tables
--- =======================================================================

---
--- TABLE: GROUPS
---
create table groups(
    grp_id     serial      NOT NULL PRIMARY KEY,
    grp_name   char(50)    NOT NULL UNIQUE CHECK (grp_name <> '')
);

---
--- TABLE: USERS
---
create table users(
    user_id     serial      NOT NULL PRIMARY KEY,
    user_name   char(50)    NOT NULL UNIQUE CHECK (user_name <> ''),
    user_pwd    char(50)    NOT NULL CHECK (user_pwd <> '')
);

--- =======================================================================
--- Mapping Tables
--- =======================================================================

---
--- TABLE: GROUPUSERS
--- Attach users to 1..n groups
---
create table groupusers(    
    gu_id     serial        NOT NULL PRIMARY KEY,
    gu_grp_id int           NOT NULL
                                REFERENCES groups(grp_id) ON DELETE CASCADE,    
    gu_user_id int          NOT NULL
                                REFERENCES users(user_id) ON DELETE CASCADE
);


--- =======================================================================
--- Views
--- =======================================================================
create view groupdetails as
  select * from groupusers 
     left join groups on groupusers.gu_grp_id = groups.grp_id
     left join users on groupusers.gu_user_id = users.user_id
     ;

Create The Database

If your database creation commands in the SQL file are "clean" the final command will create your tables, views, etc. for your application. These commands assume you have already setup your PostgreSQL users.

# psql -U<username> template1
template1=> create database <your_db_name>;
template1=> \c <your_db_name>
template1=> \i ./schema-current.sql

Tips & Tricks

Database Interaction

Name your data connections

Synopsis

Naming statement handles when doing various selects and/or updates is important.

The underlying Postgres::Handler does some special caching stuff that causes primary keys to stomp all over each other if you’re not careful.

The best way to avoid issues is to simply name all of your statement handles. It actually allows Zinc to run more efficiently.

Details

  • Look at the examples below for a sample code segment and corresponding template.
  • If the ListPeople function does not used a named data handle it stomps all over ListThings and vice-versa causing odd results.
  • If you don't do this then subsequent view commands might fail.

Example

Code

   sub ListPeople {
      my $cmd     = "SELECT * FROM people WHERE person= ".$pid;                            
      $self->Memory->PrepLEX( -cmd=>$cmd, -name=>'person');
   }
   sub ListThings {
      my $cmd     = "SELECT * FROM things WHERE thing=".$tid;                            
      $self->Memory->PrepLEX( -cmd=>$cmd, -name=>'thing');
   }

Template

  <h1>This is my template page.</h1>
  Show a list of people:<br>
  Z_ListPeople_Z
 
  Show a list of things:<br>
  Z_ListThings_Z
Personal tools
Cyber Sprocket Labs
Cyber Sprocket Tech