Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

Catalyst: Using Chained for URL Dispatching and Sane Method Organization

by stonecolddevin (Parson)
on Oct 17, 2009 at 22:27 UTC ( [id://801812]=perlmeditation: print w/replies, xml ) Need Help??

I wrote this for http://catalyzed.org. Please review and let me know if it stands worthy of posting in tutorials.

You've read the tutorial but you still can't seem to get a grasp on what exactly to use Chained dispatching for.

Chained is just another method of method/url dispatching that Catalyst allows you to use. Chained, however, allows you to chain together methods that need to share information across requests....

Say you want to construct a url that looks something like this: http://www.yourhost.com/item/1/view. Normally, you'd have to go through a bunch of parsing involving $ENV{'PATH_PART'} $ENV{'PATH_INFO}, which is ugly, and hackish. You can do it like this with Chained:

# step one: # set up a base method to make sure your item exists, and # store your item information in $c->stash sub base : Chained('/') PathPart('item') CaptureArgs(1) { my ($self, $c, $itemid) = @_; my $item = $c->model('Item')->find($itemid); if ( $item == undef ) { $c->stash( error_msg => "This item does not exist" ); $c->detach("nonexistent"); } else { $c->stash( item => $item ); } }

Let's break this method down, and then we'll get to the rest of this chain.

sub base : Chained('/') PathPart('item') CaptureArgs(1)

the Chained('/') attribute sets up the base of the chain.

PathPart determines the name of the path to capture.

CaptureArgs tells Chained to capture one argument directly after the path part.

Now, let's finish the chain so we can have a working URL.

## the next part is to link the end point to the chain ## thisis done by passing the name of the base chain method to Chaine +d for this method sub view : Chained('base') PathPart('view') Args(0) { my ($self, $c) = @_; my $item = $c->stash->{item}; $c->stash( template => 'item/view.tt2', item => $item, ); }

This method is fairly self explanatory, but just to make sure, we'll go ahead and go over it.

As in the comments, Chained is passed the name of the base point of the chain, which in this case is 'base'. We determine the path part with PathPart once again, which can be noted that it doesn't have to match the current method's name. The one different attribute is the Args(0) attribute. Args tells Chained that the end of the chain has been reached, thus giving you a usable URL at this point. You can specify arguments to be passed in Args(), and they can be accessed via the @_ variable, like $self and $c.

To recap, this gives us a url like http://www.yourdomain.com/item/itemid/view. You can expand this for CRUD actions so you can have URLs like the above, as well as something like /item/create. Here is some example code:

sub blog : Chained('/') PathPart('blog') CaptureArgs(0) { } sub load_blog : Chained('blog') PathPart('') CaptureArgs(1) { my ($self, $c, $id) = @_; my $entry = $c->model('DB::Blog')->find($id); if ( $entry ) { $c->stash(entry => $entry ); } else { $c->stash( error_msg => "No such blog" ); $c->detach; } } sub view : Chained('load_blog') PathPart('view') Args(0) { my ($self, $c) = @_; } sub create : Chained('blog') PathPart('new') Args(0) FormConfig('blog +s/create.yml') { my ($self, $c) = @_; my $form = $c->stash->{form}; if ( $form->submitted_and_valid ) { my $entry = $c->model('DB::Blogs')->new_result({ created => D +ateTime->now }); $form->model->update($entry); $c->stash( status_msg => "Post saved", entry => $entry ); } else { $c->stash( error_msg => "Your form had errors" ); $c->detach; } }

This actually creates a couple different Chained instances, giving us the ability to have urls like /blog/id/view, blog/new, etc.

Next time, using $c->urlforaction to create URIs for Chained methods.

mtfnpy

Replies are listed 'Best First'.
Re: Catalyst: Using Chained for URL Dispatching and Sane Method Organization
by dreadpiratepeter (Priest) on Oct 18, 2009 at 22:05 UTC

    Chained attributes are like crack. Once you grok them and start using them you can't stop. They simplify code so much.

    I think you should stress what you have accomplished with your chained handlers more. Make it clear that the nbenefit is access to the entry object in all methods chained from blog without having to do the work. You imply it, but don't come out and say it. In other words you have a great magic trick but are missing the Ta-Da!



    -pete
    "Worry is like a rocking chair. It gives you something to do, but it doesn't get you anywhere."
      Chained attributes are like crack. Once you grok them and start using them you can't stop. They simplify code so much.
      I understand what chained attributes do. And Catalyst was a lot of fun to work with when it first came out. I would like to offer my viewpoint on solving the same problem. Personally, if you read what dhoss says chained attributes are for:
      Chained, however, allows you to chain together methods that need to share information across requests....
      Basically, in OO terms, what he is saying is that he has a sequence of methods that belong in the same class because they consume the same data. And if you look at the implementation:
      sub base : Chained('/') PathPart('item') CaptureArgs(1) {
      The use of the word 'base' is a dead giveaway.

      So, what I see here is the use subroutine overloading to give Catalyst hints about how to handle common object-oriented programming problems for you.

      I came up with a similar strawman example here.

      The big difference is that I used clean, standard class-based OO to create a base class and then allowed the derived class to share/refine behavior as needed.

      I personally dont like learning things like Catalyst and Template Toolkit. In my eyes, they are attempts to take what any OO Perl programmer can do himself and come up with syntactic trickery and shortcuts to make it easier for those who lack said sophistication.

      Just give me Moose, CGI::Prototype and HTML::Seamstress and the tried and true methods of OO programming which work in and out of Perl anyday over language-specific syntax games like this.

      But of course, we all have our preferences and I'm sure many people are getting great mileage out of Catalyst and Template, so more power to them!

      Thanks for the chance to offer a contrasting viewpoint.

        metaperl thanks for the review! It's nice to have non-Catalysters critique my work as well, even better if they *don't* like Catalyst so I can get a rather rigid review :-)

        Also, ++ to you for Moose-ing!

        mtfnpy

Re: Catalyst: Using Chained for URL Dispatching and Sane Method Organization
by stonecolddevin (Parson) on Oct 25, 2009 at 19:53 UTC

    If no one else has any other input I'm going to post this to tutorials. Thanks all!

    mtfnpy

Re: Catalyst: Using Chained for URL Dispatching and Sane Method Organization
by Anonymous Monk on Oct 17, 2009 at 23:23 UTC
    Normally, you'd have to go through a bunch of parsing involving $ENV{'PATH_PART'}, which is ugly, and hackish.

    I'm fairly certain that is a straw man argument.

      Please, do explain.

      mtfnpy

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://801812]
Approved by ww
Front-paged by planetscape
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others taking refuge in the Monastery: (3)
As of 2024-04-20 03:34 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found