Mason - A Template system for us Perl programmers

70
Mason A Template System for us programmers March 2013 - http://www.eteve.net

description

Templating Modules are a bit like editors. Every web application developer has a favourite one. And every template system is someone's favorite. Mine is Mason. But not because the Perl MVC tutorials are full of examples using Mason. Not because it's the fastest (use xSlate if you want to trade speed for flexibility). Not because it's the most popular. It's my favourite for a very plain reason: It makes me more productive and allows me to develop web GUIs using all the powerful features a programmer should biterly miss if they are taken away. That includes writing Perl code :P I never heard of a business that went down because they didn't have fast enough CPUs, so I'm not fussy about trading a few CPU cycles for elegance, ease and speed of development.

Transcript of Mason - A Template system for us Perl programmers

Page 1: Mason - A Template system for us Perl programmers

MasonA Template System for us programmers

March 2013 - http://www.eteve.net

Page 2: Mason - A Template system for us Perl programmers

A bit of myth busting

● Mason is old● Mason is a viewcontroller● Mason is too complex● Mason is slow● Mason uses embedded Perl

Page 3: Mason - A Template system for us Perl programmers

Mason is old

Mason 1 is old (HTML::Mason)

Mason 2 released in 02/2011

Complete Moosified rewrite

Page 4: Mason - A Template system for us Perl programmers

Mason is a viewtroller

Kind of true for Mason 1

But that was 10 years ago

Mason 2 is a pure templating system

The controller bit has been moved to Poet

Page 5: Mason - A Template system for us Perl programmers

Mason is too complex

AugmentationInheritanceCompositionMethod modifiersDynamic filters

Page 6: Mason - A Template system for us Perl programmers

Mason is too complex

AugmentationInheritanceCompositionMethod modifiersDynamic filters

But wait..

Page 7: Mason - A Template system for us Perl programmers

We are programmersSo it should be just fine

Page 8: Mason - A Template system for us Perl programmers

Mason is slow

Hum, well...

Compared to TT (as complex as TT can take benchmark)

Rate Mason TTMason 909/s -- -53%TT 1923/s 112% --

Page 9: Mason - A Template system for us Perl programmers

Mason is slow - but

Power comes with a price tag

Experience shows it scales very well with complexity

Page 10: Mason - A Template system for us Perl programmers

Mason is slow - but

Power comes with a price tag

Experience shows it scales very well with complexity

The benchmark I wrote is not bigfat.Have a look:

https://bitbucket.org/jeteve/mason-pres/

Page 11: Mason - A Template system for us Perl programmers

Mason is slow - but honestly

Do we use Perl because it's faster than X?

Page 12: Mason - A Template system for us Perl programmers

Mason uses embedded Perl

Prefer PHP?

Page 13: Mason - A Template system for us Perl programmers

Mason uses embedded Perl

Or worse, a mini-language ?

Page 14: Mason - A Template system for us Perl programmers

Mason uses embedded Perl

Perl is just fine no?

use <Anything you like>;

Page 15: Mason - A Template system for us Perl programmers

The basics - Embedded code

