File: | lib/Railsish/Router.pm |
Coverage: | 89.6% |
line | stmt | bran | cond | sub | pod | time | code |
---|---|---|---|---|---|---|---|
1 | package Railsish::Router; | ||||||
2 | 13 13 13 | 603 48 156 | use Any::Moose; | ||||
3 | |||||||
4 | 13 13 13 | 1074 67 213 | use Path::Router; | ||||
5 | |||||||
6 | has "routers" => ( | ||||||
7 | is => "rw", | ||||||
8 | isa => "HashRef[Path::Router]", | ||||||
9 | lazy_build => 1, | ||||||
10 | ); | ||||||
11 | |||||||
12 | has named_routes => ( | ||||||
13 | is => "rw", | ||||||
14 | isa => "HashRef", | ||||||
15 | default => sub {{}} | ||||||
16 | ); | ||||||
17 | |||||||
18 | sub _build_routers { | ||||||
19 | return { | ||||||
20 | 12 | 894 | get => Path::Router->new, | ||||
21 | post => Path::Router->new, | ||||||
22 | put => Path::Router->new, | ||||||
23 | delete => Path::Router->new | ||||||
24 | } | ||||||
25 | } | ||||||
26 | |||||||
27 | my $APP_ROUTER; | ||||||
28 | |||||||
29 | sub connect { | ||||||
30 | 39 | 0 | 441 | my ($self, $urlish, %vars) = @_; | |||
31 | 39 | 290 | $self = $APP_ROUTER unless ref($self); | ||||
32 | |||||||
33 | 39 | 366 | $urlish =~ s/^\/*/\//; | ||||
34 | |||||||
35 | 39 | 638 | if (defined $vars{path_prefix}) { | ||||
36 | 4 | 25 | $vars{path_prefix} =~ s/^\/*/\//; | ||||
37 | 4 | 20 | $urlish = $vars{path_prefix} . $urlish; | ||||
38 | } | ||||||
39 | |||||||
40 | 39 | 161 | my $conditions = delete $vars{conditions}; | ||||
41 | 39 | 253 | my $routers = $self->routers; | ||||
42 | |||||||
43 | 105 | 1737 | return map { | ||||
44 | 105 | 401 | $_->add_route($urlish => (defaults => \%vars)); | ||||
45 | 105 | 9874 | $_->routes->[-1]; | ||||
46 | } | ||||||
47 | map { | ||||||
48 | 39 | 2564 | $routers->{$_}; | ||||
49 | } | ||||||
50 | ( | ||||||
51 | $conditions | ||||||
52 | ? lc($conditions->{method}) | ||||||
53 | : qw(get post put delete) | ||||||
54 | ); | ||||||
55 | } | ||||||
56 | |||||||
57 | sub match { | ||||||
58 | 27 | 0 | 259 | my ($self, $uri, %args) = @_; | |||
59 | 27 | 213 | $self = $APP_ROUTER unless ref($self); | ||||
60 | |||||||
61 | 27 | 217 | my $routers = $self->routers; | ||||
62 | 27 | 552 | my $conditions = delete $args{conditions}; | ||||
63 | |||||||
64 | 27 | 215 | for($conditions ? lc($conditions->{method}) : qw(get post put delete)) { | ||||
65 | 27 | 245 | if (my $matched = $routers->{$_}->match($uri)) { | ||||
66 | 23 | 13867 | return $matched; | ||||
67 | } | ||||||
68 | } | ||||||
69 | } | ||||||
70 | |||||||
71 | sub uri_for { | ||||||
72 | 3 | 0 | 48 | my ($self, @args) = @_; | |||
73 | 3 | 35 | $self = $APP_ROUTER unless ref($self); | ||||
74 | |||||||
75 | 3 | 26 | my $routers = $self->routers; | ||||
76 | 3 | 38 | for (qw(get post put delete)) { | ||||
77 | 3 | 33 | if (my $url = $routers->{$_}->uri_for(@args)) { | ||||
78 | 3 | 3402 | return "/$url"; | ||||
79 | } | ||||||
80 | } | ||||||
81 | } | ||||||
82 | |||||||
83 | 13 13 13 | 766 61 172 | use Railsish::TextHelpers qw(singularize pluralize); | ||||
84 | |||||||
85 | sub resources { | ||||||
86 | 3 | 0 | 26 | my ($self, $name, @vars) = @_; | |||
87 | 3 | 29 | $self = $APP_ROUTER unless ref($self); | ||||
88 | |||||||
89 | 3 | 22 | my $resource = singularize($name); | ||||
90 | 3 | 29307 | my $resources = pluralize($name); | ||||
91 | |||||||
92 | 3 | 3325 | my $edit = "edit_${resource}"; | ||||
93 | 3 | 101 | $self->$edit( | ||||
94 | "/$resources/:id/edit", | ||||||
95 | controller => $resources, | ||||||
96 | action => "edit", | ||||||
97 | @vars | ||||||
98 | ); | ||||||
99 | |||||||
100 | 3 | 14 | my $new = "new_${resource}"; | ||||
101 | 3 | 115 | $self->$new( | ||||
102 | "/$resources/new", | ||||||
103 | controller => $resources, | ||||||
104 | action => "new", | ||||||
105 | @vars | ||||||
106 | ); | ||||||
107 | |||||||
108 | 3 | 74 | $self->$resource( | ||||
109 | "/${resources}/:id", | ||||||
110 | controller => $resources, | ||||||
111 | action => "show", | ||||||
112 | @vars, | ||||||
113 | conditions => {method => "get"} | ||||||
114 | ); | ||||||
115 | |||||||
116 | 3 | 39 | $self->connect( | ||||
117 | "/${resources}", | ||||||
118 | controller => $resources, | ||||||
119 | action => "create", | ||||||
120 | conditions => {method => "post"} | ||||||
121 | ); | ||||||
122 | |||||||
123 | 3 | 92 | $self->connect( | ||||
124 | "/${resources}/:id", | ||||||
125 | controller => $resources, | ||||||
126 | action => "update", | ||||||
127 | conditions => {method => "put"} | ||||||
128 | ); | ||||||
129 | |||||||
130 | 3 | 159 | $self->connect( | ||||
131 | "/${resources}/:id", | ||||||
132 | controller => $resources, | ||||||
133 | action => "destroy", | ||||||
134 | conditions => {method => "delete"} | ||||||
135 | ); | ||||||
136 | |||||||
137 | 3 | 127 | $self->$resources( | ||||
138 | "/${resources}", | ||||||
139 | controller => $resources, | ||||||
140 | action => "index", | ||||||
141 | @vars, | ||||||
142 | conditions => {method => "get"} | ||||||
143 | ); | ||||||
144 | |||||||
145 | } | ||||||
146 | |||||||
147 | # this one should be invoked like: Railsish::Router->draw; | ||||||
148 | sub draw { | ||||||
149 | 12 | 0 | 100 | my ($class, $cb) = @_; | |||
150 | 12 | 127 | $APP_ROUTER = $class->new; | ||||
151 | 12 | 429 | $cb->($APP_ROUTER); | ||||
152 | |||||||
153 | 12 | 271 | return $APP_ROUTER; | ||||
154 | } | ||||||
155 | |||||||
156 | 13 13 13 | 165 49 214 | use Sub::Install; | ||||
157 | 13 13 13 | 612 52 69 | use Railsish::PathHelpers (); | ||||
158 | |||||||
159 | our $AUTOLOAD; | ||||||
160 | sub AUTOLOAD { | ||||||
161 | 14 | 191 | my ($self, $urlish, %vars) = @_; | ||||
162 | 14 | 128 | $self = $APP_ROUTER unless ref($self); | ||||
163 | |||||||
164 | 14 | 44 | my $name = $AUTOLOAD; | ||||
165 | 14 | 181 | $name =~ s/^.*:://; | ||||
166 | |||||||
167 | 14 | 119 | my @routes = $self->connect($urlish, %vars); | ||||
168 | 14 | 322 | my $route = $routes[0]; | ||||
169 | |||||||
170 | 14 | 91 | $self->named_routes->{$name} = $route; | ||||
171 | |||||||
172 | 14 | 118 | my $helper_name = "${name}_path"; | ||||
173 | Sub::Install::install_sub({ | ||||||
174 | into => __PACKAGE__, | ||||||
175 | code => sub { | ||||||
176 | 12 | 79 | my ($self, @args) = @_; | ||||
177 | 12 | 95 | $self = $APP_ROUTER unless ref($self); | ||||
178 | |||||||
179 | 12 | 90 | if (@args == 1 && ref($args[0]) eq 'HASH') { | ||||
180 | 2 2 | 7 19 | @args = (%{$args[0]}); | ||||
181 | } | ||||||
182 | |||||||
183 | 12 | 83 | my $temp_router = Path::Router->new; | ||||
184 | 12 12 | 979 77 | push @{$temp_router->routes}, $self->named_routes->{$name}; | ||||
185 | |||||||
186 | 12 | 84 | return "/" . $temp_router->uri_for(@args); | ||||
187 | }, | ||||||
188 | 14 | 360 | as => $helper_name | ||||
189 | }); | ||||||
190 | |||||||
191 | Sub::Install::install_sub({ | ||||||
192 | into => "Railsish::PathHelpers", | ||||||
193 | as => $helper_name, | ||||||
194 | code => sub { | ||||||
195 | 2 | 17 | return Railsish::Router->$helper_name(@_); | ||||
196 | } | ||||||
197 | 14 | 281 | }); | ||||
198 | 14 | 182 | push @Railsish::PathHelpers::HELPERS, $helper_name; | ||||
199 | } | ||||||
200 | |||||||
201 | __PACKAGE__->meta->make_immutable; |