[Catalyst] Best Practices - an application.

mnichols at mojosoft.org mnichols at mojosoft.org
Mon Sep 18 06:35:13 CEST 2006

Matt S Trout <dbix-class at trout.me.uk> writes:

> http://search.cpan.org/dist/DBIx-Class/lib/DBIx/Class/Relationship.pm#many_to_many
> so if your $system has a many-many called users you can use add_to_users to 
> add an entry or set_users(\@users) to set the full list at once.
> DBIx::Class was designed to support composite primary, foreign and unique keys 
> from the start, so you'll find they work fine.

Thanks for that.  I will dig into this in a bit, first I want to be able to add a system. 


I create a view, a model and a controller. Sorry everyone this from memory, I had to switch computers,  the environment isn't quite right there yet.... if I get something wrong, I'm sure someone will catch it. 

$ ./script/dmu_create.pl View TT TT;

$ ./script/dmu_create.pl Controller Servers

$ ./script/dmu_create.pl model DMU DBIC::Schema Schema::DMU create=static 'dbi:mysql:database=DMU;host=localhost' cat xxxxxxxxx

I edit my Root.pm default : Private routine.... this results in an error on the page.


sub default : Private {
    my ( $self, $c ) = @_;

    # Hello World
#           $c->response->body( $c->welcome_message );


.... this results in an error on the page - http://localhost:3000/:

Couldn't render template "file error - default: not found" which is
fine for now.

I add the following function too allow me to get back to the welcome
message in catalyst.  Might I suggest doing this by default in
Root.pm.  I don't know if this would be considered best practice but
it's provides a nice anchor so long as you don't flub it so bad you
can't start your test server.
sub Help : Local { my ( $self, $c ) = @_;
   # Hello World
   $c->response->body( $c->welcome_message );

http://localhost:3000/help brings up the original welcome page. 

Moving right along,  I make the following changes in ./lib/dmu/Controller/Servers.pm

sub index : Private {
    my ( $self, $c ) = @_;
    #$c->response->body('Matched DMU::Controller::Servers in Servers.');

I give the template the name servers.tt to distinguish it from the
next controllers index... but perhaps if I were better I'd only need
one index.tt, but alas I'm only a level 2 catalyst user, with a +5 editor. 

So finally some meat... servers.tt index needs to display all the
servers in the db in a way that they can be edited as well as a button
to add new ones.  

A bit of design discussion here warrants.  From here my lack of
knowledge on the ajax stuff really shines.  I could do this with some
basic forms, but instead want to use ajax.  I can see some real value
to the ability to drag and drop users later, and comet like actions
when we ever get to heavy lifting with the db.  So I want to hurt
myself on this simple part first to get it over with.  I've selected
dojo as it seems to be much lower level and broader then prototype.
And as much as it will hurt for me to learn something other then perl,
I do believe I have to, and I don't want to get stuck half way
through.  I'm of course open to other suggestions especially if they
mean simply using a perl class.


servers.tt:  is as follows. 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

  <meta name="GENERATOR" content="Quanta Plus">
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 [% PROCESS style.tt %]
  <script language="javascript" type="text/javascript">
  // <!--
  // -->
<script type="text/javascript" src="/static/dojo/dojo.js"></script>
<script type="text/javascript" src="/static/javascript/dmu.js"></script>
<div id="content">
<div id="answers">
<div id="tabs">
   [% IF c.stash.message %]
    <p> [% c.stash.message %]</p>
   [% END %]

<form name="myform" id="myform" action="[% c.req.uri%]" method="post" >
        [% WHILE (systems = c.stash.servers.next) %]
<div> <button dojoType="Button" widgetId="AddServerButton">New Server</button> </div>
<div dojoType="Input" widgetId="ServerName" >Please enter your name: <input type="text" id="name"></div>




For consistencies sake I include the style.tt and dmu.js file.  I like
putting the javascript into a .js file as my editor then plays better
with it. tabs,colors etc.  Plus I just like keeping it all
separate. Unfortunately this will cause a problem a bit later when I
want to stash stuff back to the .js file... but until now that hasn't
presented it's self so I'm not worrying about it and I believe I can
configure TT plug stuff into my .js too... Here is my style.tt (much
of which was shamelessly lifted off the welcome page, and then a bit
of other stuff that was lifted right off mysql's home page. Most of it
used, it's primarily used for a tab bar in a different project.  I
think the big problem for me was that catalyst dragged me out of the
world perl only, into css, javascript and beyond CGI.  This learning
curve has been steep.  But I'm glad this framework was there though
thanks to those who created it.


  o Note to make this work I installed HTML::Dojo and the catalyst
    helper: Catalyst:Helper:Dojo and ran:
$./script/dmu_create.pl Dojo kitchen_sink, this isn't necessary I think you can just download it. 
created "/home/mnichols/mnt/usb/homework/mdev/dmu/script/../root/static/dojo/src"
created "/home/mnichols/mnt/usb/homework/mdev/dmu/script/../root/static/dojo/src/rpc"
created "/home/mnichols/mnt/usb/homework/mdev/dmu/script/../root/static/dojo/src/validate"

Which results in altogether to much output to place here. I think best practice would pick a better Dojo "edition". 

  o I also had to tweak my Template config to make it pick up dojo's
    .html files by default Template only picks up .htm .  So in 
    ./lib/DMU.pm I do the following  
    I replace: 
    __PACKAGE__->config( name => 'DMU');


    __PACKAGE__->config( name => 'DMU',     
		   static=>{ignore_extensions=>[qw /tmpl tt tt2 xhtml/]}

    Which effectively allows .html pages. 

So finally in 


// dmu javascript functions etc.

// Load event to connect an event to the widget below
// Load Dojo's code relating to widget managing functions

// Load Dojo's code relating to the Button widget

function SubmitServerPressed() 
  //   alert("HELLOW WORLD ");
     url: 'add_server',
        handler: addServerCallback,
        content: {name: "WHAT" }

function AddServerPressed() 
   var server = dojo.widget.byId("ServerName");


function addServerCallback(type, data, evt)
  if (type == 'error')
    alert('Error when retrieving data from the server!');

function init()
  var link = dojo.widget.byId("AddServerButton");
  dojo.event.connect(link, "onclick", 'AddServerPressed');


Well if your still with me all this amounts to one shiny button on a
catalyst page:-( But if you dig into the above code you'll see I'm
chomping at the bit to add fancy javascript and ajaxian calls (if only
I knew how:-).  I hope in the next email to get into to some of this.  I
will post a couple of questions.  Am I doing something wrong? Is there
an easier way?  I've toyed with HTML::Widgets, but had too much else
to learn.  If someone has some any help that would be great: For
example, someone might reply: This interface you're desiring is simple
just include this, write these three lines, add this, get this module
and your done. I would greatly appreciate that.

I think I want a ajax call back to the server that adds a form, once
all the proper fields primary are filled in a submit button becomes
enabled and the person can submit this and it becomes a record in the
database. This may be high lighting a desire to do less client side
programming that showed up in an above thread.



PS, as usual no time to edit or re read.... 

More information about the Catalyst mailing list