Intro to Dancer - OSCON 2011

88
Introduction to Dancer A Sinatra-inspired web framework for Perl Mark Allen [email protected] http://byte-me.org http://github.com/mrallen1 http://bitbucket.org/mrallen1 https://metacpan.org/author/MALLEN

description

Many developers who’ve left Perl behind still think that Matt’s Script Archive is state of the art web development techniques for Perl. This talk is intended to showcase some of the most exciting new developments and frameworks for Perl since Catalyst 5.8 was released a few years ago. With a short learning curve and a lot of power under the hood, Dancer deserves a broad audience of developers, including those who may have written off Perl as a relevant language for serious web development.

Transcript of Intro to Dancer - OSCON 2011

Page 1: Intro to Dancer - OSCON 2011

Introduction to Dancer!A Sinatra-inspired web framework for Perl!!!Mark [email protected]!http://byte-me.org!http://github.com/mrallen1!http://bitbucket.org/mrallen1!https://metacpan.org/author/MALLEN!

Page 2: Intro to Dancer - OSCON 2011

The Old Days!

Page 3: Intro to Dancer - OSCON 2011

The Old Days

cgi-lib.pl (1994-1998)!!

Page 4: Intro to Dancer - OSCON 2011

The Old Days

CGI.pm (1995-2011)!!

Page 5: Intro to Dancer - OSCON 2011

The Old Days

mod_perl (1996-2011)!!

Page 6: Intro to Dancer - OSCON 2011

The Old Days

Matt’s Script Archive (1995-2011)!

!Use instead:!

http://nms-cgi.sourceforge.net/!(Thanks London.pm)!

!

Page 7: Intro to Dancer - OSCON 2011

The Old Days

use CGI.pm;!!my $q = CGI->new();!my ($a, $b, $c) = $q->param();!!if ($a !~ /\d+/) {!!print $q->header(-status => ‘400 Bad request’);!!print “<h1>Value of ‘a’ ($a) is not an integer</h1>”;!!exit 0;!

}!# yada, yada!

Page 8: Intro to Dancer - OSCON 2011

The Old Days

.htaccess Hack!!!RewriteEngine On!RewriteBase /abc!!RewriteRule ^(.*)/(.*)/(.*)$ !abc.pl?a=$1;b=$2;c=$3!!

Page 9: Intro to Dancer - OSCON 2011

The Old Days

.htaccess Hack!!# Use Web 2.0 style URLs, but keep CGI interface!RewriteEngine On!RewriteBase /abc!!RewriteRule ^(.*)/(.*)/(.*)$ !abc.pl?a=$1;b=$2;c=$3!!

Page 10: Intro to Dancer - OSCON 2011

The Old Days

.htaccess Hack!!# Use Web 2.0 style URLs, but keep CGI interface!RewriteEngine On!RewriteBase /abc!!RewriteRule ^(.*)/(.*)/(.*)$ !abc.pl?a=$1;b=$2;c=$3!!

Page 11: Intro to Dancer - OSCON 2011

The Old Days

.htaccess Hack!!# Use Web 2.0 style URLs, but keep CGI interface!RewriteEngine On!RewriteBase /abc!!RewriteRule ^(.*)/(.*)/(.*)$ !abc.pl?a=$1;b=$2;c=$3!!

Page 12: Intro to Dancer - OSCON 2011

The Old Days

h"p://flic.kr/p/5TWTR4  

Page 13: Intro to Dancer - OSCON 2011

The Old Days

h"p://flic.kr/p/5TWTR4  

Page 14: Intro to Dancer - OSCON 2011

Move over bacon, now there’s something leaner.!

!

Page 15: Intro to Dancer - OSCON 2011

Move over bacon

Perl 5 Renaissance:!•  Moose!•  DBIx::Class!•  Plack!•  Tons of great new stuff in

core perl 5.10+!!!

Page 16: Intro to Dancer - OSCON 2011

Move over bacon

Do you find Catalyst too !heavyweight or intimidating?!

!

Page 17: Intro to Dancer - OSCON 2011

Move over bacon

!Me too!!

!!

Page 18: Intro to Dancer - OSCON 2011

Move over bacon

Enter Dancer!!

Page 19: Intro to Dancer - OSCON 2011

Move over bacon

Other Sinatra-inspired frameworks:!•  Mojo (Perl – TMTOWTDI)!•  Flask (Python)!•  Fitzgerald (PHP)!•  Express (Node.js)!!

Page 20: Intro to Dancer - OSCON 2011

