Web applications with Catalyst

Post on 10-May-2015

3.488 views 0 download

Tags:

Transcript of Web applications with Catalyst

6/12/056/12/05 11 / 21 / 21

CatalystCatalysteasy to use MVC frameworkeasy to use MVC framework

Svilen Ivanov (svilen@netclime.com)Svilen Ivanov (svilen@netclime.com)

6/12/056/12/05 22 / 21 / 21

What is MVC?What is MVC?

● MModelodel VViewiew CControllerontroller::■ architecture that separates an application's data model, architecture that separates an application's data model,

user interface, and control logic into 3 distinct componentsuser interface, and control logic into 3 distinct components

■ modifications to one component can be made with minimal modifications to one component can be made with minimal impact to the others.impact to the others.

● ResponsabilityResponsability■ model - domain-specific representation of the information model - domain-specific representation of the information

on which the application operates (database)on which the application operates (database)

■ view - renders the model into a form suitable for view - renders the model into a form suitable for interaction, typically a user interface (html)interaction, typically a user interface (html)

■ controller - responds to events and invokes changes on the controller - responds to events and invokes changes on the model and/or the view model and/or the view

6/12/056/12/05 33 / 21 / 21

What is Catalyst?What is Catalyst?

● A framework for development of web application A framework for development of web application using Model-View-Controller pattern:using Model-View-Controller pattern:■ Promotes the re-use of existing Perl modules that already Promotes the re-use of existing Perl modules that already

handle common web applicationhandle common web application

■ Catalyst is controllerCatalyst is controller

■ View: Template::Toolkit, Mason, HTML::Temlate, etc.View: Template::Toolkit, Mason, HTML::Temlate, etc.

■ Model: Class::DBI, Tangram, Rose::DB, etc.Model: Class::DBI, Tangram, Rose::DB, etc.

■ platform independent (really!)platform independent (really!)

■ Engines: CGI, FastCGI, mod_perl (1.3 and 2.0), self-Engines: CGI, FastCGI, mod_perl (1.3 and 2.0), self-restartinng developement enginerestartinng developement engine

6/12/056/12/05 44 / 21 / 21

Why Catalyst?Why Catalyst?

● Doesn't aim to provide end to end solution (RnR)Doesn't aim to provide end to end solution (RnR)● Flexability – use different components as M or VFlexability – use different components as M or V● Reusability – plugins (extends runtime Reusability – plugins (extends runtime

functionality):functionality):■ session, form validation, static files serving, unicodesession, form validation, static files serving, unicode

● Built-in developent tools:Built-in developent tools:■ self-restarting developement web server on dev's machineself-restarting developement web server on dev's machine

● Distribute the application as CPAN moduleDistribute the application as CPAN module● Framwork for auto and unit testsFramwork for auto and unit tests

■ doen't need web server to generate pagesdoen't need web server to generate pages

6/12/056/12/05 55 / 21 / 21

Catalyst WorkflowCatalyst Workflow

6/12/056/12/05 66 / 21 / 21

Installing and runningInstalling and running

● Installation from CPANInstallation from CPAN■ $ perl -MCPAN -e 'install Task::Catalyst'$ perl -MCPAN -e 'install Task::Catalyst'

● Creating stub applicationCreating stub application■ $ catalyst.pl MyApp$ catalyst.pl MyApp# output omitted# output omitted$ cd MyApp$ cd MyApp$ script/myapp_create.pl controller Library::Login$ script/myapp_create.pl controller Library::Login

● RunningRunning■ $ script/myapp_server.pl$ script/myapp_server.pl

● Open in browser:Open in browser:■ http://localhost:3000/library/login/http://localhost:3000/library/login/

6/12/056/12/05 77 / 21 / 21

Building application (1)Building application (1)

