[Cascavel-pm] Catalyst: Dispatching

Ednardo Lobo ednardo em lobo.eti.br
Sexta Maio 21 07:27:51 PDT 2010


Nilson Santos Figueiredo Jr. escreveu:
> 2010/5/20 Ednardo Lobo <ednardo em lobo.eti.br>:
>> 1) Class::DBI
> 
> Primeira importante dica: troque o Class::DBI por DBIx::Class. É uma
> solução bem mais moderna, robusta e bem suportada pela comunidade.

Se o DBIx::Class é mais adequado ao Class::DBI, trocarei com prazer.


>> Minha maior dificuldade no momento é com relação ao mapeamento de URLs em
>> "actions" (dispatching), cuja a metodologia ainda não compreendi bem. Em
>> razão disso não sei ao certo qual a melhor forma de estruturar os
>> "Controllers" e as "actions" dentro deles.
> 
> Esse conhecimento vem com o tempo.
> Você já leu as manpages adequadas, pelo que disse. Então o que falta
> mesmo é colocar a mão na massa.

Já estou com o Catalyst instalado e realizando testes. :-)


> Uma maneira fácil e que funciona bem (ao menos inicialmente) é tentar
> criar controllers para cada uma das entidades sobre as quais ocorrerão
> ações em seu sistema.
> Vamos supor que seu sistema tenha "Clientes" e "Pedidos de Compra".
> Então você teria um controller para cada um dos dois. Esses
> controllers, por sua vez, teriam ações como "create", "view",
> "update", "delete" (e ações adicionais que se mostrem necessárias).

Costumo organizar meu código mais ou menos da seguinte forma:

1) Package::MyApp::Cliente

Métodos globais para manipulação de clientes.

- get

Acessa o banco e obtém dados do cliente.

Usado em: Mod, Rmv e Prt

- valid

Valida dados que vão para o banco.

Usado em: Add, Mod, Rmv e Prt


2) Package::MyApp::Cliente::Lst

Lista, em páginas, todos os clientes.


3) Package::MyApp::Cliente::Add

Adiciona um cliente.


4) Package::Myapp::Cliente::Mod

Modifica cliente selecionado da lista.


5) Package::Myapp::Cliente::Rmv

Remove cliente selecionado da lista.


6) Package::Myapp::Cliente::Prt

Imprime/Mostra cliente selecionado da lista.


Todos esses métodos respondem à requisições e ao final geram um HTML que 
é enxertado em outro (HTML base) através de Package::Myapp.

Pelo que venho estudando essa metologia vai de encontro com as técnicas 
de engenharia usadas no Catalyst.

No caso do meu framework o fluxo de execução é da seguinte forma:

- Modificando cliente

URL: ?func=cliente&ope=mod&id=3

Execução: MyApp -> MyApp::Cliente -> MyApp::Cliente::Mod -> do(3)

Porém, no Catalyst, não consegui ainda compreender muito bem como seria 
esse fluxo de execução que, no caso, é orquestrado pelo DISPATCHING. Mas 
imagino que seria assim:

URL: /cliente/mod/3 ou /cliente/3/mod

Execução: MyApp::Cliente -> mod(3) ou MyApp::Cliente::Mod -> do(3)


DÚVIDAS:

1) Como enxertar o HTML da operação específica no HTML base?

2) Atribuir a View para, digamos, $c->stash->{enxerto} é o melhor caminho?

3) É possível executar isto de forma implícita, ou seja, se nada ao 
contrário for dito o resultado do processamento da View vai direto para 
$c->stash->{enxerto}.


> Como você já leu sobre o Chained, vou colocar abaixo um padrão que eu
> costumo usar, que acho bom. Basicamente, em cada um dos controllers,
> existirá uma ação "base" que serve como "âncora" para o controller,
> alé disso existirá uma ação "load" que carrega aquela entidade e as
> outras ações que precisam dela carregada serão encadeadas nesse ponto.
> De antemão já peço pra desculpar qualquer erro de sintaxe, pois estou
> escrevendo diretamente no email.
> 
>   package MyApp::Controller::PurchaseOrder;
> 
>   sub base : Chained ('.') CaptureArgs( 0 ) {
>       # lógica que vai ser executada para cada ação nesse controller
>   }
> 
>   sub load : Chained ('base') CaptureArgs(1) {
>       my ($self, $c, $id) = @_;
>       # carrega o elemento do banco de dados
>       $c->stash->{purchase_order} =
> $c->model('Schema::PurchaseOrder')->find( $id );
>   }
> 
>   sub view : Chained('load') Args(0) PathPart('') {
>       # aqui o $c->stash->{purchase_order} já estará disponível
>   }
> 
>   sub delete : Chained('load') Args(0) PathPart('delete') {
>       my ($self, $c) = @_;
>       $c->stash->{purchase_order}->delete;
>   }
> 
>   sub create : Chained('base') Args(0) PathPart('create') {
>       # essa é encadeada no 'base' então o purchase_order não está disponível
>   }
> 
> E aí, no seu controlador Root, coloca algo assim, para cada um dos
> controladores usando esse esquema:
>
>   package MyApp::Controller::Root;
> 
>   sub purchaseorder : Chained('/') PathPart('purchaseorder') {}

Não compreendi a necessidade desta linha em ::Root?


> Dessa maneira, no final das contas você vai ter as seguintes URLs:
> 
>   /purchaseorder/123 -> view item 123
>   /purchaseorder/123/delete -> delete item 123
>   /purchaseorder/create -> create
> 
> Existem módulos na CPAN que meio que automatizam essa tarefa de crirar
> aplicações em estruturas similares, mas como você está aprendendo,
> experimentar com o que eu postei acima pode ajudar.

Irei experimentar sim, mas poderia indicar um desses módulos?


Grato,

-- 
     Ednardo Lobo

     www.lobo.eti.br


Mais detalhes sobre a lista de discussão Cascavel-pm