Conferences

      YAPC::EU 2008 in Copenhagen

      PerlDancer for Perlers (FOSDEM 2011)

      Perl Dancer Conference 2014

    Using ACT in 2013/2014

    Modern Perl for web applications

      mod_perl vs PSGI

      Apache version

      Dancer2 Advantages

      Manual SQL vs DBIx::Class

    More Reasons for "No act on ACT"

      Single Point of Failure

      Development

      Hackathon in Lyon

      Responsiveness

    Perl Dancer Conference Website

    Web Application Features

      Maps with Leaflet

        Venue on Frontpage

        Leaflet Library

        Leaflet Code

        User Map

      Cropping photos

        Current photo

        Ballerina

        Cropping I

        Cropping II

        Final Result

        Jcrop Library

      SEO / Modern Web Design

        Secure site with HTTPS

        Speaking Links I

        Speaking Links II

      Administration

        Navigation

      Development

        Dancer2::Debugger

    DBIx::Class Techniques

      Truth of ResultSet

      Chaining

      Relationship Traversal

      Hashref Inflator

      Predefined Searches

    Dancer2

      Code Structure

        Main Module

        Route module I

        Route module II

      Hooks used

      Plugins used

      Plack Middleware

        Cross-site request forgery (CSRF/XSRF)

    Summary

      Modern Perl

      Missing features

      Perl Dancer Conference 2016

      Call for developers

      Questions

Conferences

YAPC::EU 2008 in Copenhagen

s-h-stefan-hornburg-racke-no-act-on-act-en-2.png

PerlDancer for Perlers (FOSDEM 2011)

s-h-stefan-hornburg-racke-no-act-on-act-en-4.jpg

Sawyer's presentation

Perl Dancer Conference 2014

s-h-stefan-hornburg-racke-no-act-on-act-en-2.jpg

http://act.perl.dance/eic2014/

Using ACT in 2013/2014

  • Managed software

  • Listed in other conferences (Marketing)

  • User database

Modern Perl for web applications

  • PSGI / Plack

  • Web application framework (Dancer2)

  • Web framework (Bootstrap, Jquery)

  • DBIx::Class

  • Moo and friends

  • Testing

mod_perl vs PSGI

  • Apache / mod_perl

    • slow

    • memory footprint

    • deployment related code

  • PSGI

    • runs on any webserver supporting PSGI

    • fast (Nginx)

    • simple configuration (Nginx)

    • no deployment related code

Apache version

Apache/1.3.42 (Unix) mod_perl/1.31

more than 6 years old

Dancer2 Advantages

  • Clean OO interface

  • Routes

  • Hooks

  • Engines

  • Multiple Applications

    • Web application

    • REST API

    • Admin interface

Manual SQL vs DBIx::Class

  • Manual SQL

    • error prone

    • compatibility problems

    • less secure

  • DBIx::Class

    • Business logic

    • works on dozens of RDBMS

    • usually faster

    • more secure

More Reasons for "No act on ACT"

  • Single Point of Failure

  • Development

  • Responsiveness

  • No https://

Single Point of Failure

  • Baltimore Perl Workshop

  • Eventbrite

Development

Hackathon in Lyon

s-h-stefan-hornburg-racke-no-act-on-act-en-8.jpg

Responsiveness

s-h-stefan-hornburg-racke-no-act-on-act-en-3.jpg
Picture by Guillaume Brocker, CC BY-SA 3.0

Perl Dancer Conference Website

s-h-stefan-hornburg-racke-no-act-on-act-en-4.png

https://github.com/interchange/Perl-Dancer-Conference

Web Application Features

  • Maps with Leaflet

  • Cropping Photos

  • Administration

  • SEO / Modern Design

  • Dancer2::Debugger

Maps with Leaflet

  • Venue on Frontpage

  • Leaflet library

  • Leaflet code

  • User map

Venue on Frontpage
s-h-stefan-hornburg-racke-no-act-on-act-en-7.png
Leaflet Library

Leaflet Javascript library

Leaflet Code
var map = L.map('map').setView([48.20078,16.36826], 13);
L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}', {
  attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://mapbox.com">Mapbox</a>',
  maxZoom: 18,
  id: 'petermottram.mp1dpak2',
  accessToken: 'pk.eyJ1IjoicGV0ZXJtb3R0cmFtIiwiYSI6IjE1NWI5NjRjN2IxNjNkYTM1MzI3YzY5M2E0YjZjMDc0In0.T0bpnZGXCQBSW_SOv_nWHA'
}).addTo(map);
var marker2 = L.marker([48.18246, 16.38075]).addTo(map);
marker2.bindPopup("<b>Hotel Schani Wien</b><br>Karl-Popper-Straße 22<br>Conference Venue<br>21/22 Oct");
$("#marker2").click(function(){
    marker2.openPopup();
    return false;
});
User Map
s-h-stefan-hornburg-racke-no-act-on-act-en-8.png
User Map

Cropping photos

You can drag and drop or uplad your photo and crop it in our website.

Current photo
s-h-stefan-hornburg-racke-no-act-on-act-en-9.png
/profile/photo
Ballerina
s-h-stefan-hornburg-racke-no-act-on-act-en-5.jpg
Cropping I
s-h-stefan-hornburg-racke-no-act-on-act-en-11.png
Cropping II
s-h-stefan-hornburg-racke-no-act-on-act-en-14.png
Final Result
s-h-stefan-hornburg-racke-no-act-on-act-en-7.jpg
Jcrop Library

Jcrop - jQuery Image Cropping Plugin

