Modern Perl Web Development with Dancer

137
Modern Perl Web Development with Dancer

Transcript of Modern Perl Web Development with Dancer

Page 1: Modern Perl Web Development with Dancer

Modern Perl Web

Development with Dancer

Page 2: Modern Perl Web Development with Dancer

Some History

● 20 years ago most web development was done with Perl & CGI

● 10-15 years ago that changed● Competition in the web development space● Other (better?) technologies

Page 3: Modern Perl Web Development with Dancer

What Changed?

● Hard to maintain● CGI used less● No "new version" for twenty years● Technologies with less historical baggage

Page 4: Modern Perl Web Development with Dancer

What Else Changed?

● Perl changed a lot● Major release every year● Powerful extension libraries● CPAN - Perl's killer app

Page 5: Modern Perl Web Development with Dancer

The Plan

● Show that Perl is still good for web development● Demonstrate some Modern Perl tools● Show Perl working with modern web

technology– Bootstrap– jQuery– Mustache

Page 6: Modern Perl Web Development with Dancer

The App

Page 7: Modern Perl Web Development with Dancer

Perl Web Tools

● PSGI/Plack– Web server interaction

● Dancer2– Web framework

Page 8: Modern Perl Web Development with Dancer

Other Perl Tools

● DBIx::Class– ORM

● Template Toolkit– Templating engine

● Moose– OO framework

Page 9: Modern Perl Web Development with Dancer

Other Tools

● Bootstrap– CSS framework

● jQuery– Javascript framework

● Mustache– Javascript templates

Page 10: Modern Perl Web Development with Dancer

PSGI/Plack

Page 11: Modern Perl Web Development with Dancer

PSGI

● Perl Server Gateway Interface● CGI++● Interface between Perl app and web server● A lot like Python's WSGI

Page 12: Modern Perl Web Development with Dancer

PSGI Application

my $app = sub { my $env = shift;

return [ 200, [ Content_type => 'text/plain' ], [ 'Hello world!' ], ];}

Page 13: Modern Perl Web Development with Dancer

PSGI Specification

● Subroutine reference● Passed a hash reference● Returns a reference to a three-element array

● Status code● Array of header name/value pairs● Array containing body

Page 14: Modern Perl Web Development with Dancer

PSGI Advantages

● Separates development from deployment● Easier debugging & testing● Middleware

Page 15: Modern Perl Web Development with Dancer

Plack

● Plack is a toolbox for working with PSGI● A lot like Ruby's Rack● Development web server (plackup)● Middleware● Apps● Adapters for various deployment environments

Page 16: Modern Perl Web Development with Dancer

Writing a PSGI Application

● You can write your application in "raw" Plack– Plack::Request– Plack::Response

● But unless it's very simple you should use a framework

● Makes your life easier

Page 17: Modern Perl Web Development with Dancer

Frameworks in Perl

● Catalyst● Mojolicious● Ox● Dancer(2)

– Our choice

Page 18: Modern Perl Web Development with Dancer

Dancer2

● Simple route-based framework● Plenty of plugins available

– Sessions– Authentication– Database access

● Good balance between ease and power

Page 19: Modern Perl Web Development with Dancer

Step 1 - Your Dancer2 App

Page 20: Modern Perl Web Development with Dancer

Creating Your Dancer2 App

● Command line program to create an app skeleton

● dancer2 gen -a Todo

● Many files put into Todo directory

Page 21: Modern Perl Web Development with Dancer

Running Your Dancer2 App

● Run your web app in a development web server– plackup

● cd Todo

● plackup bin/app.psgi

● Go to http://localhost:5000/

Page 22: Modern Perl Web Development with Dancer

Running Your Dancer2 App

Page 23: Modern Perl Web Development with Dancer

Step 2 - Bootstrap

Page 24: Modern Perl Web Development with Dancer

Bootstrap

● The default Dancer2 index page looks nice● But we can do better● Bootstrap is a CSS framework

– From Twitter

● Easy improvements to web pages● http://getbootstrap.com

