We're looking at options for converting CamelCase to camel-case
and underscores to hyphens and hoping someone can offer some strong examples. (Using hyphens for SEO reasons).
Specifically:
Working on an MMORPG in Catalyst and getting tired of having to write things like this:
sub travel_to ( $self, $c, $star ) : Path('travel-to') Args(1) { ... }
Or this:
package Veure::Controller::Area::StorageLocker {
....
sub index ( $self, $c ) : Path('/area/storage-locker') { ... }
}
Update: Because there's some confusion, I meant that we'd much prefer to have devs write this:
# getting rid of Args() would be nice, but sigs don't have introspection
sub travel_to ( $self, $c, $star ) : Args(1) { ... }
Or this:
package Veure::Controller::Area::StorageLocker {
....
sub index ( $self, $c ) { ... }
}
This is important because for an SEO standpoint, underscores instead of hyphens can dramatically improve your SEO. By having to do extra grunt work to always force hyphens, developers are forgetting to do this and we keep wasting money going back and having to rewrite code where this caveat was forgotten. This is the sort of thing which we should be able to do automatically.
I did a bit of digging in the Catalyst sources.
Cammel case controller names
You can modify class2prefix
in Catalyst::Utils to change how the controller names translate to the namespace.
Here is a very quick hack that demonstrates what is going on with a fresh MyApp created with catalyst.pl. I borrowed Borodin's suggestion to implement it.
package MyApp::Controller::FooBar;
use Moose;
use namespace::autoclean;
BEGIN { extends 'Catalyst::Controller'; }
{
require Class::Method::Modifiers;
require String::CamelCase;
Class::Method::Modifiers::around(
'Catalyst::Utils::class2prefix' => sub {
my $orig = shift;
# I borrowed most of this from the original function ...
my $class = shift || '';
my $prefix = shift || 0;
if ( $class =~ /^.+?::([MVC]|Model|View|Controller)::(.+)$/ ) {
$prefix = $2;
$prefix =~ s{::}{/}g;
# ... and this from https://stackoverflow.com/a/37968830/1331451
$prefix = String::CamelCase::decamelize($prefix) =~ tr/_/-/r;
}
return $prefix;
}
);
}
sub index :Path :Args(0) {
my ( $self, $c ) = @_;
$c->response->body('Matched MyApp::Controller::FooBar in FooBar.');
}
1;
I tested this briefly, but cannot guarantee it's not going to break anything else. I believe if it's put into a better place and done in a more appropriate way it could be a viable option.
Underscores in actions
This one looks trickier. My best bet is to fiddle with Catalyst::DispatchType::Path in some way, or create something that installs an ActionClass that modifies it. It's basically replacing the _
with a -
. That thing could be built around gather_default_action_roles
in Catalyst::Controller (maybe as a subclass) to add that one to all actions. This is highly speculative.
CPAN has the String::CamelCase
module, which offers a decamelize
function, after which you will need to convert underscores to hyphens using tr/_/-/
I hope this short example helps to answer your question
use strict;
use warnings 'all';
use v.14.1;
use String::CamelCase 'decamelize';
for my $s ( 'travel_to', 'Veure::Controller::Area::StorageLocker' ) {
(my $ss = $s) =~ s|^[\w:]*::Controller(?=::)||;
$ss =~ s|::|/|g;
$ss = decamelize($ss) =~ tr/_/-/r;
say $ss;
}
travel-to
/area/storage-locker
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With