Skip to content

Commit b8b66d0

Browse files
committed
v0.003 - routers
1 parent b6c1f8d commit b8b66d0

File tree

7 files changed

+261
-54
lines changed

7 files changed

+261
-54
lines changed

lib/Slick.pm

Lines changed: 26 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -14,37 +14,14 @@ use Slick::Events qw(EVENTS BEFORE_DISPATCH AFTER_DISPATCH);
1414
use Slick::Database;
1515
use Slick::Methods qw(METHODS);
1616
use Slick::Route;
17+
use Slick::Router;
1718
use Slick::RouteMap;
1819
use Slick::Util;
1920

20-
our $VERSION = '0.002';
21+
our $VERSION = '0.003';
2122

2223
with 'Slick::EventHandler';
23-
24-
foreach my $meth ( @{ METHODS() } ) {
25-
Slick::Util::monkey_patch(
26-
__PACKAGE__,
27-
$meth => sub {
28-
my ( $self, $route, $callback, $events ) = @_;
29-
30-
my $route_object = Slick::Route->new(
31-
callback => $callback,
32-
route => $route
33-
);
34-
35-
if ($events) {
36-
foreach my $event ( EVENTS->@* ) {
37-
$route_object->on( $event, $_ )
38-
for ( @{ $events->{$event} } );
39-
}
40-
}
41-
42-
$self->handlers->add( $route_object, $meth );
43-
44-
return $route_object;
45-
}
46-
);
47-
}
24+
with 'Slick::RouteManager';
4825

