Mojolicious.
Веб в коробке!
 Perl Mova + YAPC::Russia 2010
Что такое Mojolicious?
Что такое Mojolicious?
• Веб-фреймворки:
  Mojolicious::Lite, Mojolicious, Mojo
• Объектно-ориентированное API,
  без скрытой магии и зависимостей,
  написанное на чистом Perl
• Полный стек HTTP 1.1 и WebSocket #76
  (клиент-сервер), а также IPv6, SSL и IDNA
Что такое Mojolicious?
• Асинхронный ввод-вывод, prefork-веб сервер
  с поддержкой epoll и kqueue,
  unix-сокетов и «горячей» разработки
• CGI, FastCGI и PSGI
• RESTful-роутеры, плагины, сессии,
  Perl-ish шаблонизатор, поддержка I18N,
  JSON и XML DOM с CSS3-селекторами
«Свежий» код,
основанный на опыте
 разработке Catalyst
«Весёлая ферма»
   Mojolicious
Удовольствие!

                               Код

      Код                Mojolicious::Lite

                             Mojolicious

                     Mojo

CGI    FastCGI    PSGI      HTTP 1.1       WebSocket
Mojolicious::Lite
   MVC веб-фреймворк
        ~ sinatra
use Mojolicious::Lite;

get '/hello' => sub {
   shift->render_text( 'Привет Киев!' );
};

app->start;
use Mojolicious::Lite;

post '/hello' => sub {
   shift->render_text( 'Привет Киев!' );
};

app->start;
use Mojolicious::Lite;

any '/hello' => sub {
   shift->render_text( 'Привет Киев!' );
};

app->start;
use Mojolicious::Lite;

get '/hello' => (agent => qr/Firefox/) => sub {
   shift->render_text( 'Привет Киев!' );
};

app->start;
use Mojolicious::Lite;

post '/:name' => sub { # /*
  my $self = shift;
  my $name = $self->param('name');

     $self->render_text( "Привет $name!" );
};

app->start;
use Mojolicious::Lite;

post '/:name' => sub { # /*
  my $self = shift;
  my $name = $self->stash('name');

     $self->render_text( "Привет $name!" );
};

app->start;
use Mojolicious::Lite;

post '/:name' => { id => 42 } => sub { # /*
   my $self = shift;
   my $name = $self->param('name');
   warn $self->param( 'id' );
   $self->render_text( "Привет $name!" );
};

app->start;
use Mojolicious::Lite;

any '/time' => 'clock';

app->start;

__DATA__

@@ clock.html.ep
% my ($sec, $min, $hour) = (localtime)[0, 1, 2];
Текущее время
 <%= $hour %>:<%= $min %>:<%= $sec %>
use Mojolicious::Lite;

websocket '/echo' => sub {
   my $self = shift;
   $self->receive_message(
      sub {
         my ($self, $msg) = @_;
         $self->send_message( "тук-тук: $msg" );
      }
   );
};
Примеры
Mojolicious WebSocket
        @xantus, @vti
  Интересный пример IRC-клиент
use Mojolicious::Lite;

get '/fetch' => sub {
   my $self = shift;
   $self->render_data(
       $self->client
            ->get( 'http://2010.yapcrussia.org' )
            ->res
            ->body
       );
};
use Mojolicious::Lite;

plugin charset => { charset => 'UTF-8' };

#

under sub {
  my $self = shift;

    # проверка авторизации
};
get '/foo' => sub { ... };
Cписок всех роутеров
    приложения
 script/lite.pl routes
    /hello   (?-xism:^/hello)
    /time    (?-xism:^/time)
    /echo    (?-xism:^/echo)
    /fetch   (?-xism:^/fetch)
    /:name   (?-xism:^/((?-xism:d+)))
Если много шаблонов
 в секции __DATA__
  script/lite.pl inflate
    /templates/
    /templates/clock.html.ep
Сокращатель ссылок
 на Mojolicious::Lite
  100 строк кода (5 обработчиков)
  130 строк шаблонов (4 шаблона)
              1 файл
Mojolicious
 MVC веб-фреймворк
   ~ Ruby on Rails
package App;
use base 'Mojolicious';

sub startup {
  my $self = shift;

     my $r = $self->routes;
     $r->route('/:controller/:action/:id')
       ->to('example#welcome', id => 1);
}

1;
package App;
use base 'Mojolicious';

