| 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; | ||||||