SlideShare a Scribd company logo
Catalyst 
Elegant Perl MVC Framework 
Sheeju Alex 
Exceleron Software
Installing Catalyst 
cpan/cpanm Task::Catalyst 
● DBIx::Class Support 
● Template::Toolkit Support 
● Authentication/Authorization Support 
● HTML::FormFu Support 
OR install from apt-get
Setting up Catalyst App 
catalyst gets rid of repeated work... 
sheeju@sheeju-exceleron:~/projects$ catalyst.pl Library 
created "Library" 
created "Library/script" 
created "Library/lib" 
created "Library/root" 
……... 
created "Library/script/library_cgi.pl" 
created "Library/script/library_fastcgi.pl" 
created "Library/script/library_server.pl" 
created "Library/script/library_test.pl" 
created "Library/script/library_create.pl" 
Change to application directory and Run "perl Makefile.PL" to make sure your install is complete
What is MVC 
● Model (Data) 
○ Get All Users 
○ Get User foo 
○ Delete User 
● View (Display) 
○ Render the page 
○ Render user as JSON/XML 
● Controller (Glue’s - model and view) 
○ Get the Data from Model 
○ Check Permission 
○ Send data over to the view
So what does this mean? 
* Is full CPAN package 
* Contains Standalone and server deployment scripts 
* loads config automatically 
* testing stubs 
* helpers to create more parts of your app
App Layout 
● lib/ - package/class namespaces 
○ Library - lib/Library.pm 
○ Library::Controller::Root - lib/Library/Controller/Root.pm 
○ Model & View - empty for purpose 
● root/ - css,js,tt etc store here exposed via /static URL 
● script/ - application level script goes here including dev server script 
○ library_create.pl 
○ library_server.pl 
● t/ - Tests goes here (Watch for TDD presentation) 
fires up app in own dedicated server http://localhost:3000
Built-In Server - Start 
sheeju@sheeju-exceleron:~/projects/Library$ ./script/library_server.pl 
[debug] Debug messages enabled 
[debug] Loaded Config "/home/sheeju/projects/Library/library.conf" 
[debug] Statistics enabled 
[debug] Loaded plugins: 
.----------------------------------------------------------------------------. 
| Catalyst::Plugin::ConfigLoader 0.32 | 
| Catalyst::Plugin::Unicode::Encoding 2.1 | 
'----------------------------------------------------------------------------' 
[debug] Loaded Request Data Handlers: 
[debug] Loaded dispatcher "Catalyst::Dispatcher" 
[debug] Loaded engine "Catalyst::Engine" 
[debug] Found home "/home/sheeju/projects/Library" 
[debug] Loaded components:
Built-In Server - Start 
[debug] Loaded components: 
.-----------------------------------------------------------------+------------. 
| Class | Type | 
+-------------------------------------------------------------+-------------+ 
| Library::Controller::Root | instance | 
'---------------------------------------------------------------+--------------' 
[debug] Loaded Private actions: 
.------------------------+-----------------------------------------+--------------. 
| Private | Class | Method | 
+----------------------+------------------------------------------+-------------+ 
| /default | Library::Controller::Root | default | 
| /index | Library::Controller::Root | index | 
| /end | Library::Controller::Root | end | 
'------------------------+-----------------------------------------+--------------' 
[debug] Loaded Path actions: 
.-------------------------------------+-------------------------------------. 
| Path | Private | 
+-------------------------------------+----------------------------------+ 
| / | /index | 
| /... | /default | 
'-------------------------------------+-------------------------------------' 
[info] Library powered by Catalyst 5.90053 
HTTP::Server::PSGI: Accepting connections at http://0:3000/
Browse me
Request ⇔ Response 
● All web applications handle request and generate responses. 
● In Catalyst, this happens in special methods called "actions". On every request, Catalyst 
identifies one or more actions and calls them with special arguments, including a reference to 
the "context" object that provides a convenient and practical API through which everything 
else is accomplished. 
○ Actions are contained within classes called "controllers", which live in a special 
path/namespace in the application 
● script/library_create.pl controller Something - creates a new controller 
○ The only reason to have more than one controller is for organization; you can put all 
your actions in the Root controller with no loss of features or ability. Controllers are just 
the containers for actions. 
● In the following sections, I describe how Catalyst decides which actions to call on each request 
("dispatch") and then explain how to use the supplied context object within them.
Dispatch 
● Catalyst provides a particularly flexible and powerful mechanism for configuring dispatch rules. 
● Rather than having a separate configuration to assign URLs to specific actions, Catalyst uses 
the actions themselves to determine URL mappings dynamically. 
● Each action definition (which is just a Perl subroutine) represents not only a block of code, but 
also what URL paths apply to it. This is specified in subroutine attributes—a lesser-known Perl 
feature that provides arbitrary labels that can be used for introspection. 
● Catalyst supports a handful of parameterized attributes (Local,Global,Private,Path, 
LocalRegex,Regex,Chained) to determine the URL path to action mappings in a variety ways 
sub do_stuff :Attribute1 :Attribute2 :Attribute3('with_argument') { ... 
Note The first : for the attributes is compulsory, whereas the 
following are optional.
Dispatch :Path 
:Path Attribute (Absolute Path) 
sub myaction :Path('/some/place') { 
my ( $self, $c, @args ) = @_; 
# do stuff... 
} 
● Regardless of what controller you put it in, the above action would map to all URLs starting 
with /some/place (http://localhost:3000/some/place with the development server). 
● If you omitted the starting slash and used :Path('some/place'), the action would map to a path 
relative to the namespace of the controller. For example, if it were in Library::Controller:: 
Foobar, it would be mapped to URL paths starting with /foobar/some/place.
Dispatch :Local 
sub place :Local { 
my ( $self, $c, @args ) = @_; 
# do stuff... 
} 
● Instead of using :Path to set the path explicitly, you can set :Local to use the name of the 
controller and method. 
● For instance, the following action, if contained in the controller Library::Controller::Some, 
would also map to /some/place: 
● If it were contained in the controller Library::Controller::Some::Other, it would map to 
/some/other/place.
Dispatch :Path/Local/* :Args 
sub myaction :Path('/some/place') { 
my ( $self, $c ) = @_; 
# do stuff... 
} 
● Actions include subpaths by default, so the above also would match /some/place/blah/foo/1. 
● When this happens, the leftover parts of the path are supplied as arguments to the action method 
('blah','foo','1'). 
● You can use the :Args attribute to limit how deep the action will match subpaths, if at all. 
● With an Args value of 0, this action would match only /some/place, but nothing below it: 
sub myaction :Path('/some/place') :Args(0) { 
my ( $self, $c ) = @_; 
# do stuff... 
}
Dispatch :Global & :Private 
● :Global 
○ works like :Local but ignores the controller name 
○ Anywhere - show’s up in the root of your namespace 
● :Private 
○ Internal Functions 
○ No URL 
○ Can be invoked only through a $c->forward or a $c->detach within a 
controller.
Dispatch :Regex/:LocalRegex 
● path pattern matching, discouraged from 
using. 
● Explore yourself 
● You can use Chained instead
Dispatch :Chained 
● You can configure additional/multiple actions to be called with single requests in any order 
you like. 
package MyApp::Controller::Users; 
use parent 'Catalyst::Controller'; 
# private 
sub base :Chained("/") :PathPart("users") :CaptureArgs(0) {} 
# match /users 
sub root :Chained("base") :PathPart("") :Args(0) {} 
# private 
sub base_user : Chained('base') PathPart('') CaptureArgs(1) { ... } 
# match /users/1 
sub root_user : Chained('base_user') PathPart('') Args(0) { ... } 
# match /users/1/edit 
sub user_edit : Chained('base') PathPart('edit') Args(0) { ... } 
# match /users/1/display 
sub user_edit : Chained('base') PathPart('display') Args(0) { ... } 
Users <id> 
Edit 
Display 
URL’s like /users/1/edit, /users/1/display can separate the processing of /users/1 part into its own 
method.
Dispatch Flow 
● When a URL matches more than one action, Catalyst picks the one that matches best. 
● Exceptions: Called at various stages of every request in addition to the matched action 
○ sub default :Private {} - Match everything that doesn’t match 
○ sub index :Private {} 
○ sub begin :Private {} 
○ sub end :Private {} 
○ sub auto :Private {} 
Eg URL: /person/sheeju 
MyApp::C::Person -> sheeju (finds “sheeju” action inside “person” namespace) 
MyApp::C::Person -> auto (When found) 
MyApp::C::Root -> auto (if previous auto returs true continue to the next auto, else kill the request) 
MyApp::C::Person -> begin (if there is controller’s begin or run Root’s begin) 
MyApp::C::Person/Root -> end (Finally end, usually to render view)
Internal Request Flow Control 
$c->forward & $c->detach
Internal Request Flow Control 
$c->visit & $c->go
The Context Object ($c) 
● Controller actions serve as entry points to application code. 
● A special per-request object called the "context" is supplied as an argument to every action 
when it is called by the dispatcher. 
● The context object typically is read into a variable named $c, but it could be called anything. 
Important Objects 
● Request ($c->req) – web paranaters, cookies, headers, uploaded files 
● Response ($c->res) – set document body, HTTP status code 
● Configuration ($c->config) – static project configuration 
● Log ($c->log) – print log messages 
● Stash ($c->stash) – pass data from model to view 
● Session ($c->session) - session store
Controller: GET/POST Params 
$c->req->method - To check the request method (GET/POST) 
● GETs end up in passing parms 
○ my ($self, $c, $get1, $get2, $get3 ) = @_; OR $c->req->params 
● POSTs 
○ my $params = $c->req-params; 
❏ Pass data to models or store in db 
❏ Get Manipulated data and pass it to View (HTML/JSON…) 
https://metacpan.org/pod/Catalyst::Request
Controller Data Stores 
1. Stash: short term, lasts one response cycle. Data are references, same 
form as TT takes for its process() method. 
2. Flash: longer term. Used often with the flash_to_stash config set. Useful 
for storage when handling forms. 
3. Session: lasts some time. Can last longer than visitor's login, 2 hrs by 
default. Don't use same data names as stash, because they interact.
Data – Long Term Storage 
● Usually handled with a database 
○ But check out http://sedition.com/a/2794 
○ The above shows how to read text files. 
● Build your tables, and then use the database to build the ORM schema. 
● script/library_create.pl model DB DBIC::Schema Library::Schema 
create=static components=TimeStamp,EncodedColumn 'dbi:Pg: 
dbname=sheeju sheeju sheeju '{ AutoCommit => 1 }'
View TT 
● Web/HTML 
perl script/library_create.pl view Web TT - creates simple TT view 
perl script/library_create.pl view Web TTSite - creates TT site with layout, header, footer 
● JSON - Catalyst::View::JSON
OK so now how to render? 
● catalyst.pl has already done this for you 
sub end: ActionClass(‘RenderView’) {} 
● RenderView will try to render a template unless body is defined or 
redirect is in place 
● More than one view? $c->config->{default_view} or $c->stash-> 
{current_view} to decide which one to use
ActionClass & ActionRole 
● ActionClass 
○ A type of Controller that uses bottom-level namespace of an class as an argument to ActionClass 
attribute 
○ Catalyst::Action::RenderView - best example available on default project, execute method is called 
○ Use Does instead 
● ActionRole (Does) 
○ Provides the :Does attribute which applies roles to your action class 
○ provides “around execute”, “after execute”, “before execute” method using Moose Methodmodifiers 
sub foo : Local Does('Moo') { ... } # Catalyst::ActionRole:: 
sub bar : Local Does('~Moo') { ... } # MyApp::ActionRole::Moo 
sub baz : Local Does('+MyApp::ActionRole::Moo') { ... } 
http://www.catalystframework.org/calendar/2012/16 
http://metacpan.org/module/Catalyst::Controller::ActionRole
AJAX Dispatching 
● See Demo on AJAX ActionRole 
# Make sure this is an AJAX request 
my $hdr_accept = $c->req->header('Accept') || ''; 
my $hdr_x_req_with = $c->req->header('X-Requested-With') || ''; 
if ( $hdr_accept ne 'application/json' && $hdr_x_req_with ne 'XMLHttpRequest') 
{ 
$c->stash->{ajax} = 0; 
return $self->$orig(@_); 
}
Authentication 
use Catalyst qw/ ... 
Authentication 
Session 
Session::Store::FastMmap 
Session::State::Cookie 
... 
/;
Authentication: Config 
__PACKAGE__->config->{'Plugin::Authentication'} = { 
default => { 
credential => { 
class => ‘Password’, 
password_field => ‘Password’, 
password_type => ‘clear’ 
}, 
store => { 
class => ‘DBIx::Class’, 
user_class => ‘LibraryDB::User’ 
} 
} 
}; 
$c->authenticate 
$c->user 
$c->user_exists() 
$c->logout
References 
http://wiki.catalystframework.org/wiki/gettingstarted/howtos/chainedexamples.view 
http://frioux.github.io/Catalyst-Presentation/ 
http://www.catalystframework.org/calendar/2007/24 
http://sedition.com/a/2794 
http://sedition.com/a/2733

More Related Content

What's hot

8 Minutes On Rack
8 Minutes On Rack8 Minutes On Rack
8 Minutes On Rack
danwrong
 
Redis for your boss
Redis for your bossRedis for your boss
Redis for your boss
Elena Kolevska
 
Angular promises and http
Angular promises and httpAngular promises and http
Angular promises and http
Alexe Bogdan
 
Django Rest Framework and React and Redux, Oh My!
Django Rest Framework and React and Redux, Oh My!Django Rest Framework and React and Redux, Oh My!
Django Rest Framework and React and Redux, Oh My!
Eric Palakovich Carr
 
A reviravolta do desenvolvimento web
A reviravolta do desenvolvimento webA reviravolta do desenvolvimento web
A reviravolta do desenvolvimento web
Wallace Reis
 
Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...
Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...
Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...
Ville Mattila
 
PSGI and Plack from first principles
PSGI and Plack from first principlesPSGI and Plack from first principles
PSGI and Plack from first principles
Perl Careers
 
Integrating icinga2 and the HashiCorp suite
Integrating icinga2 and the HashiCorp suiteIntegrating icinga2 and the HashiCorp suite
Integrating icinga2 and the HashiCorp suite
Bram Vogelaar
 
Working with WP_Query in WordPress
Working with WP_Query in WordPressWorking with WP_Query in WordPress
Working with WP_Query in WordPress
topher1kenobe
 
Http programming in play
Http programming in playHttp programming in play
Http programming in play
Knoldus Inc.
 
Tatsumaki
TatsumakiTatsumaki
Rest api with Python
Rest api with PythonRest api with Python
Rest api with Python
Santosh Ghimire
 
Finatra v2
Finatra v2Finatra v2
Finatra v2
Steve Cosenza
 
Angular server-side communication
Angular server-side communicationAngular server-side communication
Angular server-side communication
Alexe Bogdan
 
Selenium&amp;scrapy
Selenium&amp;scrapySelenium&amp;scrapy
Selenium&amp;scrapy
Arcangelo Saracino
 
Blood magic
Blood magicBlood magic
Blood magic
Alex Denisov
 
Beyond Phoenix
Beyond PhoenixBeyond Phoenix
Beyond Phoenix
Gabriele Lana
 
Symfony2 Components - The Event Dispatcher
Symfony2 Components - The Event DispatcherSymfony2 Components - The Event Dispatcher
Symfony2 Components - The Event Dispatcher
Sarah El-Atm
 
Plack - LPW 2009
Plack - LPW 2009Plack - LPW 2009
Plack - LPW 2009
Tatsuhiko Miyagawa
 
Caldera Learn - LoopConf WP API + Angular FTW Workshop
Caldera Learn - LoopConf WP API + Angular FTW WorkshopCaldera Learn - LoopConf WP API + Angular FTW Workshop
Caldera Learn - LoopConf WP API + Angular FTW Workshop
CalderaLearn
 

What's hot (20)

8 Minutes On Rack
8 Minutes On Rack8 Minutes On Rack
8 Minutes On Rack
 
Redis for your boss
Redis for your bossRedis for your boss
Redis for your boss
 
Angular promises and http
Angular promises and httpAngular promises and http
Angular promises and http
 
Django Rest Framework and React and Redux, Oh My!
Django Rest Framework and React and Redux, Oh My!Django Rest Framework and React and Redux, Oh My!
Django Rest Framework and React and Redux, Oh My!
 
A reviravolta do desenvolvimento web
A reviravolta do desenvolvimento webA reviravolta do desenvolvimento web
A reviravolta do desenvolvimento web
 
Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...
Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...
Running a Scalable And Reliable Symfony2 Application in Cloud (Symfony Sweden...
 
PSGI and Plack from first principles
PSGI and Plack from first principlesPSGI and Plack from first principles
PSGI and Plack from first principles
 
Integrating icinga2 and the HashiCorp suite
Integrating icinga2 and the HashiCorp suiteIntegrating icinga2 and the HashiCorp suite
Integrating icinga2 and the HashiCorp suite
 
Working with WP_Query in WordPress
Working with WP_Query in WordPressWorking with WP_Query in WordPress
Working with WP_Query in WordPress
 
Http programming in play
Http programming in playHttp programming in play
Http programming in play
 
Tatsumaki
TatsumakiTatsumaki
Tatsumaki
 
Rest api with Python
Rest api with PythonRest api with Python
Rest api with Python
 
Finatra v2
Finatra v2Finatra v2
Finatra v2
 
Angular server-side communication
Angular server-side communicationAngular server-side communication
Angular server-side communication
 
Selenium&amp;scrapy
Selenium&amp;scrapySelenium&amp;scrapy
Selenium&amp;scrapy
 
Blood magic
Blood magicBlood magic
Blood magic
 
Beyond Phoenix
Beyond PhoenixBeyond Phoenix
Beyond Phoenix
 
Symfony2 Components - The Event Dispatcher
Symfony2 Components - The Event DispatcherSymfony2 Components - The Event Dispatcher
Symfony2 Components - The Event Dispatcher
 
Plack - LPW 2009
Plack - LPW 2009Plack - LPW 2009
Plack - LPW 2009
 
Caldera Learn - LoopConf WP API + Angular FTW Workshop
Caldera Learn - LoopConf WP API + Angular FTW WorkshopCaldera Learn - LoopConf WP API + Angular FTW Workshop
Caldera Learn - LoopConf WP API + Angular FTW Workshop
 

Similar to Catalyst MVC

Curscatalyst
CurscatalystCurscatalyst
Curscatalyst
Kar Juan
 
Development Setup of B-Translator
Development Setup of B-TranslatorDevelopment Setup of B-Translator
Development Setup of B-Translator
Dashamir Hoxha
 
Oracle API Gateway Installation
Oracle API Gateway InstallationOracle API Gateway Installation
Oracle API Gateway Installation
Rakesh Gujjarlapudi
 
Very Brief Intro to Catalyst
Very Brief Intro to CatalystVery Brief Intro to Catalyst
Very Brief Intro to Catalyst
Zachary Blair
 
Capistrano deploy Magento project in an efficient way
Capistrano deploy Magento project in an efficient wayCapistrano deploy Magento project in an efficient way
Capistrano deploy Magento project in an efficient way
Sylvain Rayé
 
Null Bachaav - May 07 Attack Monitoring workshop.
Null Bachaav - May 07 Attack Monitoring workshop.Null Bachaav - May 07 Attack Monitoring workshop.
Null Bachaav - May 07 Attack Monitoring workshop.
Prajal Kulkarni
 
The Naked Bundle - Tryout
The Naked Bundle - TryoutThe Naked Bundle - Tryout
The Naked Bundle - Tryout
Matthias Noback
 
Bugzilla Installation Process
Bugzilla Installation ProcessBugzilla Installation Process
Bugzilla Installation Process
Vino Harikrishnan
 
Web applications with Catalyst
Web applications with CatalystWeb applications with Catalyst
Web applications with Catalyst
svilen.ivanov
 
Service Discovery using etcd, Consul and Kubernetes
Service Discovery using etcd, Consul and KubernetesService Discovery using etcd, Consul and Kubernetes
Service Discovery using etcd, Consul and Kubernetes
Sreenivas Makam
 
Deploy Rails Application by Capistrano
Deploy Rails Application by CapistranoDeploy Rails Application by Capistrano
Deploy Rails Application by Capistrano
Tasawr Interactive
 
What's New In Laravel 5
What's New In Laravel 5What's New In Laravel 5
What's New In Laravel 5
Darren Craig
 
Exploring Async PHP (SF Live Berlin 2019)
Exploring Async PHP (SF Live Berlin 2019)Exploring Async PHP (SF Live Berlin 2019)
Exploring Async PHP (SF Live Berlin 2019)
dantleech
 
PaaSTA: Autoscaling at Yelp
PaaSTA: Autoscaling at YelpPaaSTA: Autoscaling at Yelp
PaaSTA: Autoscaling at Yelp
Nathan Handler
 
[EXTENDED] Ceph, Docker, Heroku Slugs, CoreOS and Deis Overview
[EXTENDED] Ceph, Docker, Heroku Slugs, CoreOS and Deis Overview[EXTENDED] Ceph, Docker, Heroku Slugs, CoreOS and Deis Overview
[EXTENDED] Ceph, Docker, Heroku Slugs, CoreOS and Deis Overview
Leo Lorieri
 
TurboGears2 Pluggable Applications
TurboGears2 Pluggable ApplicationsTurboGears2 Pluggable Applications
TurboGears2 Pluggable Applications
Alessandro Molina
 
Orchestration Tool Roundup - Arthur Berezin & Trammell Scruggs
Orchestration Tool Roundup - Arthur Berezin & Trammell ScruggsOrchestration Tool Roundup - Arthur Berezin & Trammell Scruggs
Orchestration Tool Roundup - Arthur Berezin & Trammell Scruggs
Cloud Native Day Tel Aviv
 
Improving the Accumulo User Experience
 Improving the Accumulo User Experience Improving the Accumulo User Experience
Improving the Accumulo User Experience
Accumulo Summit
 
Drupal Day 2012 - Automating Drupal Development: Make!les, Features and Beyond
Drupal Day 2012 - Automating Drupal Development: Make!les, Features and BeyondDrupal Day 2012 - Automating Drupal Development: Make!les, Features and Beyond
Drupal Day 2012 - Automating Drupal Development: Make!les, Features and Beyond
DrupalDay
 
Practical catalyst
Practical catalystPractical catalyst
Practical catalyst
dwm042
 

Similar to Catalyst MVC (20)

Curscatalyst
CurscatalystCurscatalyst
Curscatalyst
 
Development Setup of B-Translator
Development Setup of B-TranslatorDevelopment Setup of B-Translator
Development Setup of B-Translator
 
Oracle API Gateway Installation
Oracle API Gateway InstallationOracle API Gateway Installation
Oracle API Gateway Installation
 
Very Brief Intro to Catalyst
Very Brief Intro to CatalystVery Brief Intro to Catalyst
Very Brief Intro to Catalyst
 
Capistrano deploy Magento project in an efficient way
Capistrano deploy Magento project in an efficient wayCapistrano deploy Magento project in an efficient way
Capistrano deploy Magento project in an efficient way
 
Null Bachaav - May 07 Attack Monitoring workshop.
Null Bachaav - May 07 Attack Monitoring workshop.Null Bachaav - May 07 Attack Monitoring workshop.
Null Bachaav - May 07 Attack Monitoring workshop.
 
The Naked Bundle - Tryout
The Naked Bundle - TryoutThe Naked Bundle - Tryout
The Naked Bundle - Tryout
 
Bugzilla Installation Process
Bugzilla Installation ProcessBugzilla Installation Process
Bugzilla Installation Process
 
Web applications with Catalyst
Web applications with CatalystWeb applications with Catalyst
Web applications with Catalyst
 
Service Discovery using etcd, Consul and Kubernetes
Service Discovery using etcd, Consul and KubernetesService Discovery using etcd, Consul and Kubernetes
Service Discovery using etcd, Consul and Kubernetes
 
Deploy Rails Application by Capistrano
Deploy Rails Application by CapistranoDeploy Rails Application by Capistrano
Deploy Rails Application by Capistrano
 
What's New In Laravel 5
What's New In Laravel 5What's New In Laravel 5
What's New In Laravel 5
 
Exploring Async PHP (SF Live Berlin 2019)
Exploring Async PHP (SF Live Berlin 2019)Exploring Async PHP (SF Live Berlin 2019)
Exploring Async PHP (SF Live Berlin 2019)
 
PaaSTA: Autoscaling at Yelp
PaaSTA: Autoscaling at YelpPaaSTA: Autoscaling at Yelp
PaaSTA: Autoscaling at Yelp
 
[EXTENDED] Ceph, Docker, Heroku Slugs, CoreOS and Deis Overview
[EXTENDED] Ceph, Docker, Heroku Slugs, CoreOS and Deis Overview[EXTENDED] Ceph, Docker, Heroku Slugs, CoreOS and Deis Overview
[EXTENDED] Ceph, Docker, Heroku Slugs, CoreOS and Deis Overview
 
TurboGears2 Pluggable Applications
TurboGears2 Pluggable ApplicationsTurboGears2 Pluggable Applications
TurboGears2 Pluggable Applications
 
Orchestration Tool Roundup - Arthur Berezin & Trammell Scruggs
Orchestration Tool Roundup - Arthur Berezin & Trammell ScruggsOrchestration Tool Roundup - Arthur Berezin & Trammell Scruggs
Orchestration Tool Roundup - Arthur Berezin & Trammell Scruggs
 
Improving the Accumulo User Experience
 Improving the Accumulo User Experience Improving the Accumulo User Experience
Improving the Accumulo User Experience
 
Drupal Day 2012 - Automating Drupal Development: Make!les, Features and Beyond
Drupal Day 2012 - Automating Drupal Development: Make!les, Features and BeyondDrupal Day 2012 - Automating Drupal Development: Make!les, Features and Beyond
Drupal Day 2012 - Automating Drupal Development: Make!les, Features and Beyond
 
Practical catalyst
Practical catalystPractical catalyst
Practical catalyst
 

Recently uploaded

HCL Notes and Domino License Cost Reduction in the World of DLAU
HCL Notes and Domino License Cost Reduction in the World of DLAUHCL Notes and Domino License Cost Reduction in the World of DLAU
HCL Notes and Domino License Cost Reduction in the World of DLAU
panagenda
 
Serial Arm Control in Real Time Presentation
Serial Arm Control in Real Time PresentationSerial Arm Control in Real Time Presentation
Serial Arm Control in Real Time Presentation
tolgahangng
 
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
SOFTTECHHUB
 
UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6
DianaGray10
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Paige Cruz
 
National Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practicesNational Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practices
Quotidiano Piemontese
 
20240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 202420240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 2024
Matthew Sinclair
 
Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1
DianaGray10
 
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
名前 です男
 
20240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 202420240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 2024
Matthew Sinclair
 
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with SlackLet's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
shyamraj55
 
How to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For FlutterHow to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For Flutter
Daiki Mogmet Ito
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
Alpen-Adria-Universität
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
Safe Software
 
Full-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalizationFull-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalization
Zilliz
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
mikeeftimakis1
 
Building Production Ready Search Pipelines with Spark and Milvus
Building Production Ready Search Pipelines with Spark and MilvusBuilding Production Ready Search Pipelines with Spark and Milvus
Building Production Ready Search Pipelines with Spark and Milvus
Zilliz
 
Presentation of the OECD Artificial Intelligence Review of Germany
Presentation of the OECD Artificial Intelligence Review of GermanyPresentation of the OECD Artificial Intelligence Review of Germany
Presentation of the OECD Artificial Intelligence Review of Germany
innovationoecd
 
TrustArc Webinar - 2024 Global Privacy Survey
TrustArc Webinar - 2024 Global Privacy SurveyTrustArc Webinar - 2024 Global Privacy Survey
TrustArc Webinar - 2024 Global Privacy Survey
TrustArc
 
Removing Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software FuzzingRemoving Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software Fuzzing
Aftab Hussain
 

Recently uploaded (20)

HCL Notes and Domino License Cost Reduction in the World of DLAU
HCL Notes and Domino License Cost Reduction in the World of DLAUHCL Notes and Domino License Cost Reduction in the World of DLAU
HCL Notes and Domino License Cost Reduction in the World of DLAU
 
Serial Arm Control in Real Time Presentation
Serial Arm Control in Real Time PresentationSerial Arm Control in Real Time Presentation
Serial Arm Control in Real Time Presentation
 
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
 
UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
 
National Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practicesNational Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practices
 
20240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 202420240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 2024
 
Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1
 
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
 
20240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 202420240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 2024
 
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with SlackLet's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
 
How to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For FlutterHow to use Firebase Data Connect For Flutter
How to use Firebase Data Connect For Flutter
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
 
Full-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalizationFull-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalization
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
 
Building Production Ready Search Pipelines with Spark and Milvus
Building Production Ready Search Pipelines with Spark and MilvusBuilding Production Ready Search Pipelines with Spark and Milvus
Building Production Ready Search Pipelines with Spark and Milvus
 
Presentation of the OECD Artificial Intelligence Review of Germany
Presentation of the OECD Artificial Intelligence Review of GermanyPresentation of the OECD Artificial Intelligence Review of Germany
Presentation of the OECD Artificial Intelligence Review of Germany
 
TrustArc Webinar - 2024 Global Privacy Survey
TrustArc Webinar - 2024 Global Privacy SurveyTrustArc Webinar - 2024 Global Privacy Survey
TrustArc Webinar - 2024 Global Privacy Survey
 
Removing Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software FuzzingRemoving Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software Fuzzing
 

Catalyst MVC

  • 1. Catalyst Elegant Perl MVC Framework Sheeju Alex Exceleron Software
  • 2. Installing Catalyst cpan/cpanm Task::Catalyst ● DBIx::Class Support ● Template::Toolkit Support ● Authentication/Authorization Support ● HTML::FormFu Support OR install from apt-get
  • 3. Setting up Catalyst App catalyst gets rid of repeated work... sheeju@sheeju-exceleron:~/projects$ catalyst.pl Library created "Library" created "Library/script" created "Library/lib" created "Library/root" ……... created "Library/script/library_cgi.pl" created "Library/script/library_fastcgi.pl" created "Library/script/library_server.pl" created "Library/script/library_test.pl" created "Library/script/library_create.pl" Change to application directory and Run "perl Makefile.PL" to make sure your install is complete
  • 4. What is MVC ● Model (Data) ○ Get All Users ○ Get User foo ○ Delete User ● View (Display) ○ Render the page ○ Render user as JSON/XML ● Controller (Glue’s - model and view) ○ Get the Data from Model ○ Check Permission ○ Send data over to the view
  • 5. So what does this mean? * Is full CPAN package * Contains Standalone and server deployment scripts * loads config automatically * testing stubs * helpers to create more parts of your app
  • 6. App Layout ● lib/ - package/class namespaces ○ Library - lib/Library.pm ○ Library::Controller::Root - lib/Library/Controller/Root.pm ○ Model & View - empty for purpose ● root/ - css,js,tt etc store here exposed via /static URL ● script/ - application level script goes here including dev server script ○ library_create.pl ○ library_server.pl ● t/ - Tests goes here (Watch for TDD presentation) fires up app in own dedicated server http://localhost:3000
  • 7. Built-In Server - Start sheeju@sheeju-exceleron:~/projects/Library$ ./script/library_server.pl [debug] Debug messages enabled [debug] Loaded Config "/home/sheeju/projects/Library/library.conf" [debug] Statistics enabled [debug] Loaded plugins: .----------------------------------------------------------------------------. | Catalyst::Plugin::ConfigLoader 0.32 | | Catalyst::Plugin::Unicode::Encoding 2.1 | '----------------------------------------------------------------------------' [debug] Loaded Request Data Handlers: [debug] Loaded dispatcher "Catalyst::Dispatcher" [debug] Loaded engine "Catalyst::Engine" [debug] Found home "/home/sheeju/projects/Library" [debug] Loaded components:
  • 8. Built-In Server - Start [debug] Loaded components: .-----------------------------------------------------------------+------------. | Class | Type | +-------------------------------------------------------------+-------------+ | Library::Controller::Root | instance | '---------------------------------------------------------------+--------------' [debug] Loaded Private actions: .------------------------+-----------------------------------------+--------------. | Private | Class | Method | +----------------------+------------------------------------------+-------------+ | /default | Library::Controller::Root | default | | /index | Library::Controller::Root | index | | /end | Library::Controller::Root | end | '------------------------+-----------------------------------------+--------------' [debug] Loaded Path actions: .-------------------------------------+-------------------------------------. | Path | Private | +-------------------------------------+----------------------------------+ | / | /index | | /... | /default | '-------------------------------------+-------------------------------------' [info] Library powered by Catalyst 5.90053 HTTP::Server::PSGI: Accepting connections at http://0:3000/
  • 10. Request ⇔ Response ● All web applications handle request and generate responses. ● In Catalyst, this happens in special methods called "actions". On every request, Catalyst identifies one or more actions and calls them with special arguments, including a reference to the "context" object that provides a convenient and practical API through which everything else is accomplished. ○ Actions are contained within classes called "controllers", which live in a special path/namespace in the application ● script/library_create.pl controller Something - creates a new controller ○ The only reason to have more than one controller is for organization; you can put all your actions in the Root controller with no loss of features or ability. Controllers are just the containers for actions. ● In the following sections, I describe how Catalyst decides which actions to call on each request ("dispatch") and then explain how to use the supplied context object within them.
  • 11. Dispatch ● Catalyst provides a particularly flexible and powerful mechanism for configuring dispatch rules. ● Rather than having a separate configuration to assign URLs to specific actions, Catalyst uses the actions themselves to determine URL mappings dynamically. ● Each action definition (which is just a Perl subroutine) represents not only a block of code, but also what URL paths apply to it. This is specified in subroutine attributes—a lesser-known Perl feature that provides arbitrary labels that can be used for introspection. ● Catalyst supports a handful of parameterized attributes (Local,Global,Private,Path, LocalRegex,Regex,Chained) to determine the URL path to action mappings in a variety ways sub do_stuff :Attribute1 :Attribute2 :Attribute3('with_argument') { ... Note The first : for the attributes is compulsory, whereas the following are optional.
  • 12. Dispatch :Path :Path Attribute (Absolute Path) sub myaction :Path('/some/place') { my ( $self, $c, @args ) = @_; # do stuff... } ● Regardless of what controller you put it in, the above action would map to all URLs starting with /some/place (http://localhost:3000/some/place with the development server). ● If you omitted the starting slash and used :Path('some/place'), the action would map to a path relative to the namespace of the controller. For example, if it were in Library::Controller:: Foobar, it would be mapped to URL paths starting with /foobar/some/place.
  • 13. Dispatch :Local sub place :Local { my ( $self, $c, @args ) = @_; # do stuff... } ● Instead of using :Path to set the path explicitly, you can set :Local to use the name of the controller and method. ● For instance, the following action, if contained in the controller Library::Controller::Some, would also map to /some/place: ● If it were contained in the controller Library::Controller::Some::Other, it would map to /some/other/place.
  • 14. Dispatch :Path/Local/* :Args sub myaction :Path('/some/place') { my ( $self, $c ) = @_; # do stuff... } ● Actions include subpaths by default, so the above also would match /some/place/blah/foo/1. ● When this happens, the leftover parts of the path are supplied as arguments to the action method ('blah','foo','1'). ● You can use the :Args attribute to limit how deep the action will match subpaths, if at all. ● With an Args value of 0, this action would match only /some/place, but nothing below it: sub myaction :Path('/some/place') :Args(0) { my ( $self, $c ) = @_; # do stuff... }
  • 15. Dispatch :Global & :Private ● :Global ○ works like :Local but ignores the controller name ○ Anywhere - show’s up in the root of your namespace ● :Private ○ Internal Functions ○ No URL ○ Can be invoked only through a $c->forward or a $c->detach within a controller.
  • 16. Dispatch :Regex/:LocalRegex ● path pattern matching, discouraged from using. ● Explore yourself ● You can use Chained instead
  • 17. Dispatch :Chained ● You can configure additional/multiple actions to be called with single requests in any order you like. package MyApp::Controller::Users; use parent 'Catalyst::Controller'; # private sub base :Chained("/") :PathPart("users") :CaptureArgs(0) {} # match /users sub root :Chained("base") :PathPart("") :Args(0) {} # private sub base_user : Chained('base') PathPart('') CaptureArgs(1) { ... } # match /users/1 sub root_user : Chained('base_user') PathPart('') Args(0) { ... } # match /users/1/edit sub user_edit : Chained('base') PathPart('edit') Args(0) { ... } # match /users/1/display sub user_edit : Chained('base') PathPart('display') Args(0) { ... } Users <id> Edit Display URL’s like /users/1/edit, /users/1/display can separate the processing of /users/1 part into its own method.
  • 18. Dispatch Flow ● When a URL matches more than one action, Catalyst picks the one that matches best. ● Exceptions: Called at various stages of every request in addition to the matched action ○ sub default :Private {} - Match everything that doesn’t match ○ sub index :Private {} ○ sub begin :Private {} ○ sub end :Private {} ○ sub auto :Private {} Eg URL: /person/sheeju MyApp::C::Person -> sheeju (finds “sheeju” action inside “person” namespace) MyApp::C::Person -> auto (When found) MyApp::C::Root -> auto (if previous auto returs true continue to the next auto, else kill the request) MyApp::C::Person -> begin (if there is controller’s begin or run Root’s begin) MyApp::C::Person/Root -> end (Finally end, usually to render view)
  • 19. Internal Request Flow Control $c->forward & $c->detach
  • 20. Internal Request Flow Control $c->visit & $c->go
  • 21. The Context Object ($c) ● Controller actions serve as entry points to application code. ● A special per-request object called the "context" is supplied as an argument to every action when it is called by the dispatcher. ● The context object typically is read into a variable named $c, but it could be called anything. Important Objects ● Request ($c->req) – web paranaters, cookies, headers, uploaded files ● Response ($c->res) – set document body, HTTP status code ● Configuration ($c->config) – static project configuration ● Log ($c->log) – print log messages ● Stash ($c->stash) – pass data from model to view ● Session ($c->session) - session store
  • 22. Controller: GET/POST Params $c->req->method - To check the request method (GET/POST) ● GETs end up in passing parms ○ my ($self, $c, $get1, $get2, $get3 ) = @_; OR $c->req->params ● POSTs ○ my $params = $c->req-params; ❏ Pass data to models or store in db ❏ Get Manipulated data and pass it to View (HTML/JSON…) https://metacpan.org/pod/Catalyst::Request
  • 23. Controller Data Stores 1. Stash: short term, lasts one response cycle. Data are references, same form as TT takes for its process() method. 2. Flash: longer term. Used often with the flash_to_stash config set. Useful for storage when handling forms. 3. Session: lasts some time. Can last longer than visitor's login, 2 hrs by default. Don't use same data names as stash, because they interact.
  • 24. Data – Long Term Storage ● Usually handled with a database ○ But check out http://sedition.com/a/2794 ○ The above shows how to read text files. ● Build your tables, and then use the database to build the ORM schema. ● script/library_create.pl model DB DBIC::Schema Library::Schema create=static components=TimeStamp,EncodedColumn 'dbi:Pg: dbname=sheeju sheeju sheeju '{ AutoCommit => 1 }'
  • 25. View TT ● Web/HTML perl script/library_create.pl view Web TT - creates simple TT view perl script/library_create.pl view Web TTSite - creates TT site with layout, header, footer ● JSON - Catalyst::View::JSON
  • 26. OK so now how to render? ● catalyst.pl has already done this for you sub end: ActionClass(‘RenderView’) {} ● RenderView will try to render a template unless body is defined or redirect is in place ● More than one view? $c->config->{default_view} or $c->stash-> {current_view} to decide which one to use
  • 27. ActionClass & ActionRole ● ActionClass ○ A type of Controller that uses bottom-level namespace of an class as an argument to ActionClass attribute ○ Catalyst::Action::RenderView - best example available on default project, execute method is called ○ Use Does instead ● ActionRole (Does) ○ Provides the :Does attribute which applies roles to your action class ○ provides “around execute”, “after execute”, “before execute” method using Moose Methodmodifiers sub foo : Local Does('Moo') { ... } # Catalyst::ActionRole:: sub bar : Local Does('~Moo') { ... } # MyApp::ActionRole::Moo sub baz : Local Does('+MyApp::ActionRole::Moo') { ... } http://www.catalystframework.org/calendar/2012/16 http://metacpan.org/module/Catalyst::Controller::ActionRole
  • 28. AJAX Dispatching ● See Demo on AJAX ActionRole # Make sure this is an AJAX request my $hdr_accept = $c->req->header('Accept') || ''; my $hdr_x_req_with = $c->req->header('X-Requested-With') || ''; if ( $hdr_accept ne 'application/json' && $hdr_x_req_with ne 'XMLHttpRequest') { $c->stash->{ajax} = 0; return $self->$orig(@_); }
  • 29. Authentication use Catalyst qw/ ... Authentication Session Session::Store::FastMmap Session::State::Cookie ... /;
  • 30. Authentication: Config __PACKAGE__->config->{'Plugin::Authentication'} = { default => { credential => { class => ‘Password’, password_field => ‘Password’, password_type => ‘clear’ }, store => { class => ‘DBIx::Class’, user_class => ‘LibraryDB::User’ } } }; $c->authenticate $c->user $c->user_exists() $c->logout
  • 31. References http://wiki.catalystframework.org/wiki/gettingstarted/howtos/chainedexamples.view http://frioux.github.io/Catalyst-Presentation/ http://www.catalystframework.org/calendar/2007/24 http://sedition.com/a/2794 http://sedition.com/a/2733