Page 25: Modern Perl Web Development with Dancer

Pages and Layouts

● Dancer2 stores page templates in views– views/index.tt

● And layouts in views/layouts– views/layouts/main.tt

● These are Template Toolkit files

Page 26: Modern Perl Web Development with Dancer

Changing Template Engine

● Dancer2's default templating engine is Template::Simple

● But we use the Template Toolkit instead● Change templating engine in config.yml

Page 27: Modern Perl Web Development with Dancer

config.yml (before)

template: "simple"

# template: "template_toolkit"# engines:# template:# template_toolkit:# start_tag: '<%'# end_tag: '%>'

Page 28: Modern Perl Web Development with Dancer

config.yml (after)

# template: "simple"

template: "template_toolkit"engines: template: template_toolkit: start_tag: '<%' end_tag: '%>'

Page 29: Modern Perl Web Development with Dancer

Template Toolkit

● Perl's de-facto standard templating engine● Text templates● Processing tags marked with <% ... %>● Simple programming language

– Variables– Loops

Page 30: Modern Perl Web Development with Dancer

Layouts vs Pages

● A page is a single page● A layout is a wrapper around all of your pages● Consistant look and feel● <% content %> tag where page content is

inserted

Page 31: Modern Perl Web Development with Dancer

Bootstrap Changes

● Edit views/layouts/main.tt● Steal HTML from Bootstrap examples page● Insert the <% content %> tag● Replace views/index.tt

– <p>Page content</p>

Page 32: Modern Perl Web Development with Dancer

Bootstrapped Version

Page 33: Modern Perl Web Development with Dancer

Step 3 - Plack Middleware

Page 34: Modern Perl Web Development with Dancer

Plack Middleware

● Plack Middleware wraps around your PSGI app● Can alter the request on the way in● Can alter the response on the way out● PSGI's simple specification makes this easy

Page 35: Modern Perl Web Development with Dancer

Plack Middleware Onion

Page 36: Modern Perl Web Development with Dancer

Middleware Power

● Middleware can skip the app● Go straight to the response● Authentication● Serving static files

Page 37: Modern Perl Web Development with Dancer

Static Files

● Your app will have static files– Images– CSS– Javascript

● Serve these from the filesystem● No need to go through the app● Use Plack::Middleware::Static

Page 38: Modern Perl Web Development with Dancer

Your Dancer2 App

#!/usr/bin/env perl

use strict;use warnings;use FindBin;use lib "$FindBin::Bin/../lib";

use Todo;Todo->to_app;

Page 39: Modern Perl Web Development with Dancer

Adding Middleware

● Plack::Builder is used to load and configure middleware● Use the builder and enable keywords

use Plack::Builder; my $app = ...;

builder { enable 'Some::Middleware'; $app; };

Page 40: Modern Perl Web Development with Dancer

Plack::Middleware::Static

use Plack::Builder;use Todo;

builder { enable 'Plack::Middleware::Static', path => qr{^/(javascripts|css)/}, root => './public/'; Todo->to_app;};

Page 41: Modern Perl Web Development with Dancer

Plack::Middleware::Static

● Serve static files directly– Don't go through the app

● If the path matches qr{^/(javascripts|css)/}

● Serve files from ./public– Note the "."

Page 42: Modern Perl Web Development with Dancer

Our App

Page 43: Modern Perl Web Development with Dancer

Step 4: Adding Data

Page 44: Modern Perl Web Development with Dancer

Displaying Data

● We want to display data– Todo item

● Start simple● Hard-code data in Todo.pm● Read that data in index.tt

Page 45: Modern Perl Web Development with Dancer

Data in Todo.pm

my @items = ({ title => 'Todo item 1', description => 'Do something interesting', due => '2016-08-24', done => 1,}, { ...});

Page 46: Modern Perl Web Development with Dancer

Munge the Data

my $dt_parser = DateTime::Format::Strptime->new( pattern => '%Y-%m-%d',);

my $now = DateTime->now;