SEO / Modern Web Design

  • Secure site with HTTPS

  • Speaking links

Secure site with HTTPS
  • More secure and gives users more confidence

  • Small ranking boost with Google

  • Free certificates with Let's Encrypt

Speaking Links I
s-h-stefan-hornburg-racke-no-act-on-act-en-1.jpg
No act on ACT
Speaking Links II
ACT

http://act.yapc.eu/ye2016/talk/6780

PDC

https://www.perl.dance/talks/40-no-act-on-act

Administration

  • Users

  • Talks

  • Tickets

  • Events

  • News

Navigation
s-h-stefan-hornburg-racke-no-act-on-act-en-3.png

Development

Dancer2::Debugger

Dancer2::Debugger Presentation

s-h-stefan-hornburg-racke-no-act-on-act-en-17.png

DBIx::Class Techniques

Truth of ResultSet

This doesn't execute SQL:

my $talks = $schema->resultset('Talk')->search(...);

This does:

my $first_talk = $schema->resultset('Talk')
                 ->search(...)->first;

Chaining

my $talks = $schema->resultset('Talk')
   ->search({-bool          => 'accepted'})
   ->search({conferences_id => 1})
   ->search({room           => { '!=' => '' }),
   ->search({start_time     => {
            '>=' => '2015-10-22 00:00:00'
            '<=' => '2015-10-23 00:00:00'
            }}),
);

Relationship Traversal

# countries dropdown
$tokens->{countries} = [
   $users->search_related(
     'addresses',
     {
        type => 'primary',
     },
   )->search_related(
      'country', undef,
      {
         columns  => [ 'country_iso_code', 'name' ],
         distinct => 1,
         order_by => 'country.name',
      }
   )->hri->all
];

Hashref Inflator

# countries dropdown
$tokens->{countries} = [
    rset('Country')->search( undef,
        { columns => [ 'country_iso_code', 'name' ],
          order_by => 'name' } )
      ->hri->all
];
unshift @{ $tokens->{countries} },
   { country_iso_code => undef, name => "Select Country" };

Predefined Searches

User class:

sub last_conference_attended {
    my $self = shift;
    my $conference = $self->conferences->search({}, {
        order_by => { -desc => 'start_date' },
    })->first;
}

Web application:

my $conference = $user->last_conference_attended;

Dancer2

  • Code structure

  • Hooks

  • Plugins

  • Plack::Middleware

Code Structure

  • Main module

  • Multiple modules for routes

Main Module
use Dancer2;

use PerlDance::Routes::Account;
use PerlDance::Routes::Admin;
use PerlDance::Routes::Data;
use PerlDance::Routes::PayPal;
use PerlDance::Routes::Profile;
use PerlDance::Routes::Survey;
use PerlDance::Routes::Talk;
use PerlDance::Routes::User;
use PerlDance::Routes::Wiki;
Route module I
use Dancer2 appname => 'PerlDance';

use Dancer2::Plugin::Auth::Extensible;
use Dancer2::Plugin::DataTransposeValidator;
use Dancer2::Plugin::DBIC;
use Dancer2::Plugin::Email;
use Dancer2::Plugin::Deferred;
use Dancer2::Plugin::Interchange6;
use Dancer2::Plugin::TemplateFlute;

prefix '/profile';
Route module II
get '/talk/create' => sub {
    my $tokens = {
        title => "New Talk",
    };

    $tokens->{form} = form('create-update-talk');
    $tokens->{form}->reset;
    $tokens->{form}->fill( duration => 40 );

    add_durations_token($tokens);

    template 'profile/create_update_talk', $tokens;
};

Hooks used

hook 'before_template_render' => sub {
  my $tokens = shift;

  if ( my $user = logged_in_user ) {
    $tokens->{logged_in_user} = schema->current_user;
  }

  $tokens->{conference_name} = setting('conference_name');
};

Plugins used

Dancer2::Plugin::Auth::Extensible

User Authentication

Dancer2::Plugin::DataTransposeValidator

Form validation

Dancer2::Plugin::DBIC

DBIx::Class Wrapper

Dancer2::Plugin::Deferred

Flash messages after redirect

Dancer2::Plugin::Email

Sending emails

Dancer2::Plugin::Interchange6

Cart and other business functions

Dancer2::Plugin::TemplateFlute

Form handling

Plack Middleware

s-h-stefan-hornburg-racke-no-act-on-act-en-5.png

Joy of PSGI middleware

Cross-site request forgery (CSRF/XSRF)

Plack::Middleware::XSRFBlock

# bin/app.psgi

use Plack::Builder;
use PerlDance;
my $app = PerlDance->to_app;

builder {
    enable 'Session';
    enable 'XSRFBlock',
      cookie_name    => 'PerlDance-XSRF-Token',
      meta_tag       => 'xsrf-meta',
      cookie_options => { httponly => 1, };
    enable 'XForwardedFor',
      trust => [qw( 127.0.0.1 10.0.0.0/8 172.16.0.0/20 192.168.0.0/16 )];
    $app;
}

Summary

  • Modern Perl

  • Missing features

  • Perl Dancer Conference 2016

  • Call for developers

  • Ask questions

Modern Perl

Missing features

  • Multilingual GH #8

  • Drag and drop schedule tool

  • Multisite

  • Multiple speakers GH #104

Perl Dancer Conference 2016

s-h-stefan-hornburg-racke-no-act-on-act-en-4.png

Call for developers

https://github.com/interchange/Perl-Dancer-Conference

Questions

Questions?