% while( my $product = $products->next() ){ <p>Buy our great <% $product->name() | H %>. It's only <% $product->price() | H %> </p>% }

With DefaultFilter set to H:<% $product->name() %>

Page 16: Mason - A Template system for us Perl programmers

And now, some cool Mason stuff

Page 17: Mason - A Template system for us Perl programmers

Header

Main content

Footer

Augmentation - A typical page

Page 18: Mason - A Template system for us Perl programmers

Augmentation - Non Mason-ish

/index.mc<& /comp/header.mi &>Welcome to index!<& /comp/footer.mi &>

Page 19: Mason - A Template system for us Perl programmers

Augmentation - The Mason Base.mc

/Base.mc<%augment wrap> <html><head><title>Site</title></head> <body> <% inner() %> <body></html></%augment>

Page 20: Mason - A Template system for us Perl programmers

Augmentation - a page

/index.mc<h1>Welcome</h1>

Page 21: Mason - A Template system for us Perl programmers

Augmentation - a page

Evaluates to <html><head><title>Site</title></head> <body> <h1>Welcome</h1> <body></html>

Page 22: Mason - A Template system for us Perl programmers

Augmentation - another page?

/products.mc<ul> <li>Lathe</li> <li>Piano</li></ul>

Page 23: Mason - A Template system for us Perl programmers

Augmentation - another page?

Evaluates to ..

Well you get the idea

Page 24: Mason - A Template system for us Perl programmers

Augmentation - Become specific

/products/Base.mc<%augment wrap> <div class="product"> <% inner() %> </div></%product>

Page 25: Mason - A Template system for us Perl programmers

Augmentation - Become specific

/products/lathe.mc<h1>Lathe</h1>

Page 26: Mason - A Template system for us Perl programmers

Augmentation - Become specific

Evaluates to<html> <head><title>Site</title></head> <body> <div class="product"> <h1>Lathe</h1> </div> <body></html>

Page 27: Mason - A Template system for us Perl programmers

Augmentation - Wanna go bare?

/products/baremetal.mc<%flags> extends => undef</%flags><h1>Some bare content</h1>

Evaluates to<h1>Some bare content</h1>

Page 28: Mason - A Template system for us Perl programmers

A typical layout

/index

Header

Menu

Content

Footer

Page 29: Mason - A Template system for us Perl programmers

A typical layout

/products/lathe.htmlHeader

Menu

Share BoxProduct description

Footer

Page 30: Mason - A Template system for us Perl programmers

A typical layout

/errors/404.htmlHeader

Menu

Error description

Footer

Page 31: Mason - A Template system for us Perl programmers

Augmentation - Layout control

Typical hierarchy/layout/Base.mc/layout/withmenu.mc/Base.mc/index.mc/products/Base.mc/products/lathe.mc/errors/Base.mc/errors/404.mc

Page 32: Mason - A Template system for us Perl programmers

Augmentation - Layout control

/layout/Base.mc<%flags> extends => undef</%flags><%augment wrap><html> <head><title>My site</title></head> <body><% inner() %></body></html></%augment>

Page 33: Mason - A Template system for us Perl programmers

Augmentation - Layout control

/layout/withmenu.mc<%flags> extends => undef</%flags><%augment wrap> <div class="menu">...</div> <% inner() %></%augment>

Page 34: Mason - A Template system for us Perl programmers

Augmentation - Layout control

/Base.mc<%flags> extends => '/layout/withmenu.mc'</%flags>

Page 35: Mason - A Template system for us Perl programmers

Augmentation - Layout control

/index.mc<h1>This is index</h1>

Page 36: Mason - A Template system for us Perl programmers

Augmentation - Layout control

/products/Base.mc<%augment wrap> <div class="share">...</div> <div class="product"> <% inner() %> </div></%augment>

Page 37: Mason - A Template system for us Perl programmers

Augmentation - Layout control

/products/lathe.mc<h1>This is a lathe</h1>

Page 38: Mason - A Template system for us Perl programmers

Augmentation - Layout control

/errors/Base.mc<%flags> extends => '/layout/Base.mc'</%flags><%augment wrap><div class="error"><% inner() %></div></%augment>

Page 39: Mason - A Template system for us Perl programmers

Augmentation - Layout control

/errors/404.mc<h1>Sorry, nothing here</h1>

Page 40: Mason - A Template system for us Perl programmers

Actually, I want the menu in the error pages

No problem:/errors/Base.mc<%flags> extends => '/layout/Base.mc'</%flags><%augment wrap><div class="error"><% inner() %></div></%augment>

Page 41: Mason - A Template system for us Perl programmers

And now, inheritanceAnd method modifiers

Page 42: Mason - A Template system for us Perl programmers

Let's speak about page titles

Remember /layout/Base.mc ?<%flags> inherit => undef</%flags><%method title>Site</%method><%augment wrap> ... <title><% $.title() %></title> ...</%augment>

Page 43: Mason - A Template system for us Perl programmers

Now the index title

<%method title>Welcome to Site!</%method><h1>This is index</h1>

Page 44: Mason - A Template system for us Perl programmers

The lathe.mc

<%after title> - Lathe</%method><h1>This is a Lathe</h1>

Renders as:<title>Site - Lathe</title>

Page 45: Mason - A Template system for us Perl programmers

a_product.mc

<%class> has 'product' => ( isa => 'My::Product', required => 1 );</%class><%after title> - <% $.product->title() %></%after><h1>This is a <% $.product->title() %></h1>

Page 46: Mason - A Template system for us Perl programmers

a_product.mc

In Catalyst

$c->stash()->{product} = $product;

a_product.mc instance is built with what's on the stash

Page 47: Mason - A Template system for us Perl programmers

a_product.mc

Trivial unit testing

my $mason = Mason->new();

my $p_page = $mason->run('/products/a_product', product => $p )->output;

ok_contains($p_page , $p->name() );

Page 48: Mason - A Template system for us Perl programmers

CompositionAnd a bit more

Page 49: Mason - A Template system for us Perl programmers

Classic composition

/comp/share.mi<%class> has 'stuff' => ( does => 'Sharable' );</%class><div class="share">Share <% $.stuff->share_name() %> on blabla</div>

Page 50: Mason - A Template system for us Perl programmers

Composition - New /products/Base.mc

/products/Base.mc<%class> has 'product' => ( isa => 'Product' );<%augment wrap> <& /comp/share.mi , stuff => $.product &> <div class="product"> <% inner() %> </div></%augment>

Page 51: Mason - A Template system for us Perl programmers

Internal components are components

So inheritance works

/comp/share/advanced.mi<%flags> extends => '/comp/share.mi'</%flags>Advanced share <% $.stuff->share_name() %>

Page 52: Mason - A Template system for us Perl programmers

Internal components - Unit testing

my $m = $mason->_make_request();my $m_text = $m->scomp('/comp/share.mi', p => 'Banana' );

ok_contains($m_text, "Share Banana");

Page 53: Mason - A Template system for us Perl programmers

FiltersMore powerful than it sounds

Page 54: Mason - A Template system for us Perl programmers

A Simple filter

% $.NoBlankLines {{Hello

World% }}Renders:HelloWorld

Page 55: Mason - A Template system for us Perl programmers

With argument(s)

% my $i = 1;% $.Repeat(3) {{<% $i++ %> \% }}

Renders:1 2 3

Page 56: Mason - A Template system for us Perl programmers

With parametric content

% my $nums = [ 1 , 2 , 3 ];% $.Loop($nums) {{% my ( $num ) = @_;<% $num %>, \% }}

Renders:1, 2, 3,

Page 57: Mason - A Template system for us Perl programmers

Filters - Make your own

package My::Mason::Filters;use Mason::PluginRole;method Iterate($on){ Mason::DynamicFilter->new( filter => sub{ my ($yield) = @_;my $txt = ''; while( my $next = $on->next() ){ $txt .= $yield->($next); } return $txt; });}

Page 58: Mason - A Template system for us Perl programmers

Filters - Make your own

/Base.mc<%class> with My::Mason::Filter;</%class>/anywhere% $.Iterate($resultset){{% my ($result) = @_; This is result <% $result->name() %>!%}}

Page 59: Mason - A Template system for us Perl programmers

Filters - As component

/comp/pager.mi<%class> has 'on' => ( isa => 'DBIx::Class::Resulset' ); has 'page' => ( isa => 'Int' , default => 1 ); has 'yield';</%class>% my $rs=$.on->search({} , {page => $.page});<div class="pager">.. Do stuff with $rs->page() ..</div>

Page 60: Mason - A Template system for us Perl programmers

Filters - As component

/comp/pager.mi .. Continued

%# Some paging was output% $.Iterate($rs){{% my $stuff = $_[0]; <% $.yield->($stuff) %>% }}%# Some other paging maybe?

Page 61: Mason - A Template system for us Perl programmers

Let's use our pager

/products/index.mc<$class> has 'products' => ( isa => 'DBIx::Resultset' );</$class>% $.CompCall('/comp/page.mi',on=>$.products){{% my ( $product ) = @_; Product <% product->name() %>% }}

Page 62: Mason - A Template system for us Perl programmers

Filters can be curried<%class> has 'lang'; has 'Translate' ( lazy_build => 1 ); sub _build_Translate{ my ($self) = @_; $self->TranslateIn($self->lang));}</%class>% $.Translate(){{Some Text% }}

