Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Is Mojolicious web only?

Renee
March 07, 2019

Is Mojolicious web only?

Renee

March 07, 2019
Tweet

More Decks by Renee

Other Decks in Technology

Transcript

  1. View Slide

  2. Is Mojolicious
    web only?

    View Slide

  3. View Slide

  4. Reinventing
    the wheel

    View Slide

  5. Parser for ...
    JSON, HTML,
    HTTP

    View Slide

  6. Object
    orientation

    View Slide

  7. Moose, Mouse,
    Mu, Moo, Mo

    View Slide

  8. Mojo::Base
    -base

    View Slide


  9. View Slide

  10. #!/usr/bin/env perl
    use Mojolicious::Lite;
    push @{ app->plugins->namespaces }, 'PerlServices::Plugin';
    plugin 'Ticket' => app->config->{otrs};
    app->defaults(
    bodyclass => 'start',
    active => 'home',
    );
    get '/' => 'static/index';
    get '/imprint' => 'static/imprint';
    get '/privacy' => 'static/privacy';
    get '/jobs' => 'static/jobs';
    under '/otrs' => sub {
    shift->stash(bodyclass => 'otrs', active => 'otrs');
    return 1;
    };
    get '/' => 'static/otrs';
    get '/support' => 'static/otrs-support';
    get '/development' => 'static/otrs-development';
    under '/perl' => sub {
    shift->stash(bodyclass => 'perl', active => 'perl');
    return 1;
    }
    get '/' => 'static/perl';
    under '/academy' => sub {
    shift->stash(bodyclass => 'schulung',active => 'academy');
    return 1;
    };
    get '/' => 'static/academy';
    under '/' => sub {
    my $c = shift;
    $c->stash(
    errors => {},
    values => {},
    );
    return 1;
    };
    get '/kontakt.cgi' => 'contact/form';
    post '/kontakt.cgi' => \&_send_contact_request;
    post '/get-in-touch' => \&_send_contact_request;
    under '/';
    any '/*anything' => sub {
    my $c = shift;
    $c->redirect_to( '/' );
    };
    app->start;

    View Slide

  11. Mojo == Web ?

    View Slide

  12. View Slide

  13. View Slide

  14. $ perl -Mojo -E '
    say g("https://act.yapc.eu/gpw2019/talk/7601")
    ->dom
    ->at("#talk_abstract")
    ->text
    '

    View Slide

  15. $ perl -Mojo -E '
    say g("https://act.yapc.eu/gpw2019/talk/7601")
    ->dom
    ->at("#talk_abstract")
    ->text
    '

    View Slide

  16. $ perl -Mojo -E '
    say g("https://act.yapc.eu/gpw2019/talk/7601")
    ->dom
    ->at("#talk_abstract")
    ->text
    '
    Mojolicious ist ein tolles Webframework f�r Perl.
    Aber kann es auch mehr? Ein paar Anwendungsf�lle werde
    ich im Vortrag zeigen...

    View Slide

  17. $ perl -Mojo -E '
    say p("https://api.hetzner.cloud/v1/servers" =>
    { Authorization => "Bearer " } =>
    json => {
    name => "Testserver$$",
    server_type => "cx11",
    location => "nbg1",
    image => "ubuntu-18.04"
    })
    ->json("/server/public_net/ipv4/ip")'
    116.203.66.1

    View Slide

  18. use Mojo::DOM;
    use Mojo::File qw(path);
    my $file = path('./Badge-4er-tmpl.pure.svg');
    my @user_pages = _get_gpw_users();
    my $page_nr = 0;
    for my $page ( @user_pages ) {
    my $dom = Mojo::DOM->new( $file->slurp );
    for my $i ( 0 .. 3 ) {
    say sprintf "Set name %s...", $name;
    $dom->find('#firstname-' . ($i+1) )->first->content( $firstname );
    $dom->find('#lastname-' . ($i+1) )->first->content( $page->[$i]->[2] );
    }
    path('./Badges/Badge.page' . ++$page_nr . '.svg')->spurt( "$dom" );
    }

    View Slide

  19. use Mojo::DOM;
    use Mojo::File qw(path);
    my $file = path('./Badge-4er-tmpl.pure.svg');
    my @user_pages = _get_gpw_users();
    my $page_nr = 0;
    for my $page ( @user_pages ) {
    my $dom = Mojo::DOM->new( $file->slurp );
    for my $i ( 0 .. 3 ) {
    say sprintf "Set name %s...", $name;
    $dom->find('#firstname-' . ($i+1) )->first->content( $firstname );
    $dom->find('#lastname-' . ($i+1) )->first->content( $page->[$i]->[2] );
    }
    path('./Badges/Badge.page' . ++$page_nr . '.svg')->spurt( "$dom" );
    }

    View Slide

  20. use Mojo::DOM;
    use Mojo::File qw(path);
    my $file = path('./Badge-4er-tmpl.pure.svg');
    my @user_pages = _get_gpw_users();
    my $page_nr = 0;
    for my $page ( @user_pages ) {
    my $dom = Mojo::DOM->new( $file->slurp );
    for my $i ( 0 .. 3 ) {
    say sprintf "Set name %s...", $name;
    $dom->find('#firstname-' . ($i+1) )->first->content( $firstname );
    $dom->find('#lastname-' . ($i+1) )->first->content( $page->[$i]->[2] );
    }
    path('./Badges/Badge.page' . ++$page_nr . '.svg')->spurt( "$dom" );
    }

    View Slide

  21. CLI

    View Slide

  22. $ perl -Mojo -E '
    say g("https://act.yapc.eu/gpw2019/talk/7601")
    ->dom
    ->at("#talk_abstract")
    ->text
    '
    Mojolicious ist ein tolles Webframework f�r Perl.
    Aber kann es auch mehr? Ein paar Anwendungsf�lle werde
    ich im Vortrag zeigen...

    View Slide

  23. $ mojo get https://act.yapc.eu/gpw2019/talk/7601 \
    '#talk_abstract' text
    Mojolicious ist ein tolles Webframework für Perl.
    Aber kann es auch mehr? Ein paar Anwendungsfälle werde
    ich im Vortrag zeigen...

    View Slide

  24. $ mojo get https://act.yapc.eu/gpw2019/talks 'td > a[href^="/gpw2019/talk"] > b' text
    Supercharging Math Modules with Databases
    WebPerl - Perl im Browser!
    und goto ist sooo nützlich
    Eine nützliche Quelle für Perl-Code: MySQL Workbench
    Mojolicious nur für's Web? Schaun wir mal...
    Darf der das? Regelbasierte Autorisierung in Catalyst
    Parsen mit Zuversicht
    Finding humans to turn into developers
    Gitlab und Perl – Ein Erfahrungsbericht II
    Mein Jahr mit der DSGVO
    Moving Mountains With Perl
    Emacs für Perl-Sourcen: Kleine Tricks
    Willkommen in München - Welcome to Munich
    Auf Wiedersehen - vielleicht beim 22. Deutschen Perl-Workshop?
    Einführung in Encoding mit Perl
    Was ich beim Advent Of Code 2018 gelernt habe
    Vue.js for Perl hackers
    Deploying Perl Apps using Docker, Gitlab & Kubernetes
    Hacker haben unsere Login-Daten. Was tun wir?
    Du kannst den Planeten retten. Wie wäre es mit heute Nachmittag?
    Fun with Macros
    The Camel Paradox
    Was ich über SQL gelernt habe
    Git Tips & Tricks
    Perl meetup HOWTO session
    TPF Update
    node.js in perl - event driven programming including promises via perl/POE
    static linking of perl
    OBS - Streamline the delivery of your perl project
    Perl 6 one-liners
    Creating a compiler in Perl 6
    Perl und SSL für Fortgeschrittene
    Gatekeepers
    Perl erweitern mit Nim
    Freifunk - was ist das und wie entsteht die Software
    Escape analysis and related optimizations for Perl 6
    Understanding react, supply, and whenever
    PullRequest Club
    Neuigkeiten von Coocook.org
    Perl at the Chaos Communication Congress
    Join all the things with DBIC
    Scanley Cybrick - APT für jedermann
    EPO Recording Kits
    Debugging ist bunt!
    PerlCon 2019

    View Slide

  25. mojo version
    mojo generate lite_app
    ...

    View Slide

  26. App::Cmd
    MooX::Cmd
    ...

    View Slide

  27. Mojolicious::Commands

    View Slide

  28. gpw add 2019
    gpw update 2019
    gpw show 2019
    gpw talks 2019
    gpw talk 7106

    View Slide

  29. WIP

    View Slide

  30. #!/usr/bin/perl
    use Mojolicious::Lite;
    app->plugin( JSONConfig => {
    file => app->home->child('..', 'conf', 'gpw.json'),
    });
    app->plugins->namespaces(['App::GPW::Plugin']);
    app->commands->namespaces(['App::GPW::Cmd']);
    app->plugin( 'Utils' );
    Mojo::IOLoop->start if !Mojo::IOLoop->is_running;
    my $gpw = $app;

    View Slide

  31. package App::GPW;
    use Mojo::Base 'Mojolicious', -strict;
    sub startup {
    my $app = shift;
    $app->plugin( JSONConfig => {
    file => $app->home->child('conf', 'gpw.json'),
    });
    $app->plugins->namespaces(['App::GPW::Plugin']);
    $app->commands->namespaces(['App::GPW::Cmd']);
    $app->plugin( 'Utils' );
    }
    1;

    View Slide

  32. package App::GPW;
    use Mojo::Base 'Mojolicious', -strict;
    sub startup {
    my $app = shift;
    $app->plugin( JSONConfig => {
    file => $app->home->child('conf', 'gpw.json'),
    });
    $app->plugins->namespaces(['App::GPW::Plugin']);
    $app->commands->namespaces(['App::GPW::Cmd']);
    $app->plugin( 'Utils' );
    }
    1;

    View Slide

  33. package App::GPW::Plugin::Utils;
    use Mojo::Base 'Mojolicious::Plugin', -signatures;
    # … infrastructure code …
    sub register ( $self, $app, $config ) {
    for my $attr ( qw(...) ) {
    next if !$config->{$attr};
    $self->$attr( $config->{$attr} );
    }
    $app->helper(
    'gpw.directory' => sub { $self->_directory( @_ ); }
    );
    $app->helper(
    'gpw.workshop' => sub { $self->_new_workshop( @_ ); }
    );
    }
    1;

    View Slide

  34. package App::GPW::Plugin::Utils;
    use Mojo::Base 'Mojolicious::Plugin', -signatures;
    # … infrastructure code …
    sub register ( $self, $app, $config ) {
    for my $attr ( qw(...) ) {
    next if !$config->{$attr};
    $self->$attr( $config->{$attr} );
    }
    $app->helper(
    'gpw.directory' => sub { $self->_directory( @_ ); }
    );
    $app->helper(
    'gpw.workshop' => sub { $self->_new_workshop( @_ ); }
    );
    }
    1;

    View Slide

  35. package App::GPW;
    use Mojo::Base 'Mojolicious', -strict;
    sub startup {
    my $app = shift;
    $app->plugin( JSONConfig => {
    file => $app->home->child('conf', 'gpw.json'),
    });
    $app->plugins->namespaces(['App::GPW::Plugin']);
    $app->commands->namespaces(['App::GPW::Cmd']);
    $app->plugin( 'Utils' );
    }
    1;

    View Slide

  36. package App::GPW::Cmd::add;
    use Mojo::Base 'Mojolicious::Command', -signatures;
    use Try::Tiny;
    sub run ($self, @args) {
    my $app = $self->app;
    my $year = shift @args;
    $app->log->debug( "Add $year workshop" );
    my $error;
    try { $app->gpw->workshop( $year ); }
    catch {
    $error = $_;
    $app->log->warn( "Cannot add gpw: $_" );
    };
    return 0 if $error;
    return 1;
    }
    1;

    View Slide

  37. $ perl bin/gpw add 2018
    [2019-03-04 19:33:25.42306] [10000] [debug] Add 2018 workshop
    [2019-03-04 19:33:25.42345] [10000] [debug] Get list of talks...
    [2019-03-04 19:33:25.44091] [10000] [debug] Create directory for 2018
    [2019-03-04 19:33:25.44129] [10000] [debug] Selector: /gpw2018
    [2019-03-04 19:33:25.44219] [10000] [debug] Get event info from github
    [2019-03-04 19:33:25.44227] [10000] [debug] URL: https://r...
    [2019-03-04 19:33:26.16024] [10000] [debug] {
    "end" => "2018-04-07 17:00:00",
    "name" => "Deutscher Perl-Workshop 2018",
    "start" => "2018-04-03 09:00:00"
    }
    [2019-03-04 19:33:27.75339] [10000] [debug] Get talk 7271...
    [2019-03-04 19:33:27.75420] [10000] [debug] Get talk 7272...
    [2019-03-04 19:33:27.75457] [10000] [debug] Get talk 7280...
    [2019-03-04 19:33:27.75490] [10000] [debug] Get talk 7277...
    [2019-03-04 19:33:27.75522] [10000] [debug] Get talk 7299…
    $

    View Slide

  38. $ MOJO_MODE=production perl bin/gpw add 2018
    $

    View Slide

  39. Mojo „infrastructure“

    View Slide

  40. package App::GPW::Plugin::Utils;
    use Mojo::Base 'Mojolicious::Plugin', -signatures;
    use Mojo::File qw(path);
    use Mojo::JSON qw(encode_json);
    use Mojo::UserAgent;
    use Config::Tiny;
    use File::HomeDir;
    has base_url => sub { 'https://act.yapc.eu/' };
    has github_url => sub { 'https://raw.githubusercontent.com/Act-Conferences/' };
    has conference => sub { 'gpw' };
    has talks_path => sub { '/talks' };
    has talk_path => sub { '/talk' };

    View Slide

  41. sub _get_act_info_from_github ($self, $c, $year ) {
    my $url = … ;
    my $app = $c->app;
    $app->log->debug( "Get event info from github" );
    $app->log->debug( "URL: $url" );
    $app->ua->get(
    $url => {} => sub {
    my ($ua, $tx) = @_;
    return if $tx->res->is_error;
    # ...
    $self->_directory( $c, $year )->child( 'conference.json' )->spurt(
    encode_json \%info
    );
    },
    );
    return 1;
    }

    View Slide

  42. sub _get_act_info_from_github ($self, $c, $year ) {
    my $url = … ;
    my $app = $c->app;
    $app->log->debug( "Get event info from github" );
    $app->log->debug( "URL: $url" );
    $app->ua->get(
    $url => {} => sub {
    my ($ua, $tx) = @_;
    return if $tx->res->is_error;
    # ...
    $self->_directory( $c, $year )->child( 'conference.json' )->spurt(
    encode_json \%info
    );
    },
    );
    return 1;
    }

    View Slide

  43. Reusable for web

    View Slide

  44. package App::GPW::Controller::Conf;
    use Mojo::Base 'Mojolicious::Controller', -signatures;
    use Try::Tiny;
    sub list ($c) {
    my $confs = $c->gpw->list;
    $c->stash( confs => $confs );
    return $c->render( 'index' );
    }
    sub add ($c) {
    my $year = $c->param('year');
    my $app = $c->app;
    my $success = $app->commands->run('add', $year);
    return $c->reply->exception if !$success;
    return $c->redirect_to( $c->url_for('conf-list') );
    }

    View Slide

  45. package App::GPW::Controller::Conf;
    use Mojo::Base 'Mojolicious::Controller', -signatures;
    use Try::Tiny;
    sub list ($c) {
    my $confs = $c->gpw->list;
    $c->stash( confs => $confs );
    return $c->render( 'index' );
    }
    sub add ($c) {
    my $year = $c->param('year');
    my $app = $c->app;
    my $success = $app->commands->run('add', $year);
    return $c->reply->exception if !$success;
    return $c->redirect_to( $c->url_for('conf-list') );
    }

    View Slide

  46. Mojolicious
    is not web only...

    View Slide

  47. Questions?

    View Slide

  48. https://github.com/reneeb/App-GPW

    View Slide

  49. Thank you!

    View Slide