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