Seems like you understand your problem and have a well-thought out design pattern! I think what you are wanting to accomplish elegantly is exactly what Mojolicious was built for <https://mojolicious.org/perldoc/Mojolicious/Guides/Routing#BASICS>!
Your two sample routes can be condensed into one to handle any number of customers, subclassed from a base class: $r->get('/api/v1/:controller/box/:id')->to('#open_box'); $ mojo generate app : $ cat my_app/lib/MyApp.pm my_app/lib/MyApp/Controller/Customer.pm my_app/lib/MyApp/Controller/Kwikemart.pm my_app/lib/MyApp/Controller/Ezymart.pm package MyApp; use Mojo::Base 'Mojolicious'; sub startup { my $self = shift; my $r = $self->routes; $r->get('/api/v1/:controller/box/:id')->to('#open_box'); } 1; package MyApp::Controller::Customer; use Mojo::Base 'Mojolicious::Controller'; sub open_box { die "open_box method not implemented by subclass" } 1; package MyApp::Controller::Kwikemart; use Mojo::Base 'MyApp::Controller::Customer'; sub open_box { my $self = shift; $self->render(text => 'Hello, Kwikemart Customer!'); } 1; package MyApp::Controller::Ezymart; use Mojo::Base 'MyApp::Controller::Customer'; sub open_box { my $self = shift; $self->render(text => 'Welcome to Ezymart!'); } 1; $ perl my_app/script/my_app routes /api/v1/:controller/box/:id GET apiv1controllerboxid *$ perl my_app/script/my_app get /api/v1/kwikemart/box/1* *Hello, Kwikemart Customer!* *$ perl my_app/script/my_app get /api/v1/ezymart/box/1* *Welcome to Ezymart!* On Wed, Jan 2, 2019 at 9:04 PM <hwmbo.l...@gmail.com> wrote: > Hey, no problem. Mojolicious so far, can do just about anything I can > think of, without much difficulty, as most stuff just work out of the box, > which is a pleasant surprise. > > If you don't mind, I'll take a step back, and describe my design and > reason behind it, and see if you can maybe spot something that's wrong with > my approach. Here's the hypothetical scenario: > > 1. Two customers, one Kwikemart, and one Ezymart, they both handle boxes, > but in different ways, one open it with a cutter, say, and the other one > insist on using bare hands. > 2. So I build one Customer class, and extend it, to implement actual > customer. Both Kwikemart and Ezymart are children of Customer class, and > each has a open_box() method, but within it, they each do their own thing. > 3. In order to expose the boxes' content as RESTful resource, the url to > access them, will be something like /api/v1/:customer/box/:boxid > > Of course, I could just code the route explicitly, since there's only two > customer, by having: > > > $r->get('/api/v1/kwikemart/box/:id')->to('Customer::Kwikemart#open_box'); > $r->get('/api/v1/ezymart/box/:id')->to('Customer::Ezymart#open_box'); > > However, it just feels not elegant. The name of the class, is the only > difference between the two different routes, and it'll be great to > generalize it within the dispatching process, so if I have hundreds > customers to do tomorrow, each of their own variants of 'open_box()' > action, can be routed with just one call, instead of hundreds, as long as > the url conforms to the '/api/v1/:customer/box/:id' format. > > Maybe I am just trying to be too clever for my own good, but I really > think there must be an easy and elegant way to do this? > > > > > On Wednesday, January 2, 2019 at 4:27:44 PM UTC-6, Stefan Adams wrote: >> >> Hi! I'm glad you were able to figure that out and even using the more >> advanced hook feature, but if I'm understanding your objective correctly, I >> would advise that you follow the references I shared. In essence, if I'm >> reading it correctly, you are using a framework and then solving problems >> on your own which are already solved by the framework. >> >> I just want to make sure you get off to a good start with Mojolicious so >> that you can reap the full benefits of the framework and not become >> irritated that it's not doing things that you want easily -- essentially >> questioning why you're using this framework in the first place. :) >> >> I'd recommend starting with a Mojolicious::Lite app. >> >> Start with the Hello World >> <https://mojolicious.org/perldoc/Mojolicious/Guides/Tutorial#Hello-World> >> in the Tutorial. And then expand it for your needs, perhaps like so: >> >> #!/usr/bin/env perluse Mojolicious::Lite; >> get '/:customer' => sub { >> my $c = shift; >> $c->render(inline => 'Hello, <%= param "customer" %>!');}; >> >> app->start; >> >> >> Also, just to show some other equivalent ways to do the same thing: >> >> #!/usr/bin/env perluse Mojolicious::Lite; >> get '/:customer' => sub { >> my $c = shift; my $customer = $c->param('customer'); >> $c->render(inline => 'Hello, <%= $customer %>!', customer => $customer);}; >> >> app->start; >> >> >> Also: >> >> #!/usr/bin/env perluse Mojolicious::Lite; >> get '/:customer' => sub { >> my $c = shift; $c->render(inline => 'Hello, <%= $c->param("customer") >> %>!');}; >> >> app->start; >> >> >> On Wed, Jan 2, 2019 at 3:39 PM <hwmbo...@gmail.com> wrote: >> >>> Thanks Stefan. >>> >>> >>> So, trying a different tack, I was able to parse the url of a request >>> with a 'before_depatch' hook, and figure out what Customer Class should be >>> used, before routing happens. >>> >>> Assuming the request url is /kwikemart/liquor/22, I figure out the >>> customer name (kwikemart) like this: >>> >>> >>> sub startup { >>> my $self = shift; >>> $self->req->url->path =~ m#^/(\w+)/.+#; >>> $customer = $1;} >>> >>> >>> The question is, where to store this $customer, so I can use it to >>> specify the correct route later? I still don't quite get how Mojo::Base >>> Class work. Not sure how to correctly create custom attribute, that's local >>> to each request, so it can be used within a $r->to() call. >>> >>> >>> >>> >>> >>> On Wednesday, January 2, 2019 at 4:34:20 AM UTC-6, hwmbo...@gmail.com >>> wrote: >>>> >>>> Hi. I want to route a request to a controller that's dynamically >>>> constructed, base on a place holder in the url. To illustrate, I want do >>>> something like the following: >>>> >>>> use Mojo::Base 'Mojolicious'; >>>> >>>> sub startup { >>>> >>>> my $r = $self->routes; >>>> >>>> my $route = $r->get('/:customer/boxs/:id'); >>>> >>>> >>>> [ somehow, extract the :customer holder into a variable $customer, then >>>> ] >>>> >>>> $route->( >>>> >>>> controller => "$customer::boxs', >>>> >>>> action => 'get_list', >>>> >>>> ); >>>> >>>> } >>>> >>>> >>>> I tried but can't seem to find way to this, and I'm not sure if this is >>>> possible? >>>> Some pointer is appreciated. Thanks. >>>> >>>> >>>> >>>> -- >>> You received this message because you are subscribed to the Google >>> Groups "Mojolicious" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to mojolicious...@googlegroups.com. >>> To post to this group, send email to mojol...@googlegroups.com. >>> Visit this group at https://groups.google.com/group/mojolicious. >>> For more options, visit https://groups.google.com/d/optout. >>> >> -- > You received this message because you are subscribed to the Google Groups > "Mojolicious" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to mojolicious+unsubscr...@googlegroups.com. > To post to this group, send email to mojolicious@googlegroups.com. > Visit this group at https://groups.google.com/group/mojolicious. > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "Mojolicious" group. To unsubscribe from this group and stop receiving emails from it, send an email to mojolicious+unsubscr...@googlegroups.com. To post to this group, send email to mojolicious@googlegroups.com. Visit this group at https://groups.google.com/group/mojolicious. For more options, visit https://groups.google.com/d/optout.