[Catalyst] Multiple chain sources?

David Schmidt davewood at gmx.at
Mon Nov 22 08:29:09 GMT 2010


On Mon, Nov 22, 2010 at 9:24 AM, David Schmidt <davewood at gmx.at> wrote:
> On Mon, Nov 22, 2010 at 6:15 AM, Matthew Braid <catalyst at mdb.id.au> wrote:
>> Hi all,
>>
>> Just wondering - is it possible for an action to have multiple chain paths?
>>
>> I'd like my site to have a path like /user/N/profile (/user/N being a
>> chain path, /profile being an end node off that path), but also have a
>> path like /my/profile (where /my is a chain path that acts as if the
>> user put their own ID on the end of /user/N).
>>
>> Currently I have /user/N as a chain path, /my as a chain path, and
>> then a profile action (path: /profile) that chains off of /user/N and
>> a this_profile action (path: /profile) that chains off of /my that
>> simply calls the profile action like so:
>>
>> # in the User controller
>>
>> sub user :Chained('/') :PathPart('user') :CaptureArgs(0) {
>>  # This is only here so a (not shown) chain makes '/user' a valid path
>> }
>>
>> sub specific_user :Chained('user') :PathPart('') :CaptureArgs(1) {
>>  # Captured arg goes in $c->stash->{userid}
>> }
>>
>> sub this_user :Chained('/') :PathPart('my') :CaptureArgs(0) {
>>  # The current user's ID goes in $c->stash->{userid}
>> }
>>
>> sub profile :Chained('specific_user') :PathPath('profile') :Args(0) {
>>  # Do stuff using $c->stash->{userid}
>> }
>>
>> sub this_profile :Chained('this_user') :PathPart('profile') :Args(0) {
>>  # Dummy - redirect to the main 'profile' action
>>  shift->profile(@_);
>> }
>>
>> This works, but is it the best way to do it?
>>
>> TIA,
>> MDB
>>
>> _______________________________________________
>> List: Catalyst at lists.scsys.co.uk
>> Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
>> Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
>> Dev site: http://dev.catalyst.perl.org/
>>
>
> Usually my setup looks like this
>
> # put resultset into stash
> sub base : Chained('/') PathPart('users') CaptureArgs(0) {
>    $c->stash(users_rs => $c->model('DB::Users');
> }
>
> # find user in resultset, check for existance
> sub base_with_id : Chained('base') PathPart('') CaptureArgs(1) {
>    my ($self, $c, $id ) = @_;
>    my $user = $c->stash->{users}->find($id);
>    if ($user) {
>        $c->stash(user => $user);
>    } else {
>        $c->stash(error_msg => 'not_found');
>        $c->detach('/error404');
>    }
> }
>
> sub index : Chained('base') ...
> sub show : Chained('base_with_id') ...
> sub create : Chained('base') ...
> sub edit : Chained('base_with_id') ...
> sub delete : Chained('base_with_id') ...
> sub profile : Chained('base_with_id') ...
>
> If I want a /my/profile now I'd just add another sub
>
> # put user_id in stash, then make full chain dispatch
> sub my_profile : Path('/my/profile') Args(0) Does('NeedsLogin') {
>    my ($self, $c) = @_;
>    $c->go($self->action_for('profile'), [ $c->user->id ]);
> }
>
> OR
>
> # put user obj in stash, then visit just "profile"
> sub my_profile : Path('/my/profile') Args(0) Does('NeedsLogin') {
>    my ($self, $c) = @_;
>    $c->stash(user => $c->user->obj;
>    $c->detach($self->action_for('profile'));
> }
>

ERRATA:

in sub base_with_id
my $user = $c->stash->{users_rs}->find($id);



More information about the Catalyst mailing list