● Application Class – base class for your applicationApplication Class – base class for your applicationpackage MyApp;package MyApp;use strict;use strict;use Catalyst qw/-Debug/;use Catalyst qw/-Debug/;MyApp->config(MyApp->config( name => 'My Application',name => 'My Application', # You can put anything else you want in here:# You can put anything else you want in here: my_configuration_variable => 'something',my_configuration_variable => 'something',););

sub default : sub default : PrivatePrivate { { my ( $self, $context ) = @_;my ( $self, $context ) = @_; $context->response->body('Catalyst rocks!');$context->response->body('Catalyst rocks!');}}

6/12/056/12/05 88 / 21 / 21

ActionsActions

● ActionsActions■ action is a subroutine usually executed when requesting action is a subroutine usually executed when requesting

specific URLspecific URL

■ Action-to-URL mapping: Action-to-URL mapping: module:module: MyApp::Controller::Admin::Login MyApp::Controller::Admin::Loginurl: url: http://localhost/admin/login http://localhost/admin/login

● The attribute of the subroutine defines the type of The attribute of the subroutine defines the type of the actionthe actionsubsub namename : : attributesattributes {{

}}example:example:sub bar : Regex('^item(\d+)/order(\d+)$') { }sub bar : Regex('^item(\d+)/order(\d+)$') { }

6/12/056/12/05 99 / 21 / 21

Types of actions (1)Types of actions (1)

● LiteralLiteralpackage MyApp::Controller::My::Controller;package MyApp::Controller::My::Controller;

sub bar : Path('foo/bar') { }sub bar : Path('foo/bar') { }# http://localhost:3000/my/controller/foo/bar# http://localhost:3000/my/controller/foo/bar

sub bar : Path { }sub bar : Path { }# http://localhost:3000/my/controller# http://localhost:3000/my/controller

sub bar : Path('/foo/bar') { }sub bar : Path('/foo/bar') { }# http://localhost:3000/foo/bar# http://localhost:3000/foo/bar

● LocalRegexLocalRegexpackage MyApp::Controller::My::Controller;package MyApp::Controller::My::Controller;sub bar : LocalRegex('^widget(\d+)$') { }sub bar : LocalRegex('^widget(\d+)$') { }# http://localhost:3000/my/controller/widget23# http://localhost:3000/my/controller/widget23

● RegexRegexsub bar : Regex('^item(\d+)/order(\d+)$') { }sub bar : Regex('^item(\d+)/order(\d+)$') { }# http://localhost:3000/item23/order42# http://localhost:3000/item23/order42

6/12/056/12/05 1010 / 21 / 21

Types of actions (2)Types of actions (2)

● Top-levelTop-levelpackage MyApp; package MyApp; sub foo : Global { }sub foo : Global { }# http://localhost:3000/foo# http://localhost:3000/foo

● Namespace-PrefixedNamespace-Prefixedpackage MyApp::Controller::My::Controller; package MyApp::Controller::My::Controller; sub foo : Local { }sub foo : Local { }# http://localhost:3000/my/controller/foo# http://localhost:3000/my/controller/foo

● PrivatePrivatesub foo : Private { }sub foo : Private { }

● Default actionsDefault actions■ default, index, begin, enddefault, index, begin, end

6/12/056/12/05 1111 / 21 / 21

ContextContext

● ContextContext■ object passed to each action in order to interact w/ Catalyst object passed to each action in order to interact w/ Catalyst

(get request parameters, set response body)(get request parameters, set response body)sub hello : Global {sub hello : Global { my ( $self, $c ) = @_; my ( $self, $c ) = @_; $c->res->body('Hello World!'); $c->res->body('Hello World!');}}

■ Important objects:Important objects:▬ Request ($c->req) – web paranaters, cookies, headers, Request ($c->req) – web paranaters, cookies, headers,

uploaded filesuploaded files▬ Response ($c->res) – set document body, HTTP status codeResponse ($c->res) – set document body, HTTP status code▬ Configuration ($c->config) – static project configurationConfiguration ($c->config) – static project configuration▬ Log ($c->log) – print log messagesLog ($c->log) – print log messages▬ Stash ($c->stash) – pass data from model to viewStash ($c->stash) – pass data from model to view

6/12/056/12/05 1212 / 21 / 21

Views - Template ToolkitViews - Template Toolkit

● Fast, powerful and extensible template processing Fast, powerful and extensible template processing system:system:■ rich presentation languageocumentation including tutorial rich presentation languageocumentation including tutorial

and reference manualsand reference manuals

■ output filtering (for e.g. html escaping), exception handlingoutput filtering (for e.g. html escaping), exception handling

■ use directly hashes, arrays, objects in the templateuse directly hashes, arrays, objects in the template

■ templates are compiled to Perl code for maximum runtime templates are compiled to Perl code for maximum runtime efficiency and performance.efficiency and performance.

■ compiled templates are cached and can be written to disk compiled templates are cached and can be written to disk in "compiled form" to achieve cache persistance.in "compiled form" to achieve cache persistance.

■ documentation including tutorial and reference manualsdocumentation including tutorial and reference manuals

■ open source and free! :)open source and free! :)

