Dec 27

In Mason 1 there are several ways to filter content: the <%filter> section, escape flags, and Component Calls with Content. Each of these has their own disparate implementation and API.

In Mason 2 we aim to unify these with a single implementation and a more consistent syntax.

A set of standard filters are automatically available in components, and other filter packages can be loaded via plugins.

Invoking filters (block syntax)

Here’s the typical way of invoking a filter:

<% $.Trim { %>
This string will be trimmed
</%>

Things to note here:

  • An { at the end of a <% %> tag denotes a filter call.
  • The </%> tag marks the end of the filtered content.
  • The expression $.Trim, aka $self->Trim, is a method call on the component object which returns a filter. In general everything before the brace is evaluated and is expected to return a filter or list of filters.
  • Filter names use CamelCase to distinguish themselves from other methods in the Mason::Component namespace. Another option was to use a standard prefix or suffix, e.g. trim_filter or filter_trim, but I thought this was the least ugly option and made filters look a little more like built-in tags.

Filters can take arguments:

<% $.Repeat(3) { %>
  There's no place like home.
</%>

  ==>  There's no place like home.
 There's no place like home.
 There's no place like home.

Again, the expression $.Repeat(3) returns a filter, meaning that it can
be curried:

% my $repeat_three = $.Repeat(3);
<% $repeat_three { %>
  There's no place like home.
</%>

A simple filter is just a subroutine that takes text as input and return the
new text. Thus you can create one-off filters with anonymous subroutines:

<% sub { reverse($_[0]) } { %>Hello</%>

     ==> olleH

Filters can be nested, with separate tags:

<% $.Trim { %>
  <% sub { uc($_[0]) } { %>
    This string will be trimmed and uppercased
  </%>
</%>

or within a single tag:

<% $.Trim, sub { uc($_[0]) } { %>
  This will be trimmed and uppercased
</%>

Multiple filters within the same tag are applied, intuitively, in reverse order with the last one being innermost. e.g. in this block

% my $i = 1;
<% $.Repeat(3), $.Cache($key, '1 hour') { %> <% $i++ %> </%>

  => 1 1 1

the output of <% $i++ %> is cached, and then repeated three times, whereas in this block

% my $i = 1;
<% $.Cache($key, '1 hour'), $.Repeat(3) { %> <% $i++ %> </%>

  => 1 2 3

<% $i++ %> is executed and output three times, and then the whole thing cached.

Invoking filters (pipe syntax)

Filters can also appear in a limited way inside a regular <% %> tag; this replaces Mason 1′s escape flags.

<% $content | NoBlankLines,Trim %>

The filter list contains one or more comma-separated names, which are treated as methods on the current component class. With this syntax you cannot use anonymous subroutines or variables as filters, or pass arguments to filters (but you can define local filter methods to get around this).

One common use of this form is to escape HTML strings:

<% $message_body | H %>

The H filter is provided along with other web-related filters in Mason::Plugin::HTMLFilters.

Applying filter to current component

Mason 1′s <%filter> section was good for filtering the content of the current component. e.g. to make it uppercase:

<%filter>
$_ = uc($_);
</%filter>

In Mason 2 the most succinct replacement is currently an around modifier:

<%around main>
<% sub { uc($_[0]) } { %>
% $self->$orig();
</%>
</%around>        

Creating filters

Here’s a filter package that implements two filters, Upper and Lower:

package MyApp::Filters;
use Method::Signatures::Simple;
use Moose::Role;
 
method Upper () {
    return sub { uc($_[0]) }
}
 
method Lower () {
    return sub { lc($_[0]) }
}
 
1;

To use these in a component:

<%class>
with 'MyApp::Filters';
</%class>

<% $.Upper { %>
...
</%>

Or if you want them available to all components, put them in Base.pm at the top of your component hierarchy, or in your application’s Mason::Component subclass.

Simple vs. dynamic filters

A simple filter is a code ref which takes a string and returns the output, like Upper and Lower above.

A dynamic filter (a Mason::DynamicFilter object) contains a code ref which takes a yield block and returns the output. A yield block is a zero-argument code ref that returns a content string.

The power of dynamic filters is that they can choose if and when to execute the yield block. For example, here’s the standard Cache filter in action:

<% $.Cache($key, '1 hour') { %>
... some computed content ...
</%>

This caches the inner content for one hour based on cache key $key. Here’s the implementation:

method Cache ( $key, $set_options ) {
    Mason::DynamicFilter->new(
        filter => sub {
            my $yield = shift;
            $self->cmeta->cache->compute( $key, $yield, $set_options );
        }
    );
}

Using CHI’s compute method, we check the cache first and return the output immediately if it is available. Only on a cache miss do we actually execute the (presumably expensive) yield block. This could not be implemented with a simple filter since the content would be computed every time.

Dec 19

I wrote previously about the inability of perltidy to handle the method keyword of Method::Signatures::Simple. Now, Steve Hancock has graciously accepted my patches in the latest Perl::Tidy, including prefilter and postfilter options. This allows me to easily add method support:

Perl::Tidy::perltidy(
    ...,
    prefilter => sub {
        $_ = $_[0];
        s/^method (.*)/sub $1 #__METHOD/gm;
        return $_;
    },
    postfilter => sub {
        $_ = $_[0];
        s/^sub (.*?)s* #__METHOD/method $1/gm;
        return $_;
    }
);
  • The prefilter code substitutes method for sub, and adds a comment
    so we’ll be able to find and convert these back afterwards.
  • When perltidy operates on the code, it will just see regular subs and treat them accordingly.
  • The postfilter code converts the sub back to method wherever the special comment appears.

I put this in my private Perl::Tidy subclass, along with other tweaks, such as telling perltidy to leave my Moose ‘has’ lines alone (I prefer them to always be on one line).

Then I create my own perltidy script which uses this subclass:

#!/usr/local/bin/perl
package main;
use JS::Perl::Tidy;
JS::Perl::Tidy::perltidy();

A little messy, but it works. I’m a devoted perltidy user, with enforced perltidy-on-commit policy on every project, so I’m glad I don’t have to choose between perltidy and my favorite Perl tweaks.

Dec 15

(These posts are starting to follow a familiar pattern: “In Mason 1 we did X, but in Mason 2, Moose makes it so much easier…)”

Anyway.

In Mason 1, content wrapping (the practice of wrapping HTML in one or more surrounding templates) was achieved via autohandlers. Each autohandler would print its content and then call $m->call_next, which would pass control to the next component down the subclass chain. This was all special-purpose code written against Mason’s already hacky inheritance scheme.

But in Mason 2, Moose gives us a natural solution for this pattern: inner and augment.

At the start of a Mason 2 request, after determining the top-level component (aka “page component”), Mason will call that component’s render() method. By default, render() will just call main(), which outputs the main body of the component. However, each ancestor of the page component has an opportunity to wrap render() with its own template. For example:

# /Base.m - top-most template
#
<%augment render>
  <html><body>
      <% inner() %>
      <div class="footer">Copyright 2010 McHuffy Inc.</div>
    </body></html>
</%augment>

# /product/Base.m - product-specific template
#
<%augment render>
  <h2>Products</h2>
  <& product_nav.mi &>
  <div class="products_body">
    <% inner() %>
  </div>
</%augment>

# /product/sales/Base.pm - utility methods, no additional template
#
<%method some_utility_method>
   ...
</%method>

# /product/sales/display.m:
#
<h3><% $product->title %></h3>
...

The page /product/sales/display will be wrapped by two templates: the outer one
in /Base.pm, and the inner one in /product/Base.pm.

A couple of new things here for Mason 1 users:

  • ‘autohandler’ has changed to ‘Base.m’. A component of this name becomes the automatic superclass of every component in its directory and subdirectories.
  • There are sections for declaring Moose methods and method modifiers with embedded-Perl syntax: <%after>, <%around>, <%augment>, <%before>, and <%method>. (Why we “need” all these explicit sections is a subject for another post.)

Now here’s an implementation snag. Notice that neither /product/sales/display nor /product/sales/Base.pm have a render method. For the former, we want to automatically create a render that just calls main, which will display the main body of the component. For the latter, we want render to just fall through to the next level. But there’s no way to know in advance whether a component will be used as the page component or as one of its superclasses, so we have to create a default render for every component that does the right thing at runtime. In pseudo-code:

if (we are a superclass of the page component) {
    # Go to the next level.
    inner();
} else {
    # We are the page component. Draw the main content.
    $self->main();
}

Unfortunately there’s no official way to ask Moose whether we’re at the bottom of the inner() chain. So I’ve got a couple of choices here:

1. Check ref($self):

if ( ref($self) ne __PACKAGE__ ) {
    inner();
} else {
    $self->main();
}

As long as we provide a default render for every component, I think this should correctly distinguish the bottom of the chain. But I’m not entirely sure – Moose does a lot of with auto-generated subclasses.

2. Steal the code out of Moose::inner:

if ( $Moose::INNER_BODY ) {
    inner();
} else {
    $self->main();
}

Of course this is awful, as it relies on implementation details that are subject to change.

For now I’ll be going with #1.

Dec 14

In Mason 1, extending Mason’s behavior means either using the limited plugin API (allowing you to take action before and after a request or component call), or else writing subclasses, which is problematic when you try to use more than one together.

In Mason 2, plugins are based on Moose roles, allowing you to modify behavior in each of Mason’s main subclasses — Interp, Request, Compiler, Compilation, and Component — in a composable way.

Here’s my first Mason 2 plugin, to perltidy object files after components are compiled – useful in development. First, a nominal base class:

package Mason::Plugin::TidyObjectFiles;
use Moose;
extends 'Mason::Plugin';

1;

(This has to exist for Mason to recognize the plugin, but there isn’t much to do there right now.)

Then, a role for each of Mason’s subclasses that we want to modify. In this case we only need to modify Mason::Compiler:

package Mason::Plugin::TidyObjectFiles::Compiler;
use Moose::Role;
use Perl::Tidy;
use strict;
use warnings;

has 'tidy_options' => ( is => 'ro' );

around 'write_object_file' => sub {
    my ( $orig, $self, $object_file, $object_contents ) = @_;

    my $argv = $self->tidy_options || '';
    my $source = $object_contents;
    Perl::Tidy::perltidy(
        'perltidyrc' => '/dev/null',
        source       => $source,
        destination  => $object_contents,
        argv         => $argv
    );
    $self->$orig( $object_file, $object_contents );
};

1;

To use this, I simply list ‘TidyObjectFiles’ in my plugins:

my $mason = Mason->new(..., plugins=>[ 'TidyObjectFiles' ]);

or, if I want to specify perltidy options:

my $mason = Mason->new(..., plugins=>[ 'TidyObjectFiles' ], tidy_options => '-noll -l=100');

The Mason::Plugin:: prefix is automatically added to plugin names. You can also specify a full path with a leading ‘+’, e.g.

plugins => ['+MyApp::Plugin::MyPlugin']

Now my object files go from looking like this:

no warnings 'redefine';
sub _comp_info { return {comp_dir_path => '/',comp_is_external => 1,comp_path => '/hi.m'} }
sub main {
my $self = shift;
my $m = $self->m;

my $_buffer = $m->current_buffer;
 #line 1 "/Users/swartz/git/mason.git/tmp/comps/hi.m"
$$_buffer .= 'Hi there! The time is ';
 #line 1 "/Users/swartz/git/mason.git/tmp/comps/hi.m"
{ $$_buffer .=  scalar(localtime)  if defined( scalar(localtime) ) }
 #line 1 "/Users/swartz/git/mason.git/tmp/comps/hi.m"
$$_buffer .= '.
';


;return;
}

to this:

no warnings 'redefine';

sub _comp_info {
    return {
        comp_dir_path    => '/',
        comp_is_external => 1,
        comp_path        => '/hi.m'
    };
}

sub main {
    my $self = shift;
    my $m    = $self->m;

    my $_buffer = $m->current_buffer;

    #line 1 "/Users/swartz/git/mason.git/tmp/comps/hi.m"
    $$_buffer .= 'Hi there! The time is ';

    #line 1 "/Users/swartz/git/mason.git/tmp/comps/hi.m"
    { $$_buffer .= scalar(localtime) if defined( scalar(localtime) ) }

    #line 1 "/Users/swartz/git/mason.git/tmp/comps/hi.m"
    $$_buffer .= '.
';

    return;
}
Dec 12

In Mason 1 you can declare component arguments and then refer to them as normal lexically scoped variables:

<%args>
$address
$city
$name
</%args>

Dear <% $name %>: We will come to your house at <% $address %> in the
fair city of <% $city> to deliver your prize!

In Mason 2, components are classes rather than subroutines, so we have attributes rather than arguments. When you call a component, you create an instance of the component class and pass attributes to the constructor.

Attributes have several advantages over arguments: you can refer to them in any of the component’s methods (unlike in Mason 1, where arguments have to be awkwardly passed to each method) and you can take advantage of Moose’s powerful attribute declarations.

Here’s how this looks without any special syntax:

<%class>
has 'address' => (is => 'ro');
has 'city'    => (is => 'ro');
has 'name'    => (is => 'ro');
</%class>

Dear <% $self->name %>: We will come to your house at <% $self->address %> in the fair city of <% $self->city> to deliver your prize!

Clearly, we’ll need to pour some sugar on this.

Declaring attributes

Mason 2 will provide an <%attr> section, analagous to Mason 1′s <%args>:

<%attr>
a
b => 'foo'
c => (isa => 'Str', default => 'something')
</%attr>

This illustrates the three kinds of <%attr> declarations:

  • A name by itself: required attribute.
  • A name followed by => and a non-paren: optional attribute with a default.
  • A name followed by => a paren: specifies Moose attribute options.

You can mix and match these attributes with standard has declarations. The above is equivalent to:

<%class>
has 'a' => (required => 1);
has 'b' => (default => 'foo');
has 'c' => (isa => 'Str', default => 'something');
</%class>

All attributes will be read-write by default, via MooseX::HasDefaults::RW. Although read-write attributes are sometimes discouraged, I believe they’re appropriate and convenient for these short-lived component objects that are not generally expected to be accessed outside of their class.

Accessing attributes

To make the frequent access of attributes more convenient, we resort to some limited source filtering evil and implement Perl 6ish $. notation. Specifically, all occurrances of

$.foo

within Perl sections will be replaced with

$self->foo

where foo is any valid attribute name ([A-Za-z_]w*).

Note that with read-write lvalue attributes, this could even be used for assignment:

$.foo = 5;

Very convenient for attributes which exist chiefly for sharing data between methods.

The $. substitution feature will be made easy to disable, for those who are against it.

Putting it all together

The first example above with attribute declaration and access sugar:

<%attr>
address
city
name
</%attr>

Dear <% $.name %>: We will come to your house at <% $.address %> in the
fair city of <% $.city> to deliver your prize!
preload preload preload