Docendo discimus

$self->explain

  • Calendar

    November 2008
    M T W T F S S
    « Oct   Apr »
     12
    3456789
    10111213141516
    17181920212223
    24252627282930
  • Archives

  • Recent Posts

  • Bling

Generating HTML with Moose, part 1

Posted by brunorc on November 17, 2008

It will be rather simple story, as my relationship with Moose is still far from familiarity. But wishing to show the already learnt part, I decided to put it on the blog as a short tutorial.

#!/usr/bin/env perl

use strict;
use warnings;
use feature 'say'; # use 5.10
{
    package Container;
    use Moose;
    has 'content' => (
        is => 'rw',
        isa => 'Str',
        default => 'Moose is great'
    );
    sub render {
        my $self = shift;
        say '<div>' . $self->content . '</div>';
    }
}

The class is very straightforward. It has the content attribute and the render method, used to “generate” the HTML-ized content. In case the user didn’t put any content, I provided some default value.

We can say that page is just a big container, but somehow different. It will have a header and a footer, and in lieu of simple text attribute it will rather have a collection of other containers:

{
    package Container::Page;

    use Moose;

    extends 'Container'; # we inherit from Container

    has 'title' => (
        is => 'rw',
        isa => 'Str',
        default => 'Moose strikes back!'
    );

    has 'body' => (
        is => 'rw',
        isa => 'ArrayRef[Container]',
    );

    sub render {
        my $self = shift;
        map { $_->render . "\n" } @{ $self->body };
    }
}

Now I have the stub of the class. Still no header, though. But before I take care about this, I’d like to note the sugar which comes with Moose. As we can see, body is an array reference. Thus, it will be dereferenced a lot. Instead of writing @{ $self->body } every now and then, I can ask Moose to dereference it for me:

    has 'body' => (
        is = 'rw',
        isa => 'ArrayRef[Container]',
        auto_deref => 1,
    );

    sub render {
        my $self = shift;
        map { $_->render . "\n" } $self->body;
    }

Now to the header. Of course I can put the additional HTML chunks in the render method, but I can also use method modifiers. Let’s see:

    before 'render' => sub {
        my $self = shift;
        say "<html>\n<head><title>" . $self->title
            . "</title></head>\n<body>";
    };

    after 'render' => sub {
        say "</body>\n</html>";
    };

Note that I inherit the content attribute from Container, but later I don’t use it. It’s bad, because someone may want to place the static text in this attribute, thus being rather disappointed when it doesn’t appear. I promise to be neater in the second part. But before this we can see the result of our work:

my $block = Container->new(
    { content => "This is an example of the Moose power!" }
);
my $defblock = Container->new;
my $page = Container::Page->new(
    { body => [ $block, $defblock ] }
);
$page->render;
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: