NAME

Wurm::let - Local Evaluation Tether

SYNOPSIS

  use Wurm qw(let);
  use Data::Dumper;

  # Re-implements the Hello, World app with let.
  sub build_grub {
    my ($name) = @_;

    return Wurm::let->new
    ->gate(sub {
      my $meal = shift;
      $meal->{vent}{to} = ucfirst $name;
      push @{$meal->{grit}{path}}, $name. '/gate';
      return;
    })
    ->neck(sub {
      my $meal = shift;
      push @{$meal->{grit}{path}}, $name. '/neck';
      return;
    })
    # The same as ->body(get       => sub { })
    # The same as ->body([qw(get)] => sub { })
    ->get(sub {
      my $meal = shift;
      push @{$meal->{grit}{path}}, $name. '/body:get';
      return;
    })
    ->tail(sub {
      my $meal = shift;
      push @{$meal->{grit}{path}}, $name. '/tail';
      return wrap_it_up($meal);
    })
  };

  sub wrap_it_up {
    my $meal = shift;

    my $path = join ', ', @{$meal->{grit}{path}};

    my $text = '';
    $text .= "$meal->{mind}{intro} $meal->{vent}{to},\n";
    $text .= "This is the path I took: $path\n";
    $text .= "This is what is in the tube: $meal->{tube}\n";
    $text .= "This is what I've seen: $meal->{seen}\n";

    return Wurm::_200('text/plain', $text);
  }

  # How many methods are called before the assignment is made?
  # This is the 'root' grub.
  my $grub = build_grub('root')
    ->case(sub {
      my $meal = shift;
      $meal->{vent}{to}   = 'Nobody';
      $meal->{grit}{path} = [ ];
      return $meal;
    })
    ->pore(sub {
      my ($res, $meal) = @_;
      $res->[2][0] = $res->[2][0]
        . ($res->[0] == 200 ? '' : "\n")
        . 'PSGI env: '. Dumper($meal->{env})
      ;
      return $res;
    })
  ;

  {
    # C<grub()> will make a new grub for us.
    # Or use what we give it.
    my $what = $grub->grub(wurm => build_grub('wurm'));

    # Grubs molt to become pretty butterflies.
    # If you believe nested hashes of anonymous sub-routines are
    # beautiful.  Or butterflies.

    # Tubes require molted grubs.
    $what->tube($_ => build_grub($_)->molt)
      for qw(foo bar baz);

    # I don't... better not to ask questions.  This looks nasty.
    $grub->grub($_ => $what->molt->{tube}{$_})
      for qw(foo baz);

    # qux is already molted inside $what.  eww.
    # I told you it was special.
    my $qux = $what->grub(qux => build_grub('qux'));
    $qux->gate(sub {
      my ($meal) = @_;
      $meal->{vent}{to} = 'Lord Qux';
      push @{$meal->{grit}{path}}, '*/gate';
      return wrap_it_up($meal);
    });
  }

  # Now turn the... uh... thing into an application.
  my $app = Wurm::wrapp($grub->molt, {intro => 'Hello'});
  $app

DESCRIPTION

Wurm::let is a utility module for helping create Wurm applications. It provides an easy-to-use OO interface for constructing folding rules without requiring applications to be OO-enabled themselves.

You can enable 'let' in two way:

  use Wurm::let;

- or -

  use Wurm qw(let);

METHODS

All methods (with the exception of grub) are meant for call chaining by returning the Wurm::let object. The grub method returns a new Wurm::let which can then be call-chained for setup.

new($bulk)

Creates a Wurm::let object for manipulating $bulk. If $bulk is not provided, it will be created as a HASH reference.

molt()

Returns the $bulk. Since folding rules are references, molt() can be called any time while still allowing changes to the Wurm::let. This allows you to either forward construct down-stream application logic and attach it in-whole to up-stream parts. Or you can create up-sream logic and generate down-stream pieces from it.

case($code)

Installs a case handler.

pore($code)

Installs a pore handler.

gate($code)

Installs a gate handler.

neck($code)

Installs a neck handler.

tail($code)

Installs a tail handler.

tube($name, $wurm)

Installs a tube handler tree with the key $name and a folding ruleset of $wurm. If $wurm is not provided it will be created for you. An easy way to chain application parts together is to create Wurm::let objects and molt() them into tube or use grub below.

  my $stub = Wurm::let->new
    ->gate(sub { })
    ->post(sub { })
  ;

  my $root = Wurm::let->new
    ->case(sub { })
    ->pore(sub { })
    ->tube(foo => $stub->molt)
    ->tube(bar => $stub->molt)
  ;
grub($name, $grub)

Installs a tube handler tree with the key $name and a folding ruleset of $grub. If $grub is not provided it will be created for you. If it is a HASH reference, it will be converted to a Wurm::let object which is returned.

  my $root = Wurm::let->new;

  # /mirror/ now contains the same folding rules as $root
  $root->grub(mirror => $root)
       ->tail(sub { });          # changes /mirror/

  # /foo/ will respond to gate and body/{get,post}
  my $wurm = {gate => sub { ... }, ...};
  my $grub = $root->grub(foo => $wurm);
  $grub->body([qw(get post)] => sub { ... });
body($methods, $code)

Installs a body handler. $methods can either be a simple string or an ARRAY reference. If multiple methods are given, the same handler is installed for all of them.

get($code)

Installs a body handler for the 'GET' HTTP method.

head($code)

Installs a body handler for the 'HEAD' HTTP method.

post($code)

Installs a body handler for the 'POST' HTTP method.

put($code)

Installs a body handler for the 'PUT' HTTP method.

delete($code)

Installs a body handler for the 'DELETE' HTTP method.

trace($code)

Installs a body handler for the 'TRACE' HTTP method.

options($code)

Installs a body handler for the 'OPTIONS' HTTP method.

connect($code)

Installs a body handler for the 'CONNECT' HTTP method.

patch($code)

Installs a body handler for the 'PATCH' HTTP method.

SEE ALSO

Wurm

AUTHOR

jason hord <pravus@cpan.org>

LICENSE

This software is information. It is subject only to local laws of physics.