Mojolicious route creation
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.
UPDATE
I am 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->hook( before_dispatch => sub {
my $c= shift;
$c->req->url->path =~ m#^/(w+)/.+#;
$customer = $1;
}
$r = $self->routes;
$r->get('....')->to(....);
...
...
}
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.
perl mojolicious
add a comment |
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.
UPDATE
I am 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->hook( before_dispatch => sub {
my $c= shift;
$c->req->url->path =~ m#^/(w+)/.+#;
$customer = $1;
}
$r = $self->routes;
$r->get('....')->to(....);
...
...
}
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.
perl mojolicious
I don't know if Mojolicious offers an elegant/convenient way to do this. However, you can always use a dispatch table:my %dispatch = (customer1 => &customer1); $r->get('/:customer' => sub { my $self = shift; $dispatch{$self->stash('customer')}->($self) })
(adapt to your needs...). I'll let someone with a better knowledge of Mojolicious post an answer though.
– Dada
Jan 2 at 10:54
1
I assume that you have a limited amount of values for$customer
. Then you should just do:my @customers = get_customers(); for my $customer (@customers) { $r->get("/$customer/boxs/:id")->to(controller => "$customer::boxs", ... ) }
. Otherwise, have one route to dispatch them:$r->get('/:customer/boxs/:id')->to(cb => sub { my($c) = @_; ... handle $c->param('customer')})
. If$customer
is not a class name but a customer id, don't create a class for each customer.
– Corion
Jan 2 at 11:39
Thanks. You're right, there's not many customer, but I intend to design it with flexibility in mind, and Customer does need to be a class. The idea is, each customer has its own variant of box content handler, so by calling on an different url, the relevant Customer class will be correctly invoked. Anyways, I figured out to parse the url of a request with a 'before_depatch' hook, but the question is, where to store this? I still don't quite get how Mojo::Base Class work, so not sure how to correctly create custom attribute (without race condition)
– Terry Yang
Jan 2 at 20:55
Anything that you want to store specific to that request tends to go in the stash:$c->stash(customer => $customer); ... my $customer = $c->stash('customer');
Just keep in mind the namespace is shared by both your route placeholders and reserved keys.
– Grinnz
Jan 10 at 23:37
Note your hook will run at request time, whereas your routes are set up at app startup, so you can't use anything from the hook in your route setup (but you can use the stash in the resulting actions).
– Grinnz
Jan 10 at 23:39
add a comment |
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.
UPDATE
I am 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->hook( before_dispatch => sub {
my $c= shift;
$c->req->url->path =~ m#^/(w+)/.+#;
$customer = $1;
}
$r = $self->routes;
$r->get('....')->to(....);
...
...
}
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.
perl mojolicious
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.
UPDATE
I am 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->hook( before_dispatch => sub {
my $c= shift;
$c->req->url->path =~ m#^/(w+)/.+#;
$customer = $1;
}
$r = $self->routes;
$r->get('....')->to(....);
...
...
}
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.
perl mojolicious
perl mojolicious
edited Jan 2 at 21:25
Terry Yang
asked Jan 2 at 10:43
Terry YangTerry Yang
11
11
I don't know if Mojolicious offers an elegant/convenient way to do this. However, you can always use a dispatch table:my %dispatch = (customer1 => &customer1); $r->get('/:customer' => sub { my $self = shift; $dispatch{$self->stash('customer')}->($self) })
(adapt to your needs...). I'll let someone with a better knowledge of Mojolicious post an answer though.
– Dada
Jan 2 at 10:54
1
I assume that you have a limited amount of values for$customer
. Then you should just do:my @customers = get_customers(); for my $customer (@customers) { $r->get("/$customer/boxs/:id")->to(controller => "$customer::boxs", ... ) }
. Otherwise, have one route to dispatch them:$r->get('/:customer/boxs/:id')->to(cb => sub { my($c) = @_; ... handle $c->param('customer')})
. If$customer
is not a class name but a customer id, don't create a class for each customer.
– Corion
Jan 2 at 11:39
Thanks. You're right, there's not many customer, but I intend to design it with flexibility in mind, and Customer does need to be a class. The idea is, each customer has its own variant of box content handler, so by calling on an different url, the relevant Customer class will be correctly invoked. Anyways, I figured out to parse the url of a request with a 'before_depatch' hook, but the question is, where to store this? I still don't quite get how Mojo::Base Class work, so not sure how to correctly create custom attribute (without race condition)
– Terry Yang
Jan 2 at 20:55
Anything that you want to store specific to that request tends to go in the stash:$c->stash(customer => $customer); ... my $customer = $c->stash('customer');
Just keep in mind the namespace is shared by both your route placeholders and reserved keys.
– Grinnz
Jan 10 at 23:37
Note your hook will run at request time, whereas your routes are set up at app startup, so you can't use anything from the hook in your route setup (but you can use the stash in the resulting actions).
– Grinnz
Jan 10 at 23:39
add a comment |
I don't know if Mojolicious offers an elegant/convenient way to do this. However, you can always use a dispatch table:my %dispatch = (customer1 => &customer1); $r->get('/:customer' => sub { my $self = shift; $dispatch{$self->stash('customer')}->($self) })
(adapt to your needs...). I'll let someone with a better knowledge of Mojolicious post an answer though.
– Dada
Jan 2 at 10:54
1
I assume that you have a limited amount of values for$customer
. Then you should just do:my @customers = get_customers(); for my $customer (@customers) { $r->get("/$customer/boxs/:id")->to(controller => "$customer::boxs", ... ) }
. Otherwise, have one route to dispatch them:$r->get('/:customer/boxs/:id')->to(cb => sub { my($c) = @_; ... handle $c->param('customer')})
. If$customer
is not a class name but a customer id, don't create a class for each customer.
– Corion
Jan 2 at 11:39
Thanks. You're right, there's not many customer, but I intend to design it with flexibility in mind, and Customer does need to be a class. The idea is, each customer has its own variant of box content handler, so by calling on an different url, the relevant Customer class will be correctly invoked. Anyways, I figured out to parse the url of a request with a 'before_depatch' hook, but the question is, where to store this? I still don't quite get how Mojo::Base Class work, so not sure how to correctly create custom attribute (without race condition)
– Terry Yang
Jan 2 at 20:55
Anything that you want to store specific to that request tends to go in the stash:$c->stash(customer => $customer); ... my $customer = $c->stash('customer');
Just keep in mind the namespace is shared by both your route placeholders and reserved keys.
– Grinnz
Jan 10 at 23:37
Note your hook will run at request time, whereas your routes are set up at app startup, so you can't use anything from the hook in your route setup (but you can use the stash in the resulting actions).
– Grinnz
Jan 10 at 23:39
I don't know if Mojolicious offers an elegant/convenient way to do this. However, you can always use a dispatch table:
my %dispatch = (customer1 => &customer1); $r->get('/:customer' => sub { my $self = shift; $dispatch{$self->stash('customer')}->($self) })
(adapt to your needs...). I'll let someone with a better knowledge of Mojolicious post an answer though.– Dada
Jan 2 at 10:54
I don't know if Mojolicious offers an elegant/convenient way to do this. However, you can always use a dispatch table:
my %dispatch = (customer1 => &customer1); $r->get('/:customer' => sub { my $self = shift; $dispatch{$self->stash('customer')}->($self) })
(adapt to your needs...). I'll let someone with a better knowledge of Mojolicious post an answer though.– Dada
Jan 2 at 10:54
1
1
I assume that you have a limited amount of values for
$customer
. Then you should just do: my @customers = get_customers(); for my $customer (@customers) { $r->get("/$customer/boxs/:id")->to(controller => "$customer::boxs", ... ) }
. Otherwise, have one route to dispatch them: $r->get('/:customer/boxs/:id')->to(cb => sub { my($c) = @_; ... handle $c->param('customer')})
. If $customer
is not a class name but a customer id, don't create a class for each customer.– Corion
Jan 2 at 11:39
I assume that you have a limited amount of values for
$customer
. Then you should just do: my @customers = get_customers(); for my $customer (@customers) { $r->get("/$customer/boxs/:id")->to(controller => "$customer::boxs", ... ) }
. Otherwise, have one route to dispatch them: $r->get('/:customer/boxs/:id')->to(cb => sub { my($c) = @_; ... handle $c->param('customer')})
. If $customer
is not a class name but a customer id, don't create a class for each customer.– Corion
Jan 2 at 11:39
Thanks. You're right, there's not many customer, but I intend to design it with flexibility in mind, and Customer does need to be a class. The idea is, each customer has its own variant of box content handler, so by calling on an different url, the relevant Customer class will be correctly invoked. Anyways, I figured out to parse the url of a request with a 'before_depatch' hook, but the question is, where to store this? I still don't quite get how Mojo::Base Class work, so not sure how to correctly create custom attribute (without race condition)
– Terry Yang
Jan 2 at 20:55
Thanks. You're right, there's not many customer, but I intend to design it with flexibility in mind, and Customer does need to be a class. The idea is, each customer has its own variant of box content handler, so by calling on an different url, the relevant Customer class will be correctly invoked. Anyways, I figured out to parse the url of a request with a 'before_depatch' hook, but the question is, where to store this? I still don't quite get how Mojo::Base Class work, so not sure how to correctly create custom attribute (without race condition)
– Terry Yang
Jan 2 at 20:55
Anything that you want to store specific to that request tends to go in the stash:
$c->stash(customer => $customer); ... my $customer = $c->stash('customer');
Just keep in mind the namespace is shared by both your route placeholders and reserved keys.– Grinnz
Jan 10 at 23:37
Anything that you want to store specific to that request tends to go in the stash:
$c->stash(customer => $customer); ... my $customer = $c->stash('customer');
Just keep in mind the namespace is shared by both your route placeholders and reserved keys.– Grinnz
Jan 10 at 23:37
Note your hook will run at request time, whereas your routes are set up at app startup, so you can't use anything from the hook in your route setup (but you can use the stash in the resulting actions).
– Grinnz
Jan 10 at 23:39
Note your hook will run at request time, whereas your routes are set up at app startup, so you can't use anything from the hook in your route setup (but you can use the stash in the resulting actions).
– Grinnz
Jan 10 at 23:39
add a comment |
0
active
oldest
votes
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54004894%2fmojolicious-route-creation%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
0
active
oldest
votes
0
active
oldest
votes
active
oldest
votes
active
oldest
votes
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54004894%2fmojolicious-route-creation%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
I don't know if Mojolicious offers an elegant/convenient way to do this. However, you can always use a dispatch table:
my %dispatch = (customer1 => &customer1); $r->get('/:customer' => sub { my $self = shift; $dispatch{$self->stash('customer')}->($self) })
(adapt to your needs...). I'll let someone with a better knowledge of Mojolicious post an answer though.– Dada
Jan 2 at 10:54
1
I assume that you have a limited amount of values for
$customer
. Then you should just do:my @customers = get_customers(); for my $customer (@customers) { $r->get("/$customer/boxs/:id")->to(controller => "$customer::boxs", ... ) }
. Otherwise, have one route to dispatch them:$r->get('/:customer/boxs/:id')->to(cb => sub { my($c) = @_; ... handle $c->param('customer')})
. If$customer
is not a class name but a customer id, don't create a class for each customer.– Corion
Jan 2 at 11:39
Thanks. You're right, there's not many customer, but I intend to design it with flexibility in mind, and Customer does need to be a class. The idea is, each customer has its own variant of box content handler, so by calling on an different url, the relevant Customer class will be correctly invoked. Anyways, I figured out to parse the url of a request with a 'before_depatch' hook, but the question is, where to store this? I still don't quite get how Mojo::Base Class work, so not sure how to correctly create custom attribute (without race condition)
– Terry Yang
Jan 2 at 20:55
Anything that you want to store specific to that request tends to go in the stash:
$c->stash(customer => $customer); ... my $customer = $c->stash('customer');
Just keep in mind the namespace is shared by both your route placeholders and reserved keys.– Grinnz
Jan 10 at 23:37
Note your hook will run at request time, whereas your routes are set up at app startup, so you can't use anything from the hook in your route setup (but you can use the stash in the resulting actions).
– Grinnz
Jan 10 at 23:39