Move over bacon

Dancer is:!•  Easy to learn!•  Expressive!•  Efficient!

Page 21: Intro to Dancer - OSCON 2011

Dancer is ...!!

Easy to learn!

Page 22: Intro to Dancer - OSCON 2011

Easy to learn

Basic Dancer concepts:!•  One (or more) HTTP verb(s)!•  A route!•  A handler!

Page 23: Intro to Dancer - OSCON 2011

Easy to learn

use Dancer;!!get '/' => sub {! return 'Hello World!\n’;!};!!start;!

Page 24: Intro to Dancer - OSCON 2011

Easy to learn

use Dancer;!!get '/' => sub {! return 'Hello World!\n’;!};!!start;!

Page 25: Intro to Dancer - OSCON 2011

Easy to learn

use Dancer;!!get '/' => sub {! return 'Hello World!\n’;!};!!start;!

Page 26: Intro to Dancer - OSCON 2011

Easy to learn

use Dancer;!!get '/' => sub {! return 'Hello World!\n’;!};!!start;!

Page 27: Intro to Dancer - OSCON 2011

Easy to learn

use Dancer;!!get '/' => sub {! return 'Hello World!\n’;!};!!start;!

Page 28: Intro to Dancer - OSCON 2011

Easy to learn

Page 29: Intro to Dancer - OSCON 2011

Easy to learn

get '/' => sub {! my $db = connect_db();! my $sql = 'select id, title, text from entries order by id desc’;! my $sth = $db->prepare($sql) or die $db->errstr;! $sth->execute or die $sth->errstr;! template 'show_entries.tt', {! 'msg' => get_flash(),! 'add_entry_url' => uri_for('/add'),! 'entries' => $sth->fetchall_hashref('id'),! };!};!

Page 30: Intro to Dancer - OSCON 2011

Easy to learn

get '/' => sub {! my $db = connect_db();! my $sql = 'select id, title, text from entries order by id desc’;! my $sth = $db->prepare($sql) or die $db->errstr;! $sth->execute or die $sth->errstr;! template 'show_entries.tt', {! 'msg' => get_flash(),! 'add_entry_url' => uri_for('/add'),! 'entries' => $sth->fetchall_hashref('id'),! };!};!

Page 31: Intro to Dancer - OSCON 2011

Easy to learn

get '/' => sub {! my $db = connect_db();! my $sql = 'select id, title, text from entries order by id desc’;! my $sth = $db->prepare($sql) or die $db->errstr;! $sth->execute or die $sth->errstr;! template 'show_entries.tt', {! 'msg' => get_flash(),! 'add_entry_url' => uri_for('/add'),! 'entries' => $sth->fetchall_hashref('id'),! };!};!

Page 32: Intro to Dancer - OSCON 2011

Easy to learn

get '/' => sub {! my $db = connect_db();! my $sql = 'select id, title, text from entries order by id desc’;! my $sth = $db->prepare($sql) or die $db->errstr;! $sth->execute or die $sth->errstr;! template 'show_entries.tt', {! 'msg' => get_flash(),! 'add_entry_url' => uri_for('/add'),! 'entries' => $sth->fetchall_hashref('id'),! };!};!

Page 33: Intro to Dancer - OSCON 2011

Easy to learn

get '/' => sub {! my $db = connect_db();! my $sql = 'select id, title, text from entries order by id desc’;! my $sth = $db->prepare($sql) or die $db->errstr;! $sth->execute or die $sth->errstr;! template 'show_entries.tt', {! 'msg' => get_flash(),! 'add_entry_url' => uri_for('/add'),! 'entries' => $sth->fetchall_hashref('id'),! };!};!

Page 34: Intro to Dancer - OSCON 2011

Easy to learn

get '/' => sub {! my $db = connect_db();! my $sql = 'select id, title, text from entries order by id desc’;! my $sth = $db->prepare($sql) or die $db->errstr;! $sth->execute or die $sth->errstr;! template 'show_entries.tt', {! 'msg' => get_flash(),! 'add_entry_url' => uri_for('/add'),! 'entries' => $sth->fetchall_hashref('id'),! };!};!

Page 35: Intro to Dancer - OSCON 2011

Easy to learn

get '/' => sub {! my $db = connect_db();! my $sql = 'select id, title, text from entries order by id desc’;! my $sth = $db->prepare($sql) or die $db->errstr;! $sth->execute or die $sth->errstr;! template 'show_entries.tt', {! 'msg' => get_flash(),! 'add_entry_url' => uri_for('/add'),! 'entries' => $sth->fetchall_hashref('id'),! };!};!

Page 36: Intro to Dancer - OSCON 2011

Easy to learn

get '/' => sub {! my $db = connect_db();! my $sql = 'select id, title, text from entries order by id desc’;! my $sth = $db->prepare($sql) or die $db->errstr;! $sth->execute or die $sth->errstr;! template 'show_entries.tt', {! 'msg' => get_flash(),! 'add_entry_url' => uri_for('/add'),! 'entries' => $sth->fetchall_hashref('id'),! };!};!

Page 37: Intro to Dancer - OSCON 2011

Easy to learn

get '/' => sub {! my $db = connect_db();! my $sql = 'select id, title, text from entries order by id desc’;! my $sth = $db->prepare($sql) or die $db->errstr;! $sth->execute or die $sth->errstr;! template 'show_entries.tt', {! 'msg' => get_flash(),! 'add_entry_url' => uri_for('/add'),! 'entries' => $sth->fetchall_hashref('id'),! };!};!

Page 38: Intro to Dancer - OSCON 2011

Easy to learn

show_entries.tt!!<ul class=entries>! <% IF entries.size %>! <% FOREACH id IN entries.keys.nsort %>! <li><h2><% entries.$id.title %></h2>! <% entries.$id.text %>! <% END %>! <% ELSE %>! <li><em>Unbelievable. No entries here so far</em>! <% END %>!</ul>!!

Page 39: Intro to Dancer - OSCON 2011

Easy to learn

show_entries.tt!!<ul class=entries>! <% IF entries.size %>! <% FOREACH id IN entries.keys.nsort %>! <li><h2><% entries.$id.title %></h2>! <% entries.$id.text %>! <% END %>! <% ELSE %>! <li><em>Unbelievable. No entries here so far</em>! <% END %>!</ul>!!

Page 40: Intro to Dancer - OSCON 2011

Easy to learn

show_entries.tt!!<ul class=entries>! <% IF entries.size %>! <% FOREACH id IN entries.keys.nsort %>! <li><h2><% entries.$id.title %></h2>! <% entries.$id.text %>! <% END %>! <% ELSE %>! <li><em>Unbelievable. No entries here so far</em>! <% END %>!</ul>!!

Page 41: Intro to Dancer - OSCON 2011

Easy to learn

show_entries.tt!!<ul class=entries>! <% IF entries.size %>! <% FOREACH id IN entries.keys.nsort %>! <li><h2><% entries.$id.title %></h2>! <% entries.$id.text %>! <% END %>! <% ELSE %>! <li><em>Unbelievable. No entries here so far</em>! <% END %>!</ul>!!

Page 42: Intro to Dancer - OSCON 2011

Easy to learn

get '/' => sub {! my $db = connect_db();! my $sql = 'select id, title, text from entries order by id desc’;! my $sth = $db->prepare($sql) or die $db->errstr;! $sth->execute or die $sth->errstr;! template 'show_entries.tt', {! 'msg' => get_flash(),! 'add_entry_url' => uri_for('/add'),! 'entries' => $sth->fetchall_hashref('id'),! };!};!

Page 43: Intro to Dancer - OSCON 2011

Easy to learn

show_entries.tt!!<ul class=entries>! <% IF entries.size %>! <% FOREACH id IN entries.keys.nsort %>! <li><h2><% entries.$id.title %></h2>! <% entries.$id.text %>! <% END %>! <% ELSE %>! <li><em>Unbelievable. No entries here so far</em>! <% END %>!</ul>!!

Page 44: Intro to Dancer - OSCON 2011

Easy to learn

show_entries.tt!!<ul class=entries> <!– CSS class -->! <% IF entries.size %>! <% FOREACH id IN entries.keys.nsort %>! <li><h2><% entries.$id.title %></h2>! <% entries.$id.text %>! <% END %>! <% ELSE %>! <li><em>Unbelievable. No entries here so far</em>! <% END %>!</ul>!!

Page 45: Intro to Dancer - OSCON 2011

Easy to learn

Directory structure !

dancr/!├── dancr.pl!├── public!│   └── css!│   └── style.css!└── views! ├── layouts! │   └── main.tt! ├── login.tt! └── show_entries.tt!

Page 46: Intro to Dancer - OSCON 2011

Easy to learn

Directory structure !

dancr/!├── dancr.pl!├── public!│   └── css!│   └── style.css!└── views! ├── layouts! │   └── main.tt! ├── login.tt! └── show_entries.tt!

Page 47: Intro to Dancer - OSCON 2011

Easy to learn

Directory structure !

dancr/!├── dancr.pl!├── public!│   └── css!│   └── style.css!└── views! ├── layouts! │   └── main.tt! ├── login.tt! └── show_entries.tt!

Page 48: Intro to Dancer - OSCON 2011

Easy to learn

Directory structure !

dancr/!├── dancr.pl!├── public!│   └── css!│   └── style.css!└── views! ├── layouts! │   └── main.tt! ├── login.tt! └── show_entries.tt!

Page 49: Intro to Dancer - OSCON 2011

Dancer is...!!

Expressive!

Page 50: Intro to Dancer - OSCON 2011

Expressive

post '/add' => sub {! if ( not session('logged_in') ) {! return send_error("Not logged in", 401);! }!! my $db = connect_db();! my $sql = 'insert into entries (title, text) values (?, ?)’;! my $sth = $db->prepare($sql) or die $db->errstr;! $sth->execute(params->{'title'}, params->{'text'}) or die $sth->errstr;!! set_flash('New entry posted!');! redirect '/’;!};!

Page 51: Intro to Dancer - OSCON 2011

Expressive

post '/add' => sub {! if ( not session('logged_in') ) {! return send_error("Not logged in", 401);! }!! my $db = connect_db();! my $sql = 'insert into entries (title, text) values (?, ?)’;! my $sth = $db->prepare($sql) or die $db->errstr;! $sth->execute(params->{'title'}, params->{'text'}) or die $sth->errstr;!! set_flash('New entry posted!');! redirect '/’;!};!

Page 52: Intro to Dancer - OSCON 2011

Expressive

post '/add' => sub {! if ( not session('logged_in') ) {! return send_error("Not logged in", 401);! }!! my $db = connect_db();! my $sql = 'insert into entries (title, text) values (?, ?)’;! my $sth = $db->prepare($sql) or die $db->errstr;! $sth->execute(params->{'title'}, params->{'text'}) or die $sth->errstr;!! set_flash('New entry posted!');! redirect '/’;!};!

Page 53: Intro to Dancer - OSCON 2011

Expressive

post '/add' => sub {! if ( not session('logged_in') ) {! return send_error("Not logged in", 401);! }!! my $db = connect_db();! my $sql = 'insert into entries (title, text) values (?, ?)’;! my $sth = $db->prepare($sql) or die $db->errstr;! $sth->execute(params->{'title'}, params->{'text'}) or die $sth->errstr;!! set_flash('New entry posted!');! redirect '/’;!};!

Page 54: Intro to Dancer - OSCON 2011

Expressive

post '/add' => sub {! if ( not session('logged_in') ) {! return send_error("Not logged in", 401);! }!! my $db = connect_db();! my $sql = 'insert into entries (title, text) values (?, ?)’;! my $sth = $db->prepare($sql) or die $db->errstr;! $sth->execute(params->{'title'}, params->{'text'}) or die $sth->errstr;!! set_flash('New entry posted!');! redirect '/’;!};!

Page 55: Intro to Dancer - OSCON 2011

Expressive

post '/add' => sub {! if ( not session('logged_in') ) {! return send_error("Not logged in", 401);! }!! my $db = connect_db();! my $sql = 'insert into entries (title, text) values (?, ?)’;! my $sth = $db->prepare($sql) or die $db->errstr;! $sth->execute(params->{'title'}, params->{'text'}) or die $sth->errstr;!! set_flash('New entry posted!');! redirect '/’;!};!

Page 56: Intro to Dancer - OSCON 2011

Expressive

post '/add' => sub {! if ( not session('logged_in') ) {! return send_error("Not logged in", 401);! }!! my $db = connect_db();! my $sql = 'insert into entries (title, text) values (?, ?)’;! my $sth = $db->prepare($sql) or die $db->errstr;! $sth->execute(params->{'title'}, params->{'text'}) or die $sth->errstr;!! set_flash('New entry posted!');! redirect '/’;!};!

Page 57: Intro to Dancer - OSCON 2011

Expressive

Little Bobby Tables!

h"p://xkcd.com/327/  

Page 58: Intro to Dancer - OSCON 2011

Expressive

post '/add' => sub {! if ( not session('logged_in') ) {! return send_error("Not logged in", 401);! }! # http://bobby-tables.com! my $db = connect_db();! my $sql = 'insert into entries (title, text) values (?, ?)’;! my $sth = $db->prepare($sql) or die $db->errstr;! $sth->execute(params->{'title'}, params->{'text'}) or die $sth->errstr;!! set_flash('New entry posted!');! redirect '/’;!};!

Page 59: Intro to Dancer - OSCON 2011

Expressive

Page 60: Intro to Dancer - OSCON 2011

Expressive

Configuration !•  Session Engine!•  Template Engine!•  Logging !•  Plugins!

Page 61: Intro to Dancer - OSCON 2011

Expressive

Configuration Examples!set 'session' => 'Simple'; set 'template' =>'template_toolkit'; set 'logger' => 'console'; set 'log' => 'debug'; set 'show_errors' => 1; !

Page 62: Intro to Dancer - OSCON 2011

Expressive

Configuration Examples!set 'session' => 'Simple'; set 'template' =>'template_toolkit'; set 'logger' => 'console'; set 'log' => 'debug'; set 'show_errors' => 1; !

Page 63: Intro to Dancer - OSCON 2011

Expressive

Configuration Use any non-reserved key/value pair.set 'username' => 'admin'; set 'password' => 'password';!!

Page 64: Intro to Dancer - OSCON 2011

Expressive

Routes with regex!!get qr{\A\/(?<code>[A-Za-z0-9]+)\Z} => sub {! my $decode = decode_base36( uc captures->{'code'}! );! ...;!};!

Page 65: Intro to Dancer - OSCON 2011

Expressive

Routes with regex!!get qr{\A\/(?<code>[A-Za-z0-9]+)\Z} => sub {! my $decode = decode_base36( uc captures->{'code'}! );! ...;!};!

Page 66: Intro to Dancer - OSCON 2011

Expressive

Routes with regex!!use v5.10; get qr{\A\/(?<code>[A-Za-z0-9]+)\Z} => sub {! my $decode = decode_base36( uc captures->{'code'}! );! ...;!};!

Page 67: Intro to Dancer - OSCON 2011

Expressive

Routes with regex!!use v5.10; get qr{\A\/(?<code>[A-Za-z0-9]+)\Z} => sub {! my $decode = decode_base36( uc captures->{'code'}! );! ...;!};!

Page 68: Intro to Dancer - OSCON 2011

Expressive

Routes with named params!!get '/:code/stats' => sub {! my $decode = decode_base36( uc params->{'code'} );! ...;!};!

Page 69: Intro to Dancer - OSCON 2011

Expressive

Routes with named params!!get '/:code/stats' => sub {! my $decode = decode_base36( uc params->{'code'} );! ...;!};!

Page 70: Intro to Dancer - OSCON 2011

Expressive

Routes with named params!!get qr{^/(.+)/stats$} => sub { params(‘code’) = $1; # input sanity goes here ...; };!

Page 71: Intro to Dancer - OSCON 2011

Expressive

use CGI.pm;!!my $q = CGI->new();!my ($a, $b, $c) = $q->param();!!if ($a !~ /\d+/) {!!print $q->header(-status => ‘400 Bad request’);!!print “<h1>Value of ‘a’ ($a) is not an integer</h1>”;!!exit 0;!

}!# yada, yada!

Page 72: Intro to Dancer - OSCON 2011

Expressive

!!!!use v5.10; use Dancer; !get qr{/(?<a>\d+)/(?<b>.+)/(?<c>.+)} => sub {! # Route will only match if a is an integer! # No more sanitation/validation necessary ...; };!!

Page 73: Intro to Dancer - OSCON 2011

Dancer is...!

Efficient!

Page 74: Intro to Dancer - OSCON 2011

Efficient

any ['get', 'post'] => '/login' => sub {! my $err;! if ( request->is_post ) {! if ( params->{'username'} ne setting('username') ) {! $err = "Invalid username”;! }! elsif ( params->{'password'} ne setting('password') ) {! $err = "Invalid password”;! }! else {! session 'logged_in' => true;! set_flash('You are logged in.');! redirect '/’;! }! }! template 'login.tt', {! 'err' => $err,! };!};!

Page 75: Intro to Dancer - OSCON 2011

Efficient

any ['get', 'post'] => '/login' => sub {! my $err;! if ( request->is_post ) {! if ( params->{'username'} ne setting('username') ) {! $err = "Invalid username”;! }! elsif ( params->{'password'} ne setting('password') ) {! $err = "Invalid password”;! }! else {! session 'logged_in' => true;! set_flash('You are logged in.');! redirect '/’;! }! }! template 'login.tt', {! 'err' => $err,! };!};!

Page 76: Intro to Dancer - OSCON 2011

Efficient

any ['get', 'post'] => '/login' => sub {! my $err;! if ( request->is_post ) {! if ( params->{'username'} ne setting('username') ) {! $err = "Invalid username”;! }! elsif ( params->{'password'} ne setting('password') ) {! $err = "Invalid password”;! }! else {! session 'logged_in' => true;! set_flash('You are logged in.');! redirect '/’;! }! }! template 'login.tt', {! 'err' => $err,! };!};!

Page 77: Intro to Dancer - OSCON 2011

Efficient

any ['get', 'post'] => '/login' => sub {! my $err;! if ( request->is_post ) {! if ( params->{'username'} ne setting('username') ) {! $err = "Invalid username”;! }! elsif ( params->{'password'} ne setting('password') ) {! $err = "Invalid password”;! }! else {! session 'logged_in' => true;! set_flash('You are logged in.');! redirect '/’;! }! }! template 'login.tt', {! 'err' => $err,! };!};!

Page 78: Intro to Dancer - OSCON 2011

Efficient

any ['get', 'post'] => '/login' => sub {! my $err;! if ( request->is_post ) {! if ( params->{'username'} ne setting('username') ) {! $err = "Invalid username”;! }! elsif ( params->{'password'} ne setting('password') ) {! $err = "Invalid password”;! }! else {! session 'logged_in' => true;! set_flash('You are logged in.');! redirect '/’;! }! }! template 'login.tt', {! 'err' => $err,! };!};!

Page 79: Intro to Dancer - OSCON 2011

Efficient

any ['get', 'post'] => '/login' => sub {! my $err;! if ( request->is_post ) {! if ( params->{'username'} ne setting('username') ) {! $err = "Invalid username”;! }! elsif ( params->{'password'} ne setting('password') ) {! $err = "Invalid password”;! }! else {! session 'logged_in' => true;! set_flash('You are logged in.');! redirect '/’;! }! }! template 'login.tt', {! 'err' => $err,! };!};!

Page 80: Intro to Dancer - OSCON 2011

Efficient

any ['get', 'post'] => '/login' => sub {! my $err;! if ( request->is_post ) {! if ( params->{'username'} ne setting('username') ) {! $err = "Invalid username”;! }! elsif ( params->{'password'} ne setting('password') ) {! $err = "Invalid password”;! }! else {! session 'logged_in' => true;! set_flash('You are logged in.');! redirect '/’;! }! }! template 'login.tt', {! 'err' => $err,! };!};!

Page 81: Intro to Dancer - OSCON 2011

Efficient

any ['get', 'post'] => '/login' => sub {! my $err;! if ( request->is_post ) {! if ( params->{'username'} ne setting('username') ) {! $err = "Invalid username”;! }! elsif ( params->{'password'} ne setting('password') ) {! $err = "Invalid password”;! }! else {! session 'logged_in' => true;! set_flash('You are logged in.');! redirect '/’;! }! }! template 'login.tt', {! 'err' => $err,! };!};!

Page 82: Intro to Dancer - OSCON 2011

Efficient

Hook Before / After!•  De/Serialization!•  Rendering!•  Template!•  Errors!

Page 83: Intro to Dancer - OSCON 2011

Efficient

Forward!!get '/demo/foo/:bar' => sub {! my $bar = param->{'bar'};! # magically use demo DB! ...;! return forward "/foo/$bar";!};! !

Page 84: Intro to Dancer - OSCON 2011

Efficient

Prefix!!prefix '/user'; # begins scope!!get '/view/:id' => sub { ...; };!post '/add' => sub { ...; };!any ['get', 'post'] => '/edit/:id' => sub { ...; };!!prefix undef; # ends scope!!get '/view/:id' => sub { ...; };!

Page 85: Intro to Dancer - OSCON 2011

Efficient

Dancer Plugins add keywords!•  Auto-create RSS feeds!•  Integrate Twitter for authN!•  DBIx::Class!•  DWIM CRUD apps!•  ...and more!

Page 86: Intro to Dancer - OSCON 2011

Dancer is...!!

Awesome!!

Page 87: Intro to Dancer - OSCON 2011

Awesome

Source code:!hg clone https://bitbucket.org/mrallen1/dancr!!

See also:!https://metacpan.org/module/Dancer!!

Install:!curl -L http://cpanmin.us | perl - Dancer YAML Template !

!!

Page 88: Intro to Dancer - OSCON 2011

Awesome

Thank You!!!