desarrollo de aplicaciones web usando catalyst y jquery
Post on 16-Apr-2017
2.904 Views
Preview:
TRANSCRIPT
Javier E. Prez P.Noviembre 2007
Desarrollo de aplicaciones web usandoCatalyst y jQuery
Puntos a tratar
Qu es Catalyst?
Ventajas de su uso.
Requisitos de instalacin.
Creando un proyecto.
Estructura de proyecto.
Creacin de: Controlador, Modelo, Vista.
Agregando mdulos.
Conexin a base de datos (DBIC).
Trabajando con plantillas (TT, TTSite)
Trabajando con formularios (FormBuilder).
Uso de sessiones.
Autorizacin, autenticacin.
Depuracin.
Consejos.
Proyectos nacionales desarrollados usando catalyst.
Qu es Catalyst?
Framework Web escrito usando perl.
MVC.
Unicode.
Servidor de pruebas integrado.
Metodologa MVC
Modelo
De donde se almacenan los datos.
Generalmente base de datos.
Vista
La presentacin de los datos.
HTML, JSON, RSS, XML, etc.
Controlador
Quin maneja las transacciones entre la solicitud del usuario, el proceso y salida de informacin.
Catalyst itself
Ventajas de su uso
Ventajas de su uso
Despacho del URL, se trabaja por segmentos en vez de querystring's
Instalacin sencilla.
Estructura establecida de los directorios manteniendo un orden.
Est respaldado por la gran cantidad de mdulos que hospeda cpan.
Formularios
ORM's
Reportes
i18n
autenticatin, autorizacin.
etc.
Ventajas de su uso
Despacho del URL, se trabaja basado en segmentos en vez de querystring's.
http://www.google.com/search?hl=es&client=iceweasel-a&q=catalyst&btnG=Buscar
http://www.administracion.com/usuario?id=11222333&accion=eliminar
QueryString
http://www.google.com/search/lenguale/es/cliente/iceweasel-a/q/catalyst/Buscar
http://www.administracion.com/usuario/11222333/eliminar
Basado en segmentos (segment based)
use PDF::CreateSimple;
sub pdf : Local { my ($self,$c,$mensaje) = @_;
# Heredamos el mdulo como lo haramos con cualquier aplicacin CGI my $pdfFile = PDF::CreateSimple->new("root/reporte.pdf",undef,'LETTER'); # Pasamos algunos parametros (Esto no es catalyst, es perl) $pdfFile->drawText($mensaje,'Verdana',10,200,450,'black',3); $pdfFile->drawText('Generado con Catalyst','Verdana',10,200,400,'black',3); $pdfFile->drawImage('root/images/catalyst-logo.png',250,300); # esto no enva el pdf para descargar, sino que lo guarda en el disco $pdfFile->closeFile; # Ahora enviamos al navegador a que muestre el archivo recin guardado $c->res->redirect("/archivo.pdf");}Est respaldado por la gran cantidad de mdulos que hospeda cpan.
there's nothing magical about catalyst, it doesn't get in your way, it just dispatches urls to actions
Ventajas de su uso
Por supuesto, TIMTOWTDI
(There Is More Than One Way To Do It)
Instalacin
Paquetes en debian / ubuntu :
libcatalyst-perl
libcatalyst-modules-perl
Mdulos usando cpan:
Catalyst
El resto que se necesite.
Por ejemplo, en la shell: cpan CGI::FormBuilder
usar dh_make para convertir modulos de perl a paquetes debian y as instalarlos.
$ catalyst.pl proyecto
$ cd proyecto/
$ perl script/proyecto_server.pl
Creando un proyecto
Creamos proyecto
$ catalyst.pl proyecto
Nos cambiamos de directorio de trabajo al recien creado (nombre del proyecto)
$ cd proyecto
Corremos el servidor de pruebas
$ perl script/proyecto_server.pl
Estructura establecida de los directorios manteniendo un orden.
Creando controlador
perl script/sistap_create.pl controller unesco_area
lib/sistap/Controller/unesco_area.pm
package sistap::Controller::unesco_area;
use strict;use warnings;use base 'Catalyst::Controller';
sub index : Private { my ( $self, $c ) = @_;
$c->response->body('Hola mundo');}
sub saludo : Local { my ( $self, $c ) = @_;
$c->response->body('Hola mundo... de nuevo');}
1;http://localhost:3000/unesco_area/saludo
Controlador
Accin
Mtodos de despacho
Local (: Local {})
Reconoce el nombre de la accin como primer argumento del controlador.
Path (: Path('foo/bar') { })
Se especifica una ruta absoluta a despachar.
Global (: Global { })
Despacha el primer nivel (como si fuera controlador)
Private (: Private {} )
Especial para funciones reservadas en catalyst (default, index, begin, end, auto) , no es despachada por url.
sub saludo : Local { my ( $self, $c ) = @_; $c->res->body('dvst');}
Regex ( : Regex('^item(\d+)/orden(\d+)$') { } )
Despacha segn una expresin regular dada (en todo el sistema)
No usa ModRewrite para esto.
item4/orden243 es capturada con esa expresin.
LocalRegex ( : LocalRegex('^widget(\d+)$') { } )
Igual que Regex pero solo es interpretada en el controlador donde est definida.
widget23 es reconocido con la expresin del ejemplo.
Chained
Se realiza una cadea entre diferentes acciones
CaptureArgs() y Args()
Se combina con Chained para reconocer la cadena
Metodos de despacho
Chained / CaptureArgs() / Args()
sub wiki : PathPart('wiki') Chained('/') CaptureArgs(1) { my ( $self, $c, $page_name ) = @_; # carga la pgina de nombre $page_name y coloca el objeto en el stash $c->stash->{var1} = $page_name; }
sub rev : PathPart('rev') Chained('wiki') CaptureArgs(1) { my ( $self, $c, $revision_id ) = @_; # Usa el objeto de pgina que est en el stash y obtiene el nmero # de revisin $revision_id. $c->stash->{var2} = $revision_id ; }
sub view : PathPart Chained('rev') Args(0) { my ( $self, $c ) = @_; # Muestra la revisin de la pgina en pantalla,my $salida ;$salida = "Esta pantalla muestra la revision: " . $c->stash->{var2} ;$salida .= " de la pagina: " . $c->stash->{var1} ; $c->res->body($salida); }URL:http://localhost:3000/wiki/principal/rev/4/view
Salida por pantalla:
Esta pantalla muestra la revision: 4 de la pagina: principal
sub view : PathPart Chained('wiki') Args(0) { my ( $self, $c ) = @_; # Muestra la revisin de la pgina en pantalla,my $salida ;$salida = "Esta pantalla muestra la revision: " . $c->stash->{var2} ;$salida .= " de la pagina: " . $c->stash->{var1} ; $c->res->body($salida); }
Creando un modelo (DBIx::Class -> Catalyst::Model::DBIC::Schema)
Necesitamos esquema.
(archivo lib/sistapDB.pm)
package sistapDB;
=head1 NAME
sistapDB - DBIC Schema Class
=cut
# Nuetro esquema necesita heredar desde 'DBIx::Class::Schema'use base qw/DBIx::Class::Schema/;
# Se necesitan cargas las clases de modelo de base de datos ac__PACKAGE__->load_classes({sistapDB => [qw/unesco_areaunesco_subareaunesco_categoria/]});
1;
Creando un modelo
Se crea una clase por tabla
(archivo lib/sistapDB/unesco_area.pm)
usamos DBIx::Class::Schema::Loader
package sistapDB::unesco_area;
use base qw/DBIx::Class/;
# Se cargan componentes requeridos por DBIC__PACKAGE__->load_components(qw/PK::Auto Core/);
# Se asigna el nombre de la base de datos __PACKAGE__->table('sta_unesco_area');
# Se listan los campos de la tabla__PACKAGE__->add_columns(qw/id codigo nombre descripcion activo /);
# Se indica la llave primaria de la tabla__PACKAGE__->set_primary_key(qw/id/);
# Asignamos las relaciones __PACKAGE__->has_many( subareas => 'sistapDB::unesco_subarea','id_unesco_area');
1;
Creando un modelo
package DBIC::Model::sistapDB;
use strict;
use base 'Catalyst::Model::DBIC::Schema';
__PACKAGE__->config(
schema_class => 'sistapDB',
connect_info => [
'dbi:Pg:dbname=sistap',
'usuario',
'clave',
{ AutoCommit => 1 },
],
);
Resultado:
(Archivo: lib/sistap/Model/sistapDB)
Script helper:
.script/sistap_create.pl model sistapDB DBIC::Schema \
sistapDB dbi:Pg:dbname=sistap 'usuario' 'clave' '{ AutoCommit
=> 1 }'
Trabajando con relaciones
package sistapDB::unesco_area;#... Se hereda clase ; Carga de componentes ; nombre de la tabla ; nombre columnas ; llave primaria__PACKAGE__->add_columns(qw/id_area nombre/);
# empezamos a declarar las relaciones a nivel de ORM__PACKAGE__->has_many( subareas => 'sistapDB::unesco_subarea','id_area');package sistapDB::unesco_subarea;#... igual que arriba__PACKAGE__->add_columns(qw/id_subarea id_area nombre/);
# empezamos a declarar las relaciones a nivel de ORM__PACKAGE__->belongs_to( area => 'sistapDB::unesco_area','id_area');__PACKAGE__->has_many( categorias => 'sistapDB::unesco_subarea','id_subarea');package sistapDB::unesco_categoria;#... igual que arriba__PACKAGE__->add_columns(qw/id_categoria id_subarea nombre/);
# empezamos a declarar las relaciones a nivel de ORM__PACKAGE__->belongs_to( subarea => 'sistapDB::unesco_subarea','id_subarea');
Usando DBIC en el controlador
Mtodos ms comunes:
find (SELECT .. LIMIT 1) : Obtiene un (1) registro (hash) segn patrn de busqueda
$area = $c->model(sistapDB::unesco_area)->find(3);
$persona = c->model(sistapDB::personas)->find({ nombre => { ILIKE => '%javier%' }})
search (SELECT *) : Obtiene un arreglo de registros
@productos = $c->model(sistapDB::productos)->search({ codigo => 've' , tipo => 'abc' });
create (INSERT) : Crea un nuevo registro segn el hash pasado.
my $campos = { codigo => $c->req->param("codigo"), nombre => $c->req->param(nombre)};
$registro = $c->model(sistapDB::productos)->create($campos);
# al asignar la creacin del registro a una variable, se obtiene el ResourceSet de la operacin
$registro->id ; # se obtiene el id del registro recien insertado.
update: Actualiza el ResourceSet
$equipo = $c->model(sistapDB::equipos)->find(3);
$equipo->tipo(ups);
$equipo->dominio(administracion);
$equipo->update;
delete : Elimina los registros del resourceSet
$c->model(sistapDB::equipos)->search({tipo => 'ups'})->delete;
Paginador usando DBIC
Plantilla (Template Toolkit)
package sistap::Controller::esta;
sub pagina : Local {
my ( $self , $c ) = @_ ;
my $nroRegistros = $c->req->param("nroRegistros") || 10;
my $nroPagina = $c->req->param("nroPagina") || 1;
my $paginador = $c->model("sistapDB::instituciones")->search(undef,{
page => $nroPagina,
rows => $nroRegistros
}) ;
$c->stash->{registros} = $paginador ;
}
-
[% WHILE ( r = registro.next ) %]
-
[% r.nombre %]
[% END %]
Nro pgina
Controlador
Vistas
TTSite
Template Toolkit
JSON
PHP
ClearSilver (yahoo, google)
...
Predefiniendo una vista.
Vistas
(TTSite -> Catalyst::Helper::View::TTSite)
./lib/config/
Configuracin de variables (colores, rutas predefinidas, etc) a ser usadas.
./lib/site
Plantillas fuentes
footer: Pie de pgina
header: Encabezado (h1 con nombre de pgina)
html: Esqueleto base (Incluye ttsite.css)
layout: Cuerpo (body) del documento.
wrapper: Quin se encarga de acoplarlos.
./src
Plantillas predefinidas.
.|-- lib| |-- config| | |-- col| | |-- main| | `-- url| `-- site| |-- footer| |-- header| |-- html| |-- layout| `-- wrapper`--- src |-- error.tt2 |-- message.tt2 |-- ttsite.css `-- welcome.tt2
perl script/sistap_create view TTSite TTSite
Vistas
(Template Toolkit)
perl script/sistap_create view TT TT
Por defecto, las plantillas se almacenan en root
$c->stash->{variable} && [% variable %]
Vistas
(JSON)
Catalyst::View::JSON
perl script/sistap_create view JSON JSON
my @estados = $c->model("sistapDB::paises")->find($id_pais)->estados(undef,{order_by => 'nombre'}) ;
$c->stash->{estados} = [map { { id_estado => $_->id_estado , nombre_estado => $_->nombre } } @estados ];
$c->forward('sistap::View::JSON');my @estados = $c->model("sistapDB::paises")->find($id_pais)->estados()->all ;
$c->stash->{estados} = @estados ;
$c->forward('sistap::View::JSON');
Vistas
Predefiniendo una vista
sistap.yml
Al trabajar con varias vistas, si no se especifica cual usar por defecto, podemos tener problemas.
---name: sistapdefault_view: TTauthentication: ...
Agregando mdulos (Catalyst::Plugin)
package sistap;
use strict;
use warnings;
use Catalyst::Runtime '5.70';
use Catalyst qw/
-Debug
ConfigLoader
Static::Simple
Authentication
Authentication::Store::DBIC
Authentication::Credential::Password
Authorization::Roles
Prototype
Dumper
Session
Session::Store::FastMmap
Session::State::Cookie
/;
our $VERSION = '0.01';
__PACKAGE__->config( name => 'sistap',
session => { flash_to_stash => 1 },
form => { messages => ':es_ES' }
);
__PACKAGE__->setup( qw/RequireSSL/ );
1;
lib/sistap.pm
-Debug
Modo verboso en consola cuando se usa servidor de pruebas.
ConfigLoader
Se usa para cargar informacin de sistap.yml
Static::Simple
Para que reconozca archivos estaticos (imagenes, css, js) y no trate despacha las rutas si hay coincidencia.
Authentication/Autorization*
Autenticacin (Quin tiene acceso?)
Autorizacin (de qu tiene acceso?)
Prototype
Ejectos integrados de script.aculo.us
Dumper
uso de Data::Dumper para obtener estructuras completas de data.
Session*
Manejo de sessiones.
Generacin de formularios
Catalyst::Controller::FormBuilder
Generacin de formularios
Se compone en varios archivos para mayor mantenimiento y abstrabcin de conceptos.
Detalle de formulario
root/forms/nombre/comun.fb
Controlador
lib/sistap/Controller/nombre.pm
Plantilla
root/src/nombre/comun.tt
FormBuilder en Catalyst (CGI::FormBuilder)
Descripcin del formulario (root/forms/unesco_subarea/comun.fb)
name: unesco_subarea
method: post
action: /unesco_subarea/operaciones
fields:
tOperacion:
type: hidden
id:
id: hdn_id
type: hidden
id_unesco_area:
label : Area
type: select
id: txt_id_unesco_area
disabled : disabled
autocomplete: off
codigo:
id: txt_codigo
disabled : disabled
autocomplete: off
required : 1
nombre:
id: txt_nombre
disabled : disabled
autocomplete: off
required: 1
validate : NAME
Formato yaml.
Usen espacios, no tabs.
Definicin de elementos y sus atributos.
Validaciones (Cliente y Servidor)*
Facilmente aplicable a plantillas.
* la validacin absoluta debera aplicarse a nivel de base de datos
FormBuilder en Catalyst (CGI::FormBuilder)
Controlador (lib/sistap/Controller/unesco_subarea)
package sistap::Controller::unesco_subarea;
use strict;
use warnings;
use base 'Catalyst::Controller::FormBuilder';
...
sub principal : Path('/mantenimiento/unesco_subarea') Form('unesco_subarea/comun') {
my ($self, $c) = @_ ;
my $form = $self->formbuilder;
$form->field( name => 'id_unesco_area',
options => [ map {
{ $_->id_area => $_->nombre }
} $c->model(sistapDB::unesco_area)->all ]
);
if ($form->submitted && $form->validate){
$c->model(sistapDB::unesco_subarea)->create($form->fields) ;
}
}
FormBuilder en Catalyst (CGI::FormBuilder)
Plantilla (root/src/unesco_subarea/comun.tt)
[% FormBuilder.render %]
[% FormBuilder.start -%]
[% formFuilder.jshead %]
[% FormBuilder.field.tOperacion.field -%]
[% FormBuilder.field.id_institucion.field -%]
[% FormBuilder.field.nombre.label -%]
[% FormBuilder.field.nombre.field -%]
[% FormBuilder.field.siglas.label -%]
[% FormBuilder.field.siglas.field -%]
[% FormBuilder.end -%]
Variables de session
Uso de sesiones
Agregar plugin de session
store
cookie (la data)
bd
archivo
state
url (QueryString)
Variable oculta ()
cookie (solo id nico)
Variables de session slo para el usuario que ejecuta la accin.
$c->session->{id} = hey ;
[% c.session.id %]
delete($c->session->{id}) ;
$c->session->{id} = undef ;
Variable de session para todos los usuarios
$c->store_session_data(key,value)
$c->store_session_data(color,azul)
$c->get_session_data(key)
$c->get_session_data(color)
$c->delete_session_data(key)
uso de Flash
(BTW: nada que ver con adobe )
Debe estar cargado plugin de sesion (Catalyst::Plugin::Session)
lib/sistap.pm
PACKAGE__->config(
name => 'sistap',
session => {
flash_to_stash => 1
}
);
Controlador
$c->flash->{error} = Pagina invalida
Plantilla (TT)
[% error %]
Autenticacin / Autorizacin
Autenticacin y autorizacin
---name: sistapdefault_view: TTauthentication: dbic: # nombre del esquema que contiene la informacion de los usuarios user_class: sistapDB::usuarios
# Este es el nombre del campo en la tabla de usuarios, que contiene el nombre del usuario user_field: username
# Este es el nombre del campo en la tabla de usuarios, que contiene la clave del usuario password_field: password
# Habilitar claves cifradas password_type: hashed
# Usamos el algoritmo de cifrado SHA-1 password_hash_type: SHA-1
authorization: dbic: # nombre del esquema que contiene la informacion de los roles del usuario role_class: sistapDB::roles
# Este es el nombre del campo en la tabla de de roles, que contiene los diferentes roles role_field: rol
# The name of the accessor used to map a role to the users who have this role # nombre de la relacin asociada a la tabla de usuarios_roles role_rel: map_user_role
# nombre del campo en la tabla de relacin usuarios_roles que referencia al usuario (id) user_role_user_field: usuario_id
Autenticacin y autorizacin
Configuracion: lib/sistap.pm
__PACKAGE__->config( name => 'sistap',
session => {
expires => 2400,
storage => '/tmp/session',
},
);
Acciones
$c->login($username, $password) ;
$c->user_exists ;
$c->user->ciUsuario ;
$c->check_user_roles('admin') ;
$c->logout ;
jQuery
Qu es jQuery?
Framework de JavaScript
Selectores de CSS3.
Manipulacin de eventos.
Ajax.
Gran cantidad de plugins.
Tabs.
Menues.
Formularios.
Dialogos.
Drag and Drop.
etc ( http://jquery.com/plugins/ )
jQuery
jQuery.noConflict();
jQuery(function(){
// El cdigo a ejecutarse cuando se cargue todo el documento ac
}
// ac tambin puede haber cdigo, pero no si se disparar an cuando
// el documento no est cargado
jQuery: Selectores
Bsicamente jQuery(selector CSS o xpath)
jQuery("#txt_pais").val(jQuery("#modal_pais :selected").text())
Antes: document.getElementById(txt_pais).value = document.getElementById("modal_pais").options[document.getElementById("modal_pais").selectedIndex].text
jQuery(".jd_menu li ul li ul").parent().addClass("flecha_menu");
Antes: Posiblemente usara un id por cada elemento y sabiendo quin merece la imagen, se la asigno, sino, del lado del servidor.
jQuery("table.cebra tr:even").addClass("resaltado");
Antes: Si se construye la tabla de forma dinmica (php, perl, python, etc), controlar el nmero del registro y asignar la clase correspondiente.
jQuery("input[@type=text]:visible").eq(0).focus()
Antes: Seguro hara lo mismo pero a pie, pasar por todo el fomulario buscando los elementos visibles y luego situarme en el primer elemento.
Ajax
(ahah)
Ajax
(ahah)
Crear vista de JSON.
perl script/sistap_create view JSON JSON
La informacin a enviar como respuesta est en el stash.
$c->stash->{salida} = hey;
jQuery captura los datos.
jQuery.getJSON( url , param , function(jsonData){
if (jsonData.salida == hey ){
alert(fino);
}else{
alert(error al obtener la data);
}
})
Ajax
(JSON)
my $id_pais = $c->req->param(pais_id);my @estados = $c->model("sistapDB::paises")->find($id_pais)->estados(undef,{order_by => 'nombre'}) ;
$c->stash->{estados} = [map { { id_estado => $_->id_estado , nombre_estado => $_->nombre } } @estados ];
$c->forward('sistap::View::JSON');var param = new Object();
param = {pais_id : 3} ;
jQuery.getJSON( [% c.uri_for('controlador/accion/') %] , param , function(jsonData){
if (jsonData.estados){
for (i= 0 ; jsonData.estados.lenght ; i++){
// tengo jsonData.estados[i].id_estado y jsonData.estados[i].nombre_estado
}
}else{
console.info(hubo un error al traer la data);
// incluso se puede capturar si se acab el tiempo de sesin
// de usuario segn respuesta y se recarga la pgina.
}
})
jQuery.getJSON( url , parametros , function(jsonData){ // trabajamos con el resultado... jsonData });
jQuery: plugins
Tabs
http://stilbuero.de/jquery/tabs/
menu
http://jdsharp.us/jQuery/plugins/jdMenu/
Thickbox
http://jquery.com/demo/thickbox/
Form
http://www.malsup.com/jquery/form/
Interfaces (interfaces es para para jQuery, lo que script.aculo.us es para prototype)
http://interface.eyecon.ro/
Muchos mas.
http://jquery.com/plugins/
jQuery: plugin TABS
jQuery(function(){jQuery('#menu-subvencion').tabs({ fxFade : true , fxSpeed : 'fast' , remote: true });})
-
Datos
generales
- Resumen
jQuery: plugin jdMenu
$(function(){
$('ul.jd_menu').jdMenu();
});
-
Item A
- Item 1
- Item 2
- Item B
jQuery: plugin thickbox
Usuario :
Clave :
Depuracin
Depuracin
javascript (firebug) : console.info()
Depuracin
Catalyst : $c->log->debug()
Depuracin
DBIC: export DBIC_TRACE=1=/tmp/salida.txt
Consejos
Usar uri_for (en las plantillas y controlador).
Enlace
$c->res->redirect($c->uri_for('/a/b/c'));
Usar relaciones en ORM (DBIC).
Usar Template Toolkit para generar maestros.
Usar Flash + redirect para mensajes a usuario.
Usar Ajax solo cuando sea justificado. (No AJfiXiar el sitio)
Usar Unicode
BD (UTF-8)
Servidor web (apache: AddDefaultCharset utf8)
Archivo (Usar un editor que lo soporte, como vim )
Documento (html: )
Usar la funcin jQuery en vez de la funcin annima ($)
jQuery.noConflict()
Proyectos libres nacionales desarrollados usando Catalyst (Que conozco hasta ahora)
Debian::Package::HTML
http://search.cpan.org/~bureado/Debian-Package-HTML-0.1/lib/Debian/Package/HTML.pm
PUBuilder
http://blog.bureado.com.ve/?p=307
Sistap:
http://sistemas.fsl.fundacite-merida.gob.ve/projects/sistap
TEGZ:
http://sistemas.fsl.fundacite-merida.gob.ve/projects/tegz
Preguntas?
Gracias por su atencin
Pulse para editar los formatos del texto del esquema
Segundo nivel del esquema
Tercer nivel del esquema
Cuarto nivel del esquema
Quinto nivel del esquema
Sexto nivel del esquema
Sptimo nivel del esquema
Octavo nivel del esquema
Noveno nivel del esquema
top related