The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Kelp::Module - Base class for Kelp modules

SYNOPSIS

package Kelp::Module::MyModule;
use parent 'Kelp::Module';

sub build {
    my ( $self, %args ) = @_;
    $self->register( greet => sub { print "Hi there." } );
}

DESCRIPTION

Provides the base class for creating Kelp modules. Creating a Kelp module means extending this class and overriding the build method. Kelp modules usually register a new method into the web application.

Registering methods

Modules use the "register" method to register new methods into the underlying web application. All the registrations are done in the "build" subroutine. All types of values can be registered and then accessed as a read-only attribute from the web app. The simplest thing you can register is a scalar value:

First...

# lib/Kelp/Module/Month.pm
package Kelp::Module::Month;
use Kelp::Base 'Kelp::Module';

sub build {
    my ( $self, %args ) = @_;
    $self->register( month => 'October' );
}

Then ...

# lib/MyApp.pm
package MyApp;
use parent 'Kelp';

sub build {
    my $self = shift;
    $self->load_module("Month");
}

sub is_it_october_yet {
    my $self = shift;
    if ( $self->month eq 'October' ) {
        return "It is October";
    }
    return "Not yet.";
}

The above example doesn't do anything meaningful, but it's a good way to show how to create and use Kelp modules. Pay attention to the next example, as it will show you how to register an anonymous subroutine:

package Kelp::Module::Date;
use Kelp::Base 'Kelp::Module';
use DateTime;

sub build {
    my ( $self, %args ) = @_;
    $self->register(
        date => sub {
            return DateTime->from_epoch( epoch => time );
        }
    );
}

Now, each time you use $self->date in the web application, you will create a new DateTime object for the current time.

It is more practical to register an already created object. Consider this example, which uses Redis, initializes an instance of it and registers it as a method in the web app:

package Kelp::Module::Redis;
use Kelp::Base 'Kelp::Module';
use Redis;

sub build {
    my ( $self, %args ) = @_;
    my $redis = Redis->new(%args);
    $self->register( redis => $redis );
}

Passing arguments to your module

The arguments for all modules are taken from the configuration. If you want to pass arguments for your Redis module (example above), you will have to have a structure in your config, similar to this:

Example of conf/myapp.pl:

{
    # Load module Redis on start
    modules      => ['Redis'],
    modules_init => {
        Redis => {
            server   => '192.168.0.1:6379',
            encoding => 'UTF-8',
            password => 'boo'
        }
    }
};

The hash specified by Redis will be sent as %args in the build method of the module.

Loading modules that live outside of the Kelp::Module namespace

Kelp will automatically prefix all modules with Kelp::Module, so a module name Redis should live in Kelp::Module::Redis. To use fully qualified modules that live outside of the Kelp::Module namespace, prefix the name with a plus sign.

{
    # Load a module that lives outside of Kelp::Module
    modules      => ["+Fully::Qualified::Name"],
    modules_init => {
        "+Fully::Qualified::Name" => {...}
    }
};

METHODS

build

build( %args )

Each module must override this one in order to register new methods. The %args hash will be taken from the configuration.

register

register( %items )

Registers one or many methods into the web application.

$self->register(
    json => JSON->new,
    yaml => YAML->new
);