Page 63: Mason - A Template system for us Perl programmers

Filters - One more nice one% $.Cache($key , '10 minute') {{ <div class="sluggish"> .... </div>% }}

Combine with currying for cleaner code :)

Page 64: Mason - A Template system for us Perl programmers

ConclusionsIn case you're not convinced yet

Page 65: Mason - A Template system for us Perl programmers

Mason helps writing clean code

Strict by default

Enforce type consistency a-la Moose

Enforce stash content (With Catalyst)

Minimal global variables

Easy unit testing

Page 66: Mason - A Template system for us Perl programmers

Mason is powerful

Code the view like a programmer with inheritance, augmentation, method modifiers, dynamic filters, currying ..

No change of mindset required

Changes are simple and consistent

Writing a new pages is trivial

Page 67: Mason - A Template system for us Perl programmers

Mason is extensible

Base class injection.

my $mason = Mason->new(base_*_class => 'MyApp::Mason::*Subclass' );

Or Role based Plugins (and Plugins Bundles)

For instance: Mason::Plugin::Cache

Page 68: Mason - A Template system for us Perl programmers

Reference

In order of preference● MasonHQ: http://www.masonhq.com/● Cpan: Mason● Cpan: Catalyst::View::Mason2● Mailing list● Jerome :P

Page 69: Mason - A Template system for us Perl programmers

Give it a go

$ sudo apt-get install libmason-perl$ echo "Hello world" > mason/index.mc$ mason.pl mason/index.mc

$ ## In catalyst$ sudo cpan -i Catalyst::View::Mason2

Page 70: Mason - A Template system for us Perl programmers

Thanks for your watching!

Questions?