NAME
MojoX::Automata - Call Mojo dispatchers in a finite automata manner
SYNOPSIS
# Real app flow
no yes
static file -------> detect user language ---> routes match ---+
| | |
| no | v
yes | 404 ---<-------------------+ get user
| | 403 <------+ |
| +---->----+ | not ok v
| | +-----<----- check access
| not ok v | ok
+-----<---- 500 <---------- render view <+ ok v
| ^ ok | +---------- routes dispatch
+-----<------^------<----------+ |
v | not ok |
end +---------------<---------------<------------+
package
MyApp;
use strict;
use warnings;
use base 'MojoliciousX::Automata';
use MojoX::Automata;
__PACKAGE__->attr(
config => (default => sub { {languages => [qw/ de en /]}; }));
# This method will run for each request
sub dispatch {
my ($self, $c) = @_;
# Run automata
$self->automata->run($c);
}
# This method will run once at server start
sub startup {
my $self = shift;
# Use our own context class
$self->ctx_class('MyApp::Context');
# Routes
my $r = $self->routes;
# Default route
$r->route('/')->to(controller => 'root', action => 'default', id => 1)
->name('root');
my $automata = $self->automata;
$automata->namespace('MyApp::Automata');
# Registering states
# Detect if static file was requested
$automata->state('S')->handler('Static', static => $self->static)
->to(0 => 'l', 1 => 'E');
# Detect language from the url (http://example.com/en/stuff) etc.
$automata->state('l')
->handler('DetectLang', languages => $self->config->{languages})
->to('t_on');
# Get page rendering time
$automata->state('t_on')->handler('TimerOn')->to('m');
# Mojo Routes (just the part that matches the route without calling
# appropriate controller)
$automata->state('m')->handler('Match', routes => $self->routes)
->to(0 => 'n', 1 => 'u');
# Serving 404 error
$automata->state('n')->handler('NotFound')->to('v');
# Mojo Routes controller call part
$automata->state('d')->handler('Dispatch', routes => $self->routes)
->to(302 => 'E', 500 => 'e', 200 => 't_off', 404 => 'n', 403 => 'f');
# Checking access
$automata->state('a')->handler('CheckAccess')->to(0 => 'f', 1 => 'd');
# Rendering view (no need to call $self->render in every controller)
$automata->state('v')->handler('RenderView')->to(0 => 'e', 1 => 'E');
# Serving 403 error
$automata->state('f')->handler('Forbidden')->to('v');
# Serving 500 error
$automata->state('e')->handler('InternalError')->to('E');
# Get user from cookie etc
$automata->state('u')->handler('User')->to('a');
$automata->state('t_off')->handler('TimerOff')->to('v');
# No 'E' state specified because is it the end state.
}
1;
# You can find all these states in the examples/ dir of the distribution
DESCRIPTION
MojoX::Automata is a Mojo finite automata dispatching mechanizm.
ATTRIBUTES
namespace
# Set namespace for the state classes
$self->namespace(__PACKAGE__);
limit
Holds state change limit number. Dies with an error 'Looks like an infinite loop' after limit is reached. It is 10000 by default.
METHODS
MojoX::Automata inherits all methods from Mojo::Base and implements the following the ones.
state
Register a new state(s).
$automata->state('routes');
Note that if you don't specify a handler to this state it is going be a dead end. This is a way to define 'End' state for example.
handler
Add a new handler to the state.
# Object
$state->handler(Handler->new);
# Will load Handler class, and will create instance with arguments provided
$state->handler('Handler' => (arg => 'foo'));
# Pass anonymous subroutine
$state->handler(sub { return 1 });
to
Add path between states.
# Swith from state B<a> to B<a> without any return value checks.
$state->to('r' => 'a');
# Swith from state B<s> to B<e> if state returns B<1>.
$state->to('s', 1 => 'e');
run
# Run automata. Parameters provided will be passed on to every state.
$automata->run($c);
EXAMPLE
You can find example app ready to go in examples/ directory.
COPYRIGHT & LICENSE
Copyright 2008 Viacheslav Tykhanovskyi, all rights reserved.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.