6/12/056/12/05 1313 / 21 / 21

TT - ExampleTT - Example

t.plt.plmy %vars = ( webpages => [my %vars = ( webpages => [ { url => 'http://foo.org', title => 'The Foo Organisation' }{ url => 'http://foo.org', title => 'The Foo Organisation' } { url => 'http://bar.org', title => 'The Bar Organisation' }{ url => 'http://bar.org', title => 'The Bar Organisation' } ]);]);$template->process(\%vars);$template->process(\%vars);

template.tttemplate.tt::

[% INCLUDE header[% INCLUDE header title = 'This is an HTML example'title = 'This is an HTML example'%]%]

<h1>Some Interesting Links</h1><h1>Some Interesting Links</h1>

Links:Links:<ul><ul>[% FOREACH link = webpages %][% FOREACH link = webpages %] <li><a href="<li><a href="[% link.url %][% link.url %]">">[% link.title %][% link.title %]</a></a>[% END %][% END %]</ul></ul>

header.tt:header.tt:

<html><head><title><html><head><title>[% title %][% title %]</title></head></title></head><body bgcolor="#ffffff"><body bgcolor="#ffffff">

6/12/056/12/05 1414 / 21 / 21

Model - Rose::DB::ObjectModel - Rose::DB::Object

● Base class for objects that encapsulate a single Base class for objects that encapsulate a single row in a database tablerow in a database table■ supports creating, loading, saving, deleting an objectsupports creating, loading, saving, deleting an object

■ fetching reffered by foreign-key objectsfetching reffered by foreign-key objects● Rose::DB::Object::Manager Rose::DB::Object::Manager

■ Fetch multiple objects from the database using arbitrary Fetch multiple objects from the database using arbitrary query conditions, limits, and offsets.query conditions, limits, and offsets.

■ Iterate over a list of objectIterate over a list of object

■ Update/Delete objects that match a complex query.Update/Delete objects that match a complex query.

■ Fetch objects along with "foreign objects" (related through Fetch objects along with "foreign objects" (related through any of the supported relationship types) in a single query by any of the supported relationship types) in a single query by automatically generating the appropriate SQL join(s).automatically generating the appropriate SQL join(s).

6/12/056/12/05 1515 / 21 / 21

Rose – example (1)Rose – example (1)

● Defining objectDefining objectCREATE TABLE `products` (CREATE TABLE `products` ( `id` bigint(20) unsigned NOT NULL auto_increment,`id` bigint(20) unsigned NOT NULL auto_increment, `name` varchar(255) NOT NULL default '',`name` varchar(255) NOT NULL default '', `price` decimal(10,2) NOT NULL default '0.00',`price` decimal(10,2) NOT NULL default '0.00', PRIMARY KEY (`id`),PRIMARY KEY (`id`), UNIQUE KEY `id` (`id`),UNIQUE KEY `id` (`id`), UNIQUE KEY `name` (`name`)UNIQUE KEY `name` (`name`)) ENGINE=MyISAM DEFAULT CHARSET=latin1;) ENGINE=MyISAM DEFAULT CHARSET=latin1;

package Product;package Product;use Rose::DB::Object;use Rose::DB::Object;our @ISA = qw(Rose::DB::Object);our @ISA = qw(Rose::DB::Object);__PACKAGE__->meta->table('products');__PACKAGE__->meta->table('products');__PACKAGE__->meta->columns(qw(id name price));__PACKAGE__->meta->columns(qw(id name price));__PACKAGE__->meta->primary_key_columns('id');__PACKAGE__->meta->primary_key_columns('id');__PACKAGE__->meta->add_unique_key('name');__PACKAGE__->meta->add_unique_key('name');__PACKAGE__->meta->initialize;__PACKAGE__->meta->initialize;

6/12/056/12/05 1616 / 21 / 21

Rose – example (2)Rose – example (2)