foreach my $item (@items) { $item->{due} = $dt_parser->parse_datetime($item->{due}); $item->{overdue} = $item->{due} <= $now;}

Page 47: Modern Perl Web Development with Dancer

Pass Data to Template

template 'index', { items => \@items };

Page 48: Modern Perl Web Development with Dancer

Display Data in Template<% FOREACH item IN items -%><div class="panel panel-<% IF item.done %>success<% ELSIF item.overdue %>danger<% ELSE %>info<% END %>"> <div class="panel-heading"> <h3 class="panel-title"><% item.title %></h3> </div> <div class="panel-body"><p><% item.description %></p> <p class="text-right"> <small>Due: <% item.due.strftime('%A %d %B') %></small> </p> </div></div><% END -%>

Page 49: Modern Perl Web Development with Dancer

Our App

Page 50: Modern Perl Web Development with Dancer

Step 5 - Getting Data from a

Database

Page 51: Modern Perl Web Development with Dancer

Dynamic Data

● That's nice, but we don't have a static Todo list– Hopefully

● Need to get the data from a database

Page 52: Modern Perl Web Development with Dancer

Define Database Table

CREATE TABLE item ( id integer not null auto_increment primary key, title varchar(200) not null, description text, due datetime, done boolean not null default false) Engine=InnoDB;

Page 53: Modern Perl Web Development with Dancer

Database Interfaces with Perl

● The standard Perl database interface is called DBI

● But we can do better than that● We will use DBIx::Class

– Based on DBI

● ORM

Page 54: Modern Perl Web Development with Dancer

Object Relational Mapping

● Maps between OO concepts and DB concepts● table : class● row : object● column : attribute● Write less SQL!

Page 55: Modern Perl Web Development with Dancer

Database Metadata

● DBIx::Class needs a set of Perl classes● You can write these yourself● Or you can automatically generate them● dbicdump extracts metadata from your

database● Generates the classes

Page 56: Modern Perl Web Development with Dancer

todo.conf

schema_class Todo::Schema

<connect_info> dsn dbi:mysql:todo user todouser pass sekr1t</connect_info>

<loader_options> dump_directory ./Todo/lib components InflateColumn::DateTime use_moose 1</loader_options>

Page 57: Modern Perl Web Development with Dancer

Generating Classes

● Run dbicdump from your command line● dbicdump todo.conf

● Dumps stuff into Todo/lib

Page 58: Modern Perl Web Development with Dancer

Generated Classes

● Todo/lib/Todo/Schema.pm– Main connection object

● Todo/lib/Todo/Schema/Result/Item.pm– One row from the item table

Page 59: Modern Perl Web Development with Dancer

Dancer2 and DBIC

● Use a plugin to access DBIC from Dancer2● Dancer2::Plugin::DBIC● Configure connection in config.yml

Page 60: Modern Perl Web Development with Dancer

config.yml

plugins: DBIC: default: schema_class: Todo::Schema dsn: dbi:mysql:dbname=todo user: todouser pass: sekr1t

Page 61: Modern Perl Web Development with Dancer

Todo.pm

use Dancer2::Plugin::DBIC;

get '/' => sub { # Removed hard-coded data # Get data from database instead my @items = schema->resultset('Item')->all;

template 'index', { items => \@items };};

Page 62: Modern Perl Web Development with Dancer

index.tt

● No changes● Which is a bonus● Previously we passed hashrefs● Now we pass objects● TT uses the same syntax for both

Page 63: Modern Perl Web Development with Dancer

TT Hashes vs Objects

● Hashref– Perl: $item->{key}– TT: item.key

● Object– Perl: $item->attribute– TT: item.attribute

● Handy for prototyping

Page 64: Modern Perl Web Development with Dancer

Our App

Page 65: Modern Perl Web Development with Dancer

Step 6 - Displaying with

Javascript

Page 66: Modern Perl Web Development with Dancer

Flexibility

● Generating the HTML using TT code in the template isn't very flexible