4926
has port => (
5027
is => 'ro',
@@ -88,11 +65,6 @@ has dbs => (
8865
default => sub { return {}; }
8966
);
9067

91-
has handlers => (
92-
is => 'rw',
93-
default => sub { return Slick::RouteMap->new; }
94-
);
95-
9668
has helpers => (
9769
is => 'rw',
9870
isa => HashRef,
@@ -126,7 +98,7 @@ sub _dispatch {
12698

12799
my $method = lc( $request->method );
128100

129-
for ( @{ $self->_event_handlers->{ BEFORE_DISPATCH() } } ) {
101+
for ( @{ $self->event_handlers->{ BEFORE_DISPATCH() } } ) {
130102
if ( !$_->( $self, $context ) ) {
131103
goto DONE;
132104
}
@@ -144,7 +116,7 @@ sub _dispatch {
144116
}
145117

146118
$_->( $self, $context )
147-
for ( @{ $self->_event_handlers->{ AFTER_DISPATCH() } } );
119+
for ( @{ $self->event_handlers->{ AFTER_DISPATCH() } } );
148120

149121
DONE:
150122

@@ -154,14 +126,6 @@ sub _dispatch {
154126
return $context->to_psgi;
155127
}
156128

157-
sub BUILD {
158-
my $self = shift;
159-
160-
$self->{_event_handlers} = { map { $_ => [] } EVENTS->@* };
161-
162-
return $self;
163-
}
164-
165129
sub helper {
166130
my ( $self, $name, $helper ) = @_;
167131

@@ -224,6 +188,17 @@ sub run {
224188
return $self->server->run( $self->app );
225189
}
226190

191+
sub register {
192+
my $self = shift;
193+
my $router = shift;
194+
195+
croak qq{Router cannot be undef.} unless $router;
196+
197+
$self->handlers->merge( $router->handlers, $router->event_handlers );
198+
199+
return $self;
200+
}
201+
227202
# This is for users who want to use plackup
228203
sub app {
229204
my $self = shift;
@@ -347,6 +322,14 @@ You can register more Plack middlewares with your application using the L<"middl
347322
348323
Converts the L<Slick> application to a PSGI runnable app.
349324
325+
=head2 register
326+
327+
my $router = Slick::Router->new(base => '/foo');
328+
329+
$s->register($router);
330+
331+
Registers a L<Slick::Router> to the application. This includes calling C<merge> on the app's L<Slick::RouteMap>.
332+
350333
=head2 banner
351334
352335
$s->banner;
@@ -473,6 +456,8 @@ Inherited from L<Slick::EventHandler>.
473456
474457
=over2
475458
459+
=item * L<Slick::Router>
460+
476461
=item * L<Slick::Context>
477462
478463
=item * L<Slick::Database>

lib/Slick/EventHandler.pm

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use Carp qw(croak);
88
use Slick::Events qw(EVENTS);
99
use List::Util qw(reduce);
1010

11-
has _event_handlers => (
11+
has event_handlers => (
1212
is => 'ro',
1313
lazy => 1,
1414
isa => HashRef,
@@ -28,9 +28,9 @@ sub on {
2828

2929
croak qq{Invalid event '$event', I only know of ( }
3030
. ( reduce { $a . ', ' . $b } EVENTS->@* ) . ' )'
31-
unless exists $self->_event_handlers->{$event};
31+
unless exists $self->event_handlers->{$event};
3232

33-
push @{ $self->_event_handlers->{$event} }, $code;
33+
push @{ $self->event_handlers->{$event} }, $code;
3434
return $code;
3535
}
3636

lib/Slick/Route.pm

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ has callback => (
2121
sub dispatch {
2222
my ( $self, @args ) = @_;
2323

24-
for ( @{ $self->_event_handlers->{ BEFORE_DISPATCH() } } ) {
24+
for ( @{ $self->event_handlers->{ BEFORE_DISPATCH() } } ) {
2525
if ( !$_->(@args) ) {
2626
goto DONE;
2727
}
2828
}
2929

3030
$self->callback->(@args);
3131

32-
for ( @{ $self->_event_handlers->{ AFTER_DISPATCH() } } ) {
32+
for ( @{ $self->event_handlers->{ AFTER_DISPATCH() } } ) {
3333
if ( !$_->(@args) ) {
3434
goto DONE;
3535
}

lib/Slick/RouteManager.pm

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package Slick::RouteManager;
2+
3+
use 5.036;
4+
5+
use Moo::Role;
6+
7+
use Types::Standard qw(Str);
8+
use Slick::Events qw(EVENTS);
9+
use Slick::Methods qw(METHODS);
10+
11+
has base => (
12+
is => 'ro',
13+
isa => Str,
14+
default => ''
15+
);
16+
17+
has handlers => (
18+
is => 'rw',
19+
default => sub { return Slick::RouteMap->new; }
20+
);
21+
22+
foreach my $meth ( @{ METHODS() } ) {
23+
Slick::Util::monkey_patch(
24+
__PACKAGE__,
25+
$meth => sub {
26+
my ( $self, $route, $callback, $events ) = @_;
27+
28+
$route = '/' . $route
29+
if ( $route ne '' ) && ( rindex( $route, '/', 0 ) != 0 );
30+
31+
$route = $self->base . $route if $self->base;
32+
33+
my $route_object = Slick::Route->new(
34+
callback => $callback,
35+
route => $route
36+
);
37+
38+
if ($events) {
39+
foreach my $event ( EVENTS->@* ) {
40+
$route_object->on( $event, $_ )
41+
for ( @{ $events->{$event} } );
42+
}
43+
}
44+
45+
$self->handlers->add( $route_object, $meth );
46+
47+
return $route_object;
48+
}
49+
);
50+
}
51+
52+
sub BUILD {
53+
my $self = shift;
54+
55+
$self->{base} = '/' . $self->base
56+
if ( $self->base ne '' ) && ( rindex( $self->base, '/', 0 ) != 0 );
57+
58+
return $self;
59+
}
60+
61+
1;
62+
63+
=encoding utf8
64+
65+
=head1 NAME
66+
67+
Slick::RouteManager
68+
69+
=head1 SYNOPSIS
70+
71+
A L<Moo::Role> that allows the managing of routes via a L<Slick::RouteMap> and HTTP methods.
72+
73+
=over2
74+
75+
=item * L<Slick>
76+
77+
=item * L<Slick::Router>
78+
79+
=item * L<Slick::Context>
80+
81+
=item * L<Slick::Database>
82+
83+
=item * L<Slick::DatabaseExecutor>
84+
85+
=item * L<Slick::DatabaseExecutor::MySQL>
86+
87+
=item * L<Slick::DatabaseExecutor::Pg>
88+
89+
=item * L<Slick::EventHandler>
90+
91+
=item * L<Slick::Events>
92+
93+
=item * L<Slick::Methods>
94+
95+
=item * L<Slick::RouteMap>
96+
97+
=item * L<Slick::Util>
98+
99+
=back
100+
101+
=cut

lib/Slick/RouteMap.pm

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use 5.036;
55
use Moo;
66
use Types::Standard qw(HashRef);
77
use Slick::Methods qw(METHODS);
8+
use Slick::Events qw(EVENTS);
89
use Carp qw(croak);
910
use Scalar::Util qw(blessed);
1011
use List::Util qw(first);
@@ -28,7 +29,7 @@ sub add {
2829
croak qq{Unrecognized HTTP method $method.}
2930
unless defined( grep { $_ eq $method } METHODS() );
3031

31-
chomp($route);
32+
chomp( $route->{route} );
3233
my $uri =
3334
substr( $route->route, 0, 1 ) eq '/'
3435
? substr( $route->route, 1 )
@@ -101,6 +102,41 @@ sub get {
101102
return $m->{methods}->{$method};
102103
}
103104

105+
# Merge two route maps
106+
sub merge {
107+
my $self = shift;
108+
my $other = shift;
109+
my $events = shift;
110+
111+
my @stack;
112+
113+
push( @stack,
114+
$other->{_map}->{'/'} // croak qq{Invalid route map passed.} );
115+
116+
# FIXME: This may get slow on very large projects, but we'll see.
117+
while ( my $p = pop @stack ) {
118+
for ( keys $p->{children}->%* ) {
119+
push( @stack, $p->{children}->{$_} );
120+
}
121+
122+
for ( keys $p->{methods}->%* ) {
123+
my $route = $p->{methods}->{$_};
124+
125+
# TODO: This sucks!
126+
foreach my $event ( EVENTS()->@* ) {
127+
$route->event_handlers->{$event} = [
128+
$events->{$event}->@*,
129+
$route->event_handlers->{$event}->@*
130+
];
131+
}
132+
133+
$self->add( $route, $_ );
134+
}
135+
}
136+
137+
return $self;
138+
}
139+
104140
1;
105141

106142
=encoding utf8
@@ -125,12 +161,18 @@ Otherwise return C<undef>.
125161
126162
Given a L<Slick::Route> and a uri (Str), add it to the Hash-Trie for later lookup.
127163
164+
=head2 merge
165+
166+
Merges two given L<Slick::RouteMap>s. This is the primary mechanism behind L<Slick::Router>.
167+
128168
=head1 See also
129169
130170
=over2
131171
132172
=item * L<Slick>
133173
174+
=item * L<Slick::Router>
175+
134176
=item * L<Slick::Context>
135177
136178
=item * L<Slick::Database>

0 commit comments

Comments
 (0)