● Operations using this objectOperations using this object# add new product# add new product$p1 = Product->new(name => 'Bike');$p1 = Product->new(name => 'Bike');$p1->save;$p1->save;

# get product by its primary key# get product by its primary key$p2 = Product->new(id => '1');$p2 = Product->new(id => '1');$p2->load();$p2->load();

# access/modify fields# access/modify fieldsprint $p2->name; # prints 'Bike'print $p2->name; # prints 'Bike'$p2->name('ski'); # changes the name to 'ski'$p2->name('ski'); # changes the name to 'ski'$p2->save(); # updates database;$p2->save(); # updates database;

# deletes the object by unique key# deletes the object by unique key$p3 = Product->new(name => 'ski');$p3 = Product->new(name => 'ski');$p3->delete(); # the row is gone$p3->delete(); # the row is gone

6/12/056/12/05 1717 / 21 / 21

Rose – example (3)Rose – example (3)

● Work over set of objects using manager:Work over set of objects using manager:package Product::Manager;package Product::Manager;use Rose::DB::Object::Manager;use Rose::DB::Object::Manager;our @ISA = qw(Rose::DB::Object::Manager);our @ISA = qw(Rose::DB::Object::Manager);sub object_class { 'Product' }sub object_class { 'Product' }__PACKAGE__->make_manager_methods('products');__PACKAGE__->make_manager_methods('products');

● Using the managerUsing the manager$products = Product::Manager->get_products();$products = Product::Manager->get_products();foreach my $product (@$products) { print $product->name, "\n"; }foreach my $product (@$products) { print $product->name, "\n"; }

$iterator = Product::Manager->get_products_iterator();$iterator = Product::Manager->get_products_iterator();while($product = $iterator->next) {while($product = $iterator->next) { print $product->id, ' ', $product->name, "\n";print $product->id, ' ', $product->name, "\n"; $iterator->finish if(...); # exit early?$iterator->finish if(...); # exit early?}}print $iterator->total; # total iterated overprint $iterator->total; # total iterated over

6/12/056/12/05 1818 / 21 / 21

Rose – example (4)Rose – example (4)

● Complex queryComplex query $products = Product::Manager->get_products(query =>$products = Product::Manager->get_products(query => [[ name => { like => '%Hat' },name => { like => '%Hat' }, id => { ge => 7 },id => { ge => 7 }, or => or => [[ price => 5.00,price => 5.00, price => { lt => 10.00 },price => { lt => 10.00 }, ],], ],], sort_by => 'name',sort_by => 'name', limit => 10,limit => 10, offset => 50);offset => 50);

SELECT id, name, price FROM products WHERESELECT id, name, price FROM products WHERE name LIKE '%Hat' AND id >= 7 ANDname LIKE '%Hat' AND id >= 7 AND (price = 5.00 OR price < 10.00)(price = 5.00 OR price < 10.00) ORDER BY name LIMIT 10 OFFSET 50ORDER BY name LIMIT 10 OFFSET 50

6/12/056/12/05 1919 / 21 / 21

DemonstrationDemonstration

● Starting development serverStarting development server● Demonstrate basic actionsDemonstrate basic actions

■ protection from refreshprotection from refresh

■ error handlingerror handling

■ HTML escapingHTML escaping

■ Performance of the TTPerformance of the TT● ReviewReview

■ modelmodel

■ viewview

■ controllercontroller

6/12/056/12/05 2020 / 21 / 21

ConclusionsConclusions

● Catalyst is rich web development platformCatalyst is rich web development platform■ it is AJAX-ready it is AJAX-ready (a little marketing blurp :)(a little marketing blurp :)

● Using open source tools we can boost productivity Using open source tools we can boost productivity ■ let HTML developers work spearately on Template and let HTML developers work spearately on Template and

easily test the resulteasily test the result

■ let backend developers work on model classes, write let backend developers work on model classes, write autotestsautotests

● Create better workflowCreate better workflow■ the front- and back-end integration must be defined prior the front- and back-end integration must be defined prior

start of developmentstart of development● Avoid most common errorsAvoid most common errors● Building web applications Building web applications can be fun!can be fun! :) :)

6/12/056/12/05 2121 / 21 / 21

Thank you!Thank you!

● Questions?Questions?