● Write a JSON data structure instead– JSON

● Generate the HTML from the JSON– Mustache

● Process Mustache template on page load– jQuery

Page 67: Modern Perl Web Development with Dancer

JSON<script>var items = [<% FOREACH item IN items -%>{ counter: <% loop.count %>, title: "<% item.title %>", description: "<% item.description %>", done: <% item.done %>, overdue: <% item.overdue %>, due: "<% item.due.strftime('%A %d %B') %>", panel_class: "<% IF item.done %>success <% ELSIF item.overdue %>danger <% ELSE %>info<% END %>",}<% UNLESS loop.last %>,<% END %><% END -%>];</script>

Page 68: Modern Perl Web Development with Dancer

Somewhere to Put the List

<div id="list"></div>

Page 69: Modern Perl Web Development with Dancer

Mustache

● Simple Javascript templating language● Similar features to Template Toolkit● Define templates in <script> tags● Render with Mustache.render()

Page 70: Modern Perl Web Development with Dancer

Mustache Template

<script id="item-template" type="text/template">{{#items}}<div class="panel panel-{{panel_class}}"> <div class="panel-heading"> <h3 class="panel-title">{{counter}}: {{title}}</h3> </div> <div class="panel-body"><p>{{description}}</p> <p class="text-right"><small>Due: {{due}}</small></p> </div></div>{{/items}}</script>

Page 71: Modern Perl Web Development with Dancer

Rendering the Template

<script>$( document ).ready(function() { var template = $('#item-template').html(); var list = Mustache.render( template, { items: items } ); $('#list').append(list);});</script>

Page 72: Modern Perl Web Development with Dancer

Our App

Page 73: Modern Perl Web Development with Dancer

Step 7 - Show/Hide Done Items

Page 74: Modern Perl Web Development with Dancer

Our First Feature

● Show/hide done items– Bootstrap Switch– jQuery

● Save the state in a cookie– js.cookie

● No Perl in this step

Page 75: Modern Perl Web Development with Dancer

Add the Switch

<p>Completed items: <input type="checkbox" name="show-complete" data-on-text="Show" data-off-text="Hide" data-size="small"></p>

Page 76: Modern Perl Web Development with Dancer

Set Up the Switch

function set_up_switch(the_switch, curr_state) { the_switch.on('switchChange.bootstrapSwitch', function(event, new_state) { show_list(new_state); Cookies.set('show-complete', new_state); });

the_switch.bootstrapSwitch( 'state', curr_state );}

Page 77: Modern Perl Web Development with Dancer

Some Other Helpersfunction generate_list(div, list_items) { var template = $('#item-template').html(); div.append( Mustache.render(template, { items: list_items }) );}

function show_list(state) { if (state) { $(".panel-success").show(1000); } else { $(".panel-success").hide(1000); }}

Page 78: Modern Perl Web Development with Dancer

Document Ready$( document ).ready(function() { list_div = $("#list");

list_div.hide(); generate_list(list_div, items); # Gotcha! cook_state = Cookies.get('show-complete') == 'true'; set_up_switch( $("[name='show-complete']"), cook_state ); show_list(cook_state); list_div.show();});

Page 79: Modern Perl Web Development with Dancer

Our App

Page 80: Modern Perl Web Development with Dancer

Our App

Page 81: Modern Perl Web Development with Dancer

Step 8 - Mark Items Done

Page 82: Modern Perl Web Development with Dancer

An Important Feature

● Need to mark items as done● Add "done" button to page

– Bootstrap Glyphicons

● Update status in database● Redisplay page

Page 83: Modern Perl Web Development with Dancer

More Data Needed

● Add id to JSON● Add button_type to JSON

– Controls colour of button

Page 84: Modern Perl Web Development with Dancer

index.tt<% FOREACH item IN items -%>{ counter: <% loop.count %>, id: <% item.id %>, title: "<% item.title %>", description: "<% item.description %>", done: <% item.done %>, overdue: <% item.overdue %>, due: "<% item.due.strftime('%A %d %B') %>", panel_class: "<% IF item.done %>success <% ELSIF item.overdue %>danger <% ELSE %>info<% END %>", button_type: "<% IF item.done %>success <% ELSIF item.overdue %>danger <% ELSE %>primary<% END %>"}<% UNLESS loop.last %>,<% END %><% END -%>

Page 85: Modern Perl Web Development with Dancer

Display Button<script id="item-template" type="text/template">{{#items}}<div class="panel panel-{{panel_class}}"> <div class="panel-heading"> <h3 class="panel-title">{{counter}}: {{title}} {{^done}}"> <form style="float:right" method="post" action="/done/{{id}}"> <button type="submit" class="btn btn-{{button_type}} btn-lg"> <span class="glyphicon glyphicon-ok"></span> </button> </form>{{/done}} </h3> </div> <div class="panel-body"> <p>{{description}}</p> <p class="text-right"><small>Due: {{due}}</small></p> </div></div>{{/items}}</script>

Page 86: Modern Perl Web Development with Dancer

POST vs GET

● Done action is POST● Alters the database● Protection from crawlers

Page 87: Modern Perl Web Development with Dancer

Marking Item Done

● Find item in database– Not found -> 404

● Update status● Redirect to home page

Page 88: Modern Perl Web Development with Dancer

Todo.pm

post '/done/:id' => sub { my $id = route_parameters->get('id'); my $item = schema->resultset('Item')->find($id);

unless ($item) { status 404; return "Item $id not found"; }

$item->update({ done => 1 }); redirect('/');};

Page 89: Modern Perl Web Development with Dancer

Our App

Page 90: Modern Perl Web Development with Dancer

Step 9 - Add New Tasks

Page 91: Modern Perl Web Development with Dancer

Add Todo Items

● Todo lists get longer● Need to add new items● New form to capture information● Save to database● Handle missing information

Page 92: Modern Perl Web Development with Dancer

Add an Add Button

<span style="float:right"> <a href="/add"> <button type="submit" class="btn btn-primary btn-lg"> <span class="glyphicon glyphicon-plus"></span> </button> </a></span>

Page 93: Modern Perl Web Development with Dancer

Display Add Form

● Two actions on /add● Display form● Process form data● Use HTTP method to differentiate● GET vs POST

Page 94: Modern Perl Web Development with Dancer

Todo.pm - GET

get '/add' => sub { template 'add';};

Page 95: Modern Perl Web Development with Dancer

Todo.pm - POSTpost '/add' => sub { my $item; my @errors; my %cols = ( title => 'Title', description => 'Description', due => 'Due Date', ); foreach (qw[title description due]) { unless ($item->{$_} = body_parameters->get($_)) { push @errors, $cols{$_}; } }

if (@errors) { return template 'add', { errors => \@errors, item => $item }; }

resultset('Item')->create($item); redirect('/');};

Page 96: Modern Perl Web Development with Dancer

add.tt (Error Display)

<% IF errors.size -%><div class="alert alert-danger" role="alert">The following inputs were missing:<ul><% FOREACH error IN errors -%> <li><% error %></li><% END -%></ul></div><% END -%>

Page 97: Modern Perl Web Development with Dancer

add.tt (Data Capturing)<form method="post"> <div class="form-group"> <label for="title">Title</label> <input type="text" class="form-control" id="title" name="title" placeholder="Title" value="<% item.title %>"> </div> <div class="form-group"> <label for="description">Description</label> <textarea class="form-control" rows="5" id="description" name="description" placeholder="Description"> <% item.description %> </textarea> </div> <div class="form-group"> <label for="due">Date Due</label> <input type="date" id="due" name="due" value="<% item.due %>"> </div> <button type="submit" class="btn btn-default">Save</button></form>

Page 98: Modern Perl Web Development with Dancer

Our App

Page 99: Modern Perl Web Development with Dancer

Our App

Page 100: Modern Perl Web Development with Dancer

Our App

Page 101: Modern Perl Web Development with Dancer

Step 10 - Logging In

Page 102: Modern Perl Web Development with Dancer

Logging In

● Only valid users should be able to edit the list● Other visitors can view the list● Use sessions to store login details

Page 103: Modern Perl Web Development with Dancer

Add Login Form and Logout Link to main.tt

<li><% IF session.user %> <a href="/logout">Log out</a><% ELSE %> <form class="navbar-form navbar-right" method="post" action="/login"> <div class="form-group form-group-sm"> <input type="text" class="form-control" name="user" placeholder="User"> </div> <div class="form-group form-group-sm"> <input type="password" class="form-control" name="password" placeholder="Password"> </div> <button type="submit" class="btn btn-default btn-xs">Log in</button> </form><% END %></li>

Page 104: Modern Perl Web Development with Dancer

Todo.pm - Logging In

post '/login' => sub { my $user = body_parameters->get('user'); my $pass = body_parameters->get('password');

# TODO: Make this better! if ($pass eq 'letmein') { session user => $user; } redirect '/';};

Page 105: Modern Perl Web Development with Dancer

Todo.pm - Logging Out

get '/logout' => sub { session user => undef; redirect '/';};

Page 106: Modern Perl Web Development with Dancer

Display Appropriate Buttons - Add

<% IF session.user -%> <span style="float:right"> <a href="/add"> <button type="submit" class="btn btn-primary btn-lg"> <span class="glyphicon glyphicon-plus"></span> </button> </a> </span><% END -%>

Page 107: Modern Perl Web Development with Dancer

Display Appropriate Buttons - Mark Done

<% IF session.user %>{{^done}} <form style="float:right" method="post" action="/done/{{id}}"> <button type="submit" class="btn btn-{{button_type}} btn-lg"> <span class="glyphicon glyphicon-ok"></span> </button> </form>{{/done}}<% END %>

Page 108: Modern Perl Web Development with Dancer

Our App

Page 109: Modern Perl Web Development with Dancer

Our App

Page 110: Modern Perl Web Development with Dancer

Step 11 - Edit Tasks

Page 111: Modern Perl Web Development with Dancer

Editing Tasks

● Tasks aren't fixed in stone● Deadlines change● Details change● Fix typos● Delete tasks

Page 112: Modern Perl Web Development with Dancer

Add Edit and Delete Buttons<div class="panel-heading"><h3 class="panel-title">{{counter}}: {{title}}<% IF session.user %> {{^done}}<form style="float:right" method="post" action="/done/{{id}}"> <button title="Mark Done" type="submit" class="btn btn-{{button_type}} btn-lg"> <span class="glyphicon glyphicon-ok"></span> </button> <a href="/edit/{{id}}"><button title="Edit" type="button" class="btn btn-{{button_type}} btn-lg"> <span class="glyphicon glyphicon-pencil"></span> </button></a> <a href="/delete/{{id}}"><button title="Delete" type="button" class="btn btn-{{button_type}} btn-lg"> <span class="glyphicon glyphicon-remove"></span> </button></a></form>{{/done}}<% END %></h3></div>

Page 113: Modern Perl Web Development with Dancer

Add Edit and Delete Buttons

Page 114: Modern Perl Web Development with Dancer

Deletion Codeget '/delete/:id' => sub { my $id = route_parameters->get('id'); my $item = find_item_by_id($id) or return "Item $id not found";

template 'delete', { item => $item };};

post '/delete/:id' => sub { my $id = route_parameters->get('id'); my $item = find_item_by_id($id) or return "Item $id not found";

$item->delete; redirect '/';};

Page 115: Modern Perl Web Development with Dancer

Deletion Check

Page 116: Modern Perl Web Development with Dancer

Edit Code (GET)

get '/edit/:id' => sub { my $id = route_parameters->get('id'); my $item = find_item_by_id($id) or return "Item $id not found";

template 'add', { item => $item };};

Page 117: Modern Perl Web Development with Dancer

Edit Code (POST)post '/edit/:id' => sub { my $id = route_parameters->get('id'); my $item = find_item_by_id($id) or return "Item $id not found";

my $new_item; my @errors; my %cols = ( title => 'Title', description => 'Description', due => 'Due Date', ); foreach (qw[title description due]) { unless ($new_item->{$_} = body_parameters->get($_)) { push @errors, $cols{$_}; } }

if (@errors) { return template 'add', { errors => \@errors, item => $new_item }; }

$item->update($new_item); redirect('/');};

Page 118: Modern Perl Web Development with Dancer

find_item_by_id($id)

sub find_item_by_id { my ($id) = @_; my $item = schema->resultset('Item')->find($id);

unless ($item) { status 404; return; } return $item;}

Page 119: Modern Perl Web Development with Dancer

Step 12 - Tag Tasks

Page 120: Modern Perl Web Development with Dancer

Tag Tasks

● Associate tags with tasks● Display tags for task● Edit tags● Filter on tags

Page 121: Modern Perl Web Development with Dancer

Database Changes

● New table "tag"● New link table "item_tag"● Generate new DBIC schema classes

Page 122: Modern Perl Web Development with Dancer

Database Changes

Page 123: Modern Perl Web Development with Dancer

Database Changes (Cheating)

● cd step12

● db/make_db

● dbicdump todo.conf

Page 124: Modern Perl Web Development with Dancer

Database Relationships

● DBIC recognises relationships between tables● Regenerates code automatically● Item has_many Item Tags● Item Tags belong_to Items● Item has a many_to_many relationship with

Tag– And vice versa

Page 125: Modern Perl Web Development with Dancer

Add Tags

my @tags = split /\s*,\s*/, body_parameters->get('tags');

...

my $new_item = resultset('Item')->create($item);foreach my $tag (@tags) { $new_item->add_to_tags({ name => $tag });}

Page 126: Modern Perl Web Development with Dancer

Displaying Tags (1)

tags: [<% FOREACH tag IN item.tags -%> "<% tag.name %>" <% UNLESS loop.last %>,<% END %><% END -%> ]

Page 127: Modern Perl Web Development with Dancer

Displaying Tags (2)

<div class="panel panel-{{panel_class}} {{#tags}}tag-{{.}} {{/tags}}">

Page 128: Modern Perl Web Development with Dancer

Displaying Tags (3)

<p><a class="btn btn-{{button_type}} btn-xs tag-button" href="#" role="button" title="Clear tag filter" id="clear-tag"> <span class="glyphicon glyphicon-remove"></span></a> {{#tags}} <a class="btn btn-{{button_type}} btn-xs tag-button" href="#" role="button">{{.}}</a> {{/tags}}</p>

Page 129: Modern Perl Web Development with Dancer

Displaying Tags

Page 130: Modern Perl Web Development with Dancer

Filtering Tags

$(".tag-button").on('click', function(event) { event.preventDefault(); if (this.id == "clear-tag") { $(".panel").show(400); } else { $(".panel").hide(400); $(".tag-" + this.text).show(400); }});

Page 131: Modern Perl Web Development with Dancer

Some Conclusions

Page 132: Modern Perl Web Development with Dancer

Things We Didn't Cover

● Testing● Deployment

Page 133: Modern Perl Web Development with Dancer

Things to Add

● User management● Better error checks● AJAX

– Pop-ups

Page 134: Modern Perl Web Development with Dancer

Things to Read

● Dancer documentation● Dancer advent calendar● PSGI/Plack documentation● CPAN

Page 135: Modern Perl Web Development with Dancer

Things to Consider

● Perl has great tools for web development● Moose is a state of the art object system● DBIC is a state of the art ORM● Dancer, Catalyst and Mojolicious are state of the

art web frameworks● No language has better tools

Page 136: Modern Perl Web Development with Dancer

Stay in Touch

[email protected]● @perlhacks● http://perlhacks.com/● Mailing list● Facebook

Page 137: Modern Perl Web Development with Dancer

Thank You