[SP-pm] Catalyst: Começando...

Thiago Rondon thiago at aware.com.br
Wed Feb 4 04:36:29 PST 2009


Sim, para um aplicativo real, esta seria uma boa maneira de aplicar o 
Chained. Que tal um documento
sobre praticas de utilização de URI/Chained com o Catalyst ?

Mais um pouco, você poderia transformar um texto para adicionarmos no 
wiki também !

No exemplo que coloquei no texto, é realmente pratico, fast-food, não vi 
necessidade de criar um base
no Root.pm.

-Thiago Rondon

Lindolfo "Lorn" Rodrigues escreveu:
> Você pode mudar isso para Chained Action:
>
> sub index :Path :Args(0) {
> 	my ($self, $c) = @_;
> 	
> 	$c->res->redirect(
> 	$c->uri_for(
> 	$c->controller->action_for('list')
> 	)
>
> 	);
> }
>
> sub root : Chained('base') Args(0) {
>         my ($self, $c) = @_;
> 	$c->res->redirect(
> 	$c->uri_for(
> 	$c->controller->action_for('list')
> 	)
> 	);
> }
>     
>
> # Essa parte do Controller Telefone, pode ficar assim:    
>
> - sub base :Chained('/') CaptureArgs(0) PathPart('telefone') {
> + sub base :Chained('/base') CaptureArgs(0) PathPart('telefone') {
>
>
> Para isso preciso disso no Controller Root.pm, eu acho que assim fica mais "extensivel" sua agenda.
>
> Root.pm
>
> sub base : Chained('/') CaptureArgs(0) PathPart('') {}
>
> sub root : Chained('base') PathPart('') Args(0){
>
>          my ($self, $c) = @_;
>          # Quando o usuario acessar localhost:3000/ vai ser redirecionado para localhost:3000/telefone, pois é 
>          # a unica parte da agenda que está pronta 
>          $c->res->redirect('/telefone');
>
> }
>
> Usando Chained Action a partir do Root.pm, você consegue controlar coisas desse tipo:
>
> sub favicon : Chained('base') PathPart('favicon.ico') Args(0) {
>           my ($self, $c) = @_;
>           # coloque aqui o codigo para servir o favicon.ico de sua prefrencia
>
> }
>
> sub error_404 : Chained('base') PathPart('') Args {
>          my ($self, $c) = @_;
>          $c->response->body( 'Page not found' );
>          $c->response->status(404);
>
>
>      
> }
>
> O CODIGO ACIMA NÃO FOI TESTADO :)
>   
>
> 2009/2/4 Thiago Rondon <thiago em aware.com.br <mailto:thiago em aware.com.br>>
>
>
>     Espero continuações... oops, contribuições. :)
>
>     -Thiago Rondon
>
>     Blabos de Blebe escreveu:
>
>         Muito bom. Gostei das explicações nos comentários. Vai ter
>         continuação? Espero que sim.
>
>         Parabéns
>
>         2009/2/3 Daniel de Oliveira Mantovani
>         <daniel.oliveira.mantovani em gmail.com
>         <mailto:daniel.oliveira.mantovani em gmail.com>>:
>          
>
>             Valeu Thiago!
>             2009/2/3 Nelson Ferraz <nferraz em gmail.com
>             <mailto:nferraz em gmail.com>>
>                
>
>                 Parece muito bom, Thiago! Obrigado pela contribuição!
>
>                 Por que não formata o documento em pod, e copia para o
>                 wiki? Aqui vai um
>                 começo:
>
>                 =head1 NOME
>
>                 Catalyst - O Elegante framework de programação Web em
>                 Perl.
>
>                 =head1 DESCRICAO
>
>                 Catalyst é um framework elegante de programação MVC
>                 para Web em Perl
>                 (ambos gratuitos e de código aberto). Este tutorial
>                 simples e talvez muito objetivo tem como missão
>                 facilitar o
>                 entedimento para os novos nesta ferramenta de forma
>                 pratica, não
>                 se prendendo muito a conceitos, motivos e paradigmas.
>
>                 =head1 INICIO
>
>                 =head2 Instalação do Catalyst.
>
>                 O Perl tem o CPAN, no qual é um repositorio farto de
>                 modulos e
>                 documentação, você pode utilizar o site
>                 http://search.cpan.org/ para
>                 navegar por ele, e toda distribuição do Perl vem com
>                 um aplicativo
>                 chamado "cpan" para você poder instalar os modulos
>                 atravez da
>                 linha de comando.
>
>                   $ export PERL_MM_USE_DEFAULT=1
>                   $ cpan -i Task::Catalyst
>
>                 O Catalyst tem algumas dependencias, e por isto, além
>                 do pacote do
>                 Catalyst o "cpan" irá automaticamente instalar as suas
>                 dependencias,
>                 perceba que estamos utilizando o pacote
>                 Task::Catalyst, no qual contém
>                 uma serie de pacotes recomendadas para a utilização do
>                 Catalyst.
>
>                 DICA: Sete a variavel de ambiente
>                 PERL_MM_USE_DEFAULT=1 para o cpan
>                 não lhe questionar sobre as dependencias e demais
>                 perguntas, e
>                 instalar elas sem lhe perguntar.
>
>                 Pronto, a instalação esta concluida, agora estamos com
>                 o sistema apto
>                 para programar utilizando o framework de programação
>                 Catalyst.
>
>                 =head2 Iniciando o meu primeiro projeto.
>
>                 No pacote do Catalyst, vem acompanhando um aplicativo
>                 que facilita a
>                 nossa vida para montar o ambiente básico para
>                 iniciarmos o nosso
>                 projeto, chamado de "catalyst.pl", para isto basta
>                 executar ele com o
>                 primeiro argumento sendo o nome do projeto.
>
>                   $ catalyst.pl webapp
>                   created "webapp"
>                   created "webapp/script"
>                   created "webapp/lib"
>                   created "webapp/root"
>                   created "webapp/root/static"
>                   created "webapp/root/static/images"
>                   created "webapp/t"
>                   created "webapp/lib/webapp"
>                   created "webapp/lib/webapp/Model"
>                   created "webapp/lib/webapp/View"
>                   created "webapp/lib/webapp/Controller"
>                   created "webapp/webapp.conf"
>                   created "webapp/lib/webapp.pm <http://webapp.pm>"
>                   created "webapp/lib/webapp/Controller/Root.pm"
>                   created "webapp/README"
>                   created "webapp/Changes"
>                   created "webapp/t/01app.t"
>                   created "webapp/t/02pod.t"
>                   created "webapp/t/03podcoverage.t"
>                   created "webapp/root/static/images/catalyst_logo.png"
>                   created "webapp/root/static/images/btn_120x50_built.png"
>                   created
>                 "webapp/root/static/images/btn_120x50_built_shadow.png"
>                   created
>                 "webapp/root/static/images/btn_120x50_powered.png"
>                   created
>                 "webapp/root/static/images/btn_120x50_powered_shadow.png"
>                   created "webapp/root/static/images/btn_88x31_built.png"
>                   created
>                 "webapp/root/static/images/btn_88x31_built_shadow.png"
>                   created
>                 "webapp/root/static/images/btn_88x31_powered.png"
>                   created
>                 "webapp/root/static/images/btn_88x31_powered_shadow.png"
>                   created "webapp/root/favicon.ico"
>                   created "webapp/Makefile.PL"
>                   created "webapp/script/webapp_cgi.pl"
>                   created "webapp/script/webapp_fastcgi.pl"
>                   created "webapp/script/webapp_server.pl"
>                   created "webapp/script/webapp_test.pl"
>                   created "webapp/script/webapp_create.pl"
>
>                 Pronto, agora estamos com nosso ambiente básico para
>                 começar a
>                 programar, vou explicar de forma rápida a estrutura
>                 de diretorios criada para você entender melhor:
>
>                   $ ls webapp/
>                   Changes  lib/  Makefile.PL  README  root/  script/
>                  t/  webapp.conf
>
>                 Veja, que temos quatro diretorios, que são eles:
>
>                 =over
>
>                 =item lib/
>
>                 Contém a parte da programação lógica, onde iremos
>                 escrever nossos
>                 modulos e códigos em Perl.
>
>                 =item root/
>
>                 Neste diretorio iremos colocar arquivos estáticos,
>                 como templates,
>                 javascript e css.
>
>                 =item script/
>
>                 Scripts para inicializar a nossa aplicação.
>
>                 =item t/
>
>                 Testes para nossa aplicação.
>
>                 =back
>
>                 Vamos falar um pouco do diretorio "script/", nele você
>                 tem um script
>                 que usaremos muito neste tutorial, webapp_server.pl, no
>                 qual irá iniciar um servidor http na porta 3000 por
>                 padrão, para
>                 visualizarmos o nosso aplicativo:
>
>                   $ script/webapp_server.pl
>
>                 Depois de executar ele, você já pode acessar o
>                 aplicativo pelo seu
>                 browser favorito, pelo endereço:
>
>                 L<http://localhost:3000>
>
>                 =head2 Entendendo um MVC (Model-View-Controller)
>
>                 MVC é um padrão de arquitetura de software, uma das
>                 maiores
>                 dificuldades do entendimento de um framework de
>                 programação
>                 web como o Catalyst para os iniciantes é justamente
>                 este conceito.
>
>                 Basicamente o significado deles é:
>
>                 =over
>
>                 =item Model:
>
>                 São as informações utilizadas pelo aplicativo, no qual
>                 este modelo
>                 pode ser um banco de dados, um arquivo texto e etc.
>
>                 =item Controller:
>
>                 Lógica do nosso aplicativo, onde podemos por exemplo
>                 alterar as
>                 informações (Model), filtrar e etc.
>
>                 =item View:
>
>                 Renderizar o Model e o Controller para o usuário, ou
>                 seja como o
>                 aplicativo será apresentado.
>
>                 =back
>
>                 Esta é uma forma rápida de apresentar os três
>                 componentes do MVC,
>                 sabendo disto, vamos começar a produzir nosso aplicativo.
>
>                 =head2 Nosso projeto: Agenda telefonica
>
>                 Vamos começar a estudar o nosso aplicativo, ele irá
>                 gerenciar uma
>                 lista de telefones, no qual iremos efetuar um simples
>                 "CRUD"
>                 (Create-Remove-Update-Destroy), no qual iremos
>                 permitir efetuar a
>                 criação, remover, atualizar e apagar dados de nossa lista.
>
>                 Vamos projetar nossa agenda telefonica, utilizando o
>                 MVC da seguinte da
>                 forma:
>
>                 =over
>
>                 =item Model:
>
>                 Iremos utilizar o MySQL, porém para efetuar a
>                 conectividade com o
>                 banco de dados, iremos utilizar um driver do DBI, no
>                 qual o MySQL e tantos outros ele suporta, e é
>                 interessante além de
>                 utilizar o driver de comunicação com o banco de dados,
>                 algum
>                 ORM
>                 (http://en.wikipedia.org/wiki/Object-relational_mapping)
>                 para
>                 facilitar a interface com o DB, existem alguns
>                 disponiveis como
>                 por exemplo o Class::DBI ou DBIx::Class para evitar
>                 que você escreva
>                 SQL no teu código, evitar alguns bugs e trazer
>                 agilidade no
>                 desenvolvimento, no nosso caso iremos utilizar o
>                 DBIx::Class.
>
>                 =item View:
>
>                 Iremos utilizar o HTML como formato de apresentação
>                 para nossos
>                 usuarios, portanto teremos que carregar o modulo que
>                 cuidará de manipular os dados que iremos jogar em
>                 nosso arquivo de
>                 template, existem alguns modulos disponiveis como o
>                 HTML::Manson ou Template::Toolkit), iremos utilizar
>                 neste caso o
>                 Template::Toolkit.
>
>                 =item Controller:
>
>                 Aqui é o lugar onde iremos programar, captar os dados
>                 no Model e
>                 "espirrar" para a View, entre outras.
>
>                 =back
>
>                 =head2 Começando pelo Model.
>
>                 Bem, já dissemos que iremos utilizar o MySQL como
>                 banco de dados, e
>                 também já explicamos por que iremos utilizar o
>                 DBIx::Class.
>
>                 Precisamos instalar ele:
>
>                   $ cpan -i DBIx::Class
>
>                 Certo, agora temos tudo o que precisamos para
>                 trabalhar com o nosso
>                 Model. Neste tutorial eu vou utilizar o exemplo de criar a
>                 tabela direto pelo client do MySQL, e depois ler elas
>                 pelo DBIx::Class.
>
>                   mysql> create database webapp
>                   mysql> grant all on webapp.* to webapp em localhost
>                 identified by
>                 'webapp';
>                   mysql> flush privileges;
>                   mysql> create table telefones (
>                       id int not null auto_increment,
>                       nome varchar(255),
>                       telefone varchar(255),
>                       primary key(id));
>
>                 Criado a nosso database e nossa tabela, agora vamos
>                 para "importar"
>                 nosso banco de dados para o DBIx::Class, eu não irei me
>                 aprofundar no DBIx::Class neste tutorial, pois não é o
>                 objetivo dele.
>
>                 Para importarmos este database para os schemas que o
>                 DBIx::Class
>                 utiliza, iremos executar um dos scripts facilitadores
>                 do diretorio
>                 scripts/ que se chama "webapp_create.pl" no qual
>                 facilita algumas
>                 tarefas como esta, a sintaxe utilizada é
>                 auto-explicativa, é
>                 basicamente:
>
>                   # script/webapp_create.pl model DB DBIC::Schema
>                 webapp::Schema
>                 create=static dbi:mysql:dbname=webapp webapp webapp
>                   exists "/home/thiago/webapp/script/../lib/webapp/Model"
>                   exists "/home/thiago/webapp/script/../t"
>                   Dumping manual schema for webapp::Schema to directory
>                 /home/thiago/webapp/script/../lib ...
>                   Schema dump completed.
>                   created
>                 "/home/thiago/webapp/script/../lib/webapp/Model/DB.pm"
>                   created "/home/thiago/webapp/script/../t/model_DB.t"
>
>                 Vejamos os argumentos deste script:
>
>                 =over
>
>                 =item model
>
>                 Estamos criando um model para o script webapp_create.pl
>
>                 =item DB
>
>                 O nome criado para este modem será DB (vide
>                 lib/webapp/Model/DB.pm)
>
>                 =item DBIC::Schema
>
>                 Nome do helper para criar o Schema para o DBIx::Class
>
>                 =item create=static
>
>                 Significa que o schema será estatico, ou seja, a toda
>                 alteração nas
>                 tabelas, você precisa atualizar nos arquivos criados
>                 para o schema.
>
>                 =item dbname
>
>                 Nome do database no MySQL.
>
>                 =item webapp
>
>                 Usuario para se conectar no banco.
>
>                 =item webapp
>
>                 Senha para se conectar no banco.
>
>                 =back
>
>                 Agora, de uma lida nos arquivos criados em
>                 lib/webapp/Schema/* e
>                 lib/webapp/Model/*
>
>                 Pronto, já temos o nosso Model pronto para o nosso
>                 aplicativo.
>
>                 =head2 View - Template Toolkit.
>
>                 Iremos utilizar neste exemplo a Template::Toolkit,
>                 iremos utilizar um
>                 helper da mesma maneira que
>                 usamos para o banco de dados:
>
>                   # script/webapp_create.pl view TT TT
>                   exists "/home/thiago/webapp/script/../lib/webapp/View"
>                   exists "/home/thiago/webapp/script/../t"
>                   created
>                 "/home/thiago/webapp/script/../lib/webapp/View/TT.pm"
>                   created "/home/thiago/webapp/script/../t/view_TT.t"
>
>                 Pronto, o helper já criou os arquivos necessarios para
>                 utilizarmos a
>                 Template Toolkit em nosso projeto.
>
>                 =head2 Controller - Agora sim, programando!
>
>                 Estamos na melhor parte, é onde tudo acontece, iremos
>                 criar 4 actions,
>                 para criar, remover, listar e editar.
>
>                 Eu irei colocar o código que utilizei, e com ele
>                 comentado explicando
>                 passo-a-passo do que estou
>                 fazendo nele. Não irei utilizar nenhum helper ou
>                 facilitador nesta
>                 parte, pois acredito que a melhor maneira
>                 de se desenvolver o Controller é na 'unha'.
>
>                 Iremos criar um arquivo
>                 lib/webapp/Controller/telefone.pm
>                 <http://telefone.pm>, no qual ele
>                 irá representar na URI "/telefone".
>
>                 Caso queira baixar todos os arquivos, clique aqui.
>
>                   package webapp::Controller::telefone;
>
>                   use strict;
>                   use warnings;
>                   use parent 'Catalyst::Controller';
>
>                   # Nos estamos utilizando um mecanismo muito
>                 interessante neste
>                   # exemplo, que recomendo a utilizacao, o Chained.
>                   # Não iremos entrar discutir sobre ele, porem ele ajuda
>                   # manusearmos os argumentos passados pela URI.
>                   # Por tanto, vamos criar uma rotina "base" no qual
>                 todas as
>                   # requisições passaram por ela (Chained()).
>                   #
>                 search.cpan.org/dist/Catalyst-Runtime/lib/Catalyst/DispatchType/Chained.pm
>                 <http://search.cpan.org/dist/Catalyst-Runtime/lib/Catalyst/DispatchType/Chained.pm>
>
>                   sub base :Chained('/') CaptureArgs(0)
>                 PathPart('telefone') {
>                       my ($self, $c) = @_;
>
>                       # stash é o local onde iremos colocar
>                 informações para compartilhar
>                       # com outras partes do nosso aplicativo, para
>                 cada requisição o
>                 stash
>                       # tem uma vida.
>                       # No caso, abaixo estamos atribuindo ao
>                 "collection" no stash o
>                 nosso
>                       # model "DB::telefones", que corresponde a nossa
>                 tabela telefones
>                 que
>                       # criamos no MySQL.
>
>                       $c->stash->{collection} =
>                 $c->model('DB::telefones');
>                   }
>
>
>                   # Veja, aqui estamos criando uma URI list/, no qual
>                 ela esta
>                 vinculada a nossa
>                   # função base, criada anteriormente (Chained('base')),
>                   #
>                   # Ou seja, para chamar a URL,
>                 http://localhost:3000/telefone/list,
>                 primeiramente
>                   # ele vai passar na base e depois na list. (* E por
>                 último, neste
>                 nosso exemplo
>                   # na action end do Root.pm, no qual nem iremos
>                 comentar neste
>                 tutorial).
>                   #
>                   # Veja que estamos dizendo Args(0), isto significa
>                 que não preciso de
>                 nenhum
>                   # elemento extra na minha URI, sempre que esta
>                 action for requisitada,
>                 será
>                   # /telefone/list
>
>                   sub list :Chained('base') Args(0) {
>                       my ($self, $c) = @_;
>
>                       # "req" ou "request" são as informações que
>                 estão no request da
>                       # requisição, e no qual temos o metodo param que
>                 retorna o valor
>                       # do atributo que gostariamos.
>                       my $key = $c->req->param('key') || "";
>
>                       # Aham, aqui estamos utilizando o DBIx:Class,
>                 repare que não iremos
>                       # escrever nenhum um código de SQL aqui, veja
>                 abaixo que iremos
>                       # utilizar uma função search_like(), no qual
>                 iremos procurar pelo
>                       # elemento $key nos dois campos (nome,
>                 telefone), estou usando o
>                       # $key, caso o usuario queira procurar por
>                 alguma palavra chave.
>                       my $items = $c->stash->{collection}->search_like({
>                       nome => "\%$key\%",
>                       telefone => "\%$key\%"
>                       });
>
>                       # Aqui estou colocando no stash o key, para
>                 mostrar na View por
>                 qual
>                       # palavra o usuario esta procurando, e o items
>                 encontrados.
>                       $c->stash->{key} = $key;
>                       $c->stash->{items} = $items;
>                   }
>
>                   # Esta função é para remover uma determinada coluna
>                 do nosso banco de
>                 dados,
>                   # repare que aqui estamos utilizando Args(1), ou
>                 seja estou esperando
>                 um
>                   # elemento na minha URI, além de /telefones/destroy,
>                 eu só irei acessar
>                 esta
>                   # URI, se acessar por /telefones/destroy/N, onde N é
>                 o ID do nosso
>                 item.
>                   # Veja que no código da função, estaremos novamente
>                 usando uma
>                 função do DBIx:Class,
>                   # primeiramente irei procurar por este elemento com
>                 find() e então
>                 irei remover
>                   # ele.
>
>                   sub destroy :Chained('base') :Args(1) {
>                       my ($self, $c, $id) = @_;
>                       my $row = $c->stash->{collection}->find({ id =>
>                 $id });
>                       $row->delete if $row;
>                   }
>
>                   # Aqui, iremos editar o nosso item, onde também
>                 esperamos um
>                 argumento, que é o id
>                   # do item, e iremos procurar ele.
>                   # Repare que aqui, eu faço uma verificação, onde
>                 quero saber se o
>                 metodo utilizado
>                   # para chamar esta requisição é POST, caso não seja
>                 eu vou
>                 "encarrar" (detach())
>                   # esta função e vou passar para a próxima função da
>                 cadeia. (end()
>                 no Root.pm, neste
>                   # caso).
>                   # Resumindo, se o usuário não apertou "ALTERAR" no
>                 html (no qual o
>                 form esta enviando
>                   # os dados via POST), eu irei mostrar a página com
>                 os dados do
>                 objeto N ($id).
>
>                   sub edit :Chained('base') :Args(1) {
>                       my ($self, $c, $id) = @_;
>
>                       my $row = $c->stash->{row} =
>                 $c->stash->{collection}->find({id =>
>                 $id});
>                       $c->stash->{template} = "telefone/create.tt
>                 <http://create.tt>";
>
>                       $c->detach() unless $c->req->method eq 'POST';
>
>                       # Caso o usuario, tenha apertado o submit do
>                 nosso form, para
>                 alterar os dados,
>                       # eu vou colocar eles em $parameters = {}, e vou
>                 mandar o $row
>                 (que é o objeto
>                       # do find()) para o metodo update().
>
>                       my $parameters;
>                       $parameters->{nome} = $c->req->param('nome');
>                       $parameters->{telefone} =
>                 $c->req->param('telefone');
>
>                       $row->update($parameters);
>
>                       # Agora, nao vou mandar ele para a mesma tela,
>                 vou enviar para
>                 uma template diferente.
>                       $c->stash->{template} = "telefone/edit_ok.tt
>                 <http://edit_ok.tt>";
>                   }
>
>                   # Esta rotina é bem parecida com a do edit, com a
>                 unica diferença,
>                 que ao invez de atualizar
>                   # eu vou inserir.
>
>                   sub create :Chained('base') :Args(0) {
>                       my ($self, $c) = @_;
>                       $c->detach() unless $c->req->method eq 'POST';
>
>                       my $parameters;
>                       $parameters->{nome} = $c->req->param('nome');
>                       $parameters->{telefone} =
>                 $c->req->param('telefone');
>
>                       my $row = $c->stash->{collection}->new($parameters);
>                       $row->insert;
>
>                       $c->stash->{template} = "telefone/create_ok.tt
>                 <http://create_ok.tt>";
>                   }
>
>                   # Caso, eu não especifique nada na URI de telefones,
>                 ou seja, acessar
>                   # http://localhost:3000/telefone eu irei
>                 redirecionar para a action
>                 list,
>                   # que já comentamos sobre ela.
>                   sub index :Path :Args(0) {
>                       my ($self, $c) = @_;
>
>                       $c->res->redirect(
>                       $c->uri_for(
>                       $c->controller->action_for('list')
>                       )
>                       );
>                   }
>
>                   1;
>
>
>                 Código pronto, porem precisamos das templates.
>
>                 Agora, crie estes arquivos no diretorio root/telefone:
>
>                 Este arquivo, é para a action "create", no qual é o
>                 nosso formulario
>                 para criar um item na nossa agenda.
>
>                 =head3 create.tt <http://create.tt>
>
>                   <h1>Criar</h1>
>
>                   <form method="POST">
>
>                   <table><tr><td>
>                   Nome:
>                   </td><td> <input type="text" name="nome" value="[%
>                 row.nome %]"
>                 size=20>
>                   </td></tr><tr><td>
>                   Telefone:
>                   </td><td> <input type="text" name="telefone" value="[%
>                 row.telefone %]" size=20>
>                   </td></tr><tr><td colspan="2">
>                   <center><input type="submit"></center>
>                   </td></tr></table>
>
>                   </form>
>
>                 Este arquivo é a mensagem depois da criação do item.
>
>                 =head3 create_ok.tt <http://create_ok.tt>
>
>                   <h1>Telefone inserido com sucesso!</h1>
>
>                 Mensagem para o item apagado.
>                 =head3 destroy.tt <http://destroy.tt>
>
>                   <h1>Telefone apagado</h1>
>
>                 Mensagem para item editado.
>
>                 =head3 edit_ok.tt <http://edit_ok.tt>
>
>                 <h1>Editado com sucesso.</h1>
>
>                 Listar itens da nossa agenda, e também dar ao usuário
>                 a opção de procurar
>                 neles.
>
>                 =head3 list.tt <http://list.tt>
>
>                   <h1>Listar</h1>
>
>                   <form>
>                   Procurar por:
>                   <input type="text" name="key" size="15">
>                   <input type="submit" value=" Procurar " >
>                   </form>
>
>                   [% IF key %]
>                   <br/>
>                   <b>Procurando por [% key %]</b>
>                   <br/>
>                   [% END %]
>
>                   <table><tr><td>
>                   <b>Nome</b>
>                   </td><td>
>                   <b>Telefone</td>
>                   </td><td>
>                   <b>A&ccedil;&atilde;o
>                   </td></tr>
>
>                   [% WHILE (item = items.next) %]
>                       <tr><td>
>                       [% item.nome %]
>                       </td><td>
>                       [% item.telefone %]
>                       </td><td>
>                       <a href="[% c.uri_for('edit', item.id
>                 <http://item.id>) %]">Editar</a>
>                       -
>                       <a href="[% c.uri_for('destroy', item.id
>                 <http://item.id>) %]">Remover</a>
>                       </td></tr>
>                   [% END %]
>
>                   </table>
>
>                 =head1 AUTOR
>
>                 Thiago Rondon <thiago em aware.com.br
>                 <mailto:thiago em aware.com.br>>
>
>                 =head1 COLABORADORES
>                 _______________________________________________
>                 SaoPaulo-pm mailing list
>                 SaoPaulo-pm em pm.org <mailto:SaoPaulo-pm em pm.org>
>                 http://mail.pm.org/mailman/listinfo/saopaulo-pm
>                      
>
>
>             --
>             http://mantovanihouse.blogspot.com/
>
>             -------(\_------------_/)-----------
>             -------)--(----------)--(-----------
>             ------(----(---------)----)----------
>             -------)----(-------)----(-----------
>             -------(----(-------)----)-----------
>             --------\_-(\\.---.//)-_/------------
>             ----------\)' -8--8- '(/--------------
>             -----------/------------\---------------
>             ----------(--)--------(--)--------------
>             ------------(_c__c_)----------------
>             ----------------------------------------
>
>             _______________________________________________
>             SaoPaulo-pm mailing list
>             SaoPaulo-pm em pm.org <mailto:SaoPaulo-pm em pm.org>
>             http://mail.pm.org/mailman/listinfo/saopaulo-pm
>
>                
>
>         _______________________________________________
>         SaoPaulo-pm mailing list
>         SaoPaulo-pm em pm.org <mailto:SaoPaulo-pm em pm.org>
>         http://mail.pm.org/mailman/listinfo/saopaulo-pm
>
>
>          
>
>
>     _______________________________________________
>     SaoPaulo-pm mailing list
>     SaoPaulo-pm em pm.org <mailto:SaoPaulo-pm em pm.org>
>     http://mail.pm.org/mailman/listinfo/saopaulo-pm
>
>
>
>
> -- 
> --Lindolfo "Lorn" Rodrigues
> www.slackwarezine.com.br <http://www.slackwarezine.com.br>
> http://lornlab.org
> http://sao-paulo.pm.org
> use Catalyst;
> ------------------------------------------------------------------------
>
> _______________________________________________
> SaoPaulo-pm mailing list
> SaoPaulo-pm em pm.org
> http://mail.pm.org/mailman/listinfo/saopaulo-pm



More information about the SaoPaulo-pm mailing list