Mojolicious. Веб в коробке!
-
Upload
anatoly-sharifulin -
Category
Documents
-
view
1.303 -
download
0
description
Transcript of Mojolicious. Веб в коробке!
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
CGI FastCGI PSGI HTTP 1.1 WebSocket
Mojo
Mojolicious
Mojolicious::Lite
Код
Удовольствие!
Код
Mojolicious::LiteMVC веб-фреймворк
~ 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 файл
MojoliciousMVC веб-фреймворк
~ 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.1Connection: keep-aliveAccept: text/html, application/xhtml, ....Accept-Charset: windows-1251, utf-8; ...Accept-Encoding: gzip,deflateAccept-Language: ru,en-us;q=0.7,en;q=0.3Host: localhost:3000User-Agent: Mozilla/5.0 (Macintosh; ...Content-Length: 0Keep-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::ClientHTTP 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::IOLoopTCP клиент-сервер
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
• Mojo::Server::FCGI
• AnyEvent::Mojo
• Apache::Mojo
Apache2::Mojo
• Catalyst::Engine::MojoSquatting::On::Mojo
• MojoX::Log::*
• MojoX::Renderer::*
• TT
• CTTP2, HTP
• XSLT
Модель, где же модель данных?А говорите всё есть :)
Любая модель данных может быть использована
в MojoliciousDBI, 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Соревнование
Mojoliciousvs.
CatalystЧто выбрать?
«Особая разновидность современного программиста – программист, изучающий
фреймворки»Алекс Капранов
Анатолий Шарифулин
«Каждый программист должен сделать 3 вещи: фреймворк, шаблонизатор и событийную машину»
use Mojoliciousor die
Viva la revolution!
use Perlor die
JFDI
Посмотрите, какие у меня крутые часы :)
Спасибо за внимание!Анатолий Шарифулин
sharifulin
any ‘/questions’ => sub { shift->render( answer => ‘sharifulin’ ); };