sub startup {
  my $self = shift;

     my $r = $self->routes;
     $r->route('/:controller/:action/:id')
       ->to('example#welcome', id => 1);
}

1;
package App;
use base 'Mojolicious';

sub startup {
  my $self = shift;

     my $r = $self->routes;
     $r->route('/:controller/:action/:id')
       ->to('example#welcome', id => 1);
}

1;
package App;
use base 'Mojolicious';

sub startup {
  my $self = shift;

     my $r = $self->routes;
     $r->route('/:controller/:action/:id')
       ->to('example#welcome', id => 1);
}

1;
package App;
use base 'Mojolicious';

sub startup {
  my $self = shift;

    my $r = $self->routes;
    my $b = $r->bridge->to('auth#check);

    $b->route('/admin')->to('admin#welcome');
}
package App;
use base 'Mojolicious';

sub startup {
  my $self = shift;

     $self->plugin(charset => { ... });
     $self->types->type(json => 'text/plain');
     $self->renderer->root( ... );
}

1;
package App;
use base 'Mojolicious';

sub startup {
  my $self = shift;

     my $r = $self->routes;
     $r->route('/:controller/:action/:id')
       ->to('example#welcome', id => 1);
}

1;
package App::Example;
use base 'Mojolicious::Controller';

sub welcome {
    my $self = shift;
	

 warn $self->param( ‘id’ );
    $self->render( message => 'Привет Киев!' );
}

1;
package App::Example;
use base 'Mojolicious::Controller';

sub welcome {
    my $self = shift;
	

 warn $self->stash( ‘id’ );
    $self->render( message => 'Привет Киев!' );
}

1;
Шаблон
example/welcome.html.ep
    controller / action . format . handler
Шаблон
example/welcome.xml.ep
    controller / action . format . handler
Шаблон
example/welcome.rss.ep
    controller / action . format . handler
Шаблон
example/welcome.mail.ep
    controller / action . format . handler
Шаблон
example/welcome.html.ep
    controller / action . format . handler
Шаблон
example/welcome.html.ep
    controller / action . format . handler
Шаблон
example/welcome.html.tt
    controller / action . format . handler
Шаблон
example/welcome.html.cttp2
      controller / action . format . handler
Шаблон
example/welcome.html.ep
    controller / action . format . handler
% layout 'default';

<h2><%= $message %></h2>

<a href="<%== url_for %>">click here</a>
% layout 'default';

<h2><%= $message %></h2>

<a href="<%== url_for %>">click here</a>
% layout 'default';

<h2><%= stash 'message' %></h2>

<a href="<%== url_for %>">click here</a>
% layout 'default';

<h2><%= $self->stash('message') %></h2>

<a href="<%== url_for %>">click here</a>
% layout 'default';

<h2><%= $message2 %></h2>

<a href="<%== url_for %>">click here</a>
Global symbol "$message2" requires explicit
package name at (eval 280) line 2.

1: % layout 'default';
2: <h2><%= $message2 %></h2>
3: ...

{
    'status' => 500,
    'message' => ‘Привет Киев!’,
    ...
% layout 'default';

<h2><%= $message if is_iphone %></h2>

<a href="<%== url_for %>">click here</a>
sub startup {
   ...
   $self->renderer->add_helper(
      is_iphone => sub {
        shift->tx->req->headers
             ->user_agent =~ /iphone|cfnetwork/i
               ? 1 :0
      }
);
Шаблон
layouts/default.html.ep
путь к layout-шаблонам / имя . format . handler
<!doctype html>
<html>
   <head><title> Привет! </title></head>
   <body>
     <%== content %>
   </body>
</html>
Около 20 проектов
  на Mojolicious
Mojo
Базовый веб-фреймворк
package App;
use base 'Mojo';

sub handler {
    my ($self, $tx) = @_;
	

	

 warn $tx->req; warn $tx->req->url;
	

    $tx->res->headers
             ->content_type( 'text/plain' );
    $tx->res->body( 'Привет Киев!' );
}
package App;
use base 'Mojo';

sub handler {
    my ($self, $tx) = @_;
	

	

 warn $tx->req; warn $tx->req->url;
	

    $tx->res->headers
             ->content_type( 'text/plain' );
    $tx->res->body( 'Привет Киев!' );
}
GET / HTTP/1.1
Connection: keep-alive
Accept: text/html, application/xhtml, ....
Accept-Charset: windows-1251, utf-8; ...
Accept-Encoding: gzip,deflate
Accept-Language: ru,en-us;q=0.7,en;q=0.3
Host: localhost:3000
User-Agent: Mozilla/5.0 (Macintosh; ...
Content-Length: 0
Keep-Alive: 300
package App;
use base 'Mojo';

sub handler {
    my ($self, $tx) = @_;
	

	

 warn $tx->req; warn $tx->req->url;
	

    $tx->res->headers
             ->content_type( 'text/plain' );
    $tx->res->body( 'Привет Киев!' );
}
Mojo::Client
HTTP 1.1 и WebSocket клиент
my $client = Mojo::Client->new;

$client->get(
	

 ‘http://2010.yapcrussia.org’ => sub {
	

 	

 my ($self, $tx) = @_;
	

 	

 say $tx->res;
	

 }
)->process;
my $client = Mojo::Client->new;

$client->get(
	

 ‘http://2010.yapcrussia.org’ => sub { ... },
);
$client->post(
	

 ‘http://2010.yapcrussia.ru’ => sub { ... },
);

$client->process;
my $client = Mojo::Client->new;

$client->get(‘http://goo.gl’)->res->code;

$client->get(
  'http://search.twitter.com/trends.json'
)->success->json->{trends}->[0]->{name}

$client->get( ... )->dom->success
 ->search('body > #container > div p[id]')
Mojo::IOLoop
  TCP клиент-сервер
my $loop = Mojo::IOLoop->new;
$loop->listen(port => 3000, cb => sub {
   my ($self, $id) = @_;

     $self->read_cb ($id => sub { ... });

     $self->write_cb($id => sub { ... });
);
my $id = $loop->connect(port => 3000, ...);
$loop->start; $loop->stop;
Test::Mojo
Фреймворк для тестирования
my $t = Test::Mojo->new( app => 'App' );

$t->get_ok( '/hello' )
  ->status_is( 200 )
  ->header_is(
    'X-Powered-By' => 'Mojolicious (Perl)'
  )
  ->content_is( 'Привет Киев!' );

$t->post_ok( '/42' )
  ->content_like(qr/Привет/, 'тест пройден!');
Всё, что нужно – есть!
    Mojolicious – веб в коробке!
Если нет, то есть
    на CPAN
или github.com :)
Mojolicious на CPAN
• Mojolicious              • MojoX::Log::*
• Mojo::Server::FCGI       • MojoX::Renderer::*
• AnyEvent::Mojo            • TT
• Apache::Mojo              • CTTP2, HTP
  Apache2::Mojo
                            • XSLT
• Catalyst::Engine::Mojo    • Mail
  Squatting::On::Mojo
Модель, где же модель
      данных?
      А говорите всё есть :)
Любая модель данных
может быть использована
     в Mojolicious
  DBI, DBIx::Class, Fey::ORM, CouchDB, MongoDB, ...
Документация

• Пока мало документации, зато очень
  хороший фидбек :)
• Mojolicious::Lite и Mojolicious::Guides
• Mojolicious Handbook @kvorg
• Mojolicious FAQ @vti
Полезная информация
• http://mojolicious.org
• irc://irc.perl.org/#mojo
• http://groups.google.com/group/mojolicious
• Github: kraih, vti, xantus, memowe, sharifulin
• Twitter: @kraih, @vtivti, @sharifulin
• Juick: @vti, @sharifulin
«Making hard things possible
   and everything fun!»
         Девиз Mojolicious
«Duct tape
for the HTML5 Web»
    Девиз Mojolicious #2
«Viva la revolution!»
    Девиз Mojolicious #3
Mojolicious::Lite
       vs.
   Dancer
    Соревнование
Mojolicious
   vs.
 Catalyst
  Что выбрать?
«Особая разновидность
современного программиста
 – программист, изучающий
        фреймворки»
         Алекс Капранов
«Каждый программист
 должен сделать 3 вещи:
фреймворк, шаблонизатор
 и событийную машину»
      Анатолий Шарифулин
use Mojolicious
      or die
Viva la revolution!
use Perl
  or die
JFDI
Посмотрите, какие
у меня крутые часы :)
Спасибо
за внимание!
 Анатолий Шарифулин
          sharifulin
any ‘/questions’ => sub {
	

 	

 shift->render(
	

 	

 	

 answer => ‘sharifulin’
	

 	

 );
   };

Mojolicious. Веб в коробке!