Login | Register For Free | Help
Search for: (Advanced)

Mailing List Archive: Catalyst: Users

url parsing and sub controller

 

 

Catalyst users RSS feed   Index | Next | Previous | View Threaded


bernard.fritatgmail.com

Sep 5, 2005, 5:57 PM

Post #1 of 7 (221 views)
Permalink
url parsing and sub controller

Probably a dumb question ...

I have a controller
MyApp::C::Categ

with

sub default : Private {
my ( $self, $c ) = @_;
$c->res->redirect('/default_action');
}

sub begin : Private {
my ( $self, $c , $categ) = @_;
if ($categ) {
$c->stash->{title} = "Category = $categ";
return 1;
}
}

when typing "domaine.tld /categ/MyCategory" I was expecting having
$categ = MyCategory but I only have $categ=categ so I needed
my ( $self, $c , $dummy, $categ) = @_;
to get the correct value. Is it correct behavior ?

More, I can't figure out why after executing begin, Catalyst execute
default and redirect to "/default_action" ?

--
Bernard FRIT still unbrainedly trying to understand...


Danijel.Milicevicatrawmode.org

Sep 5, 2005, 6:56 PM

Post #2 of 7 (221 views)
Permalink
url parsing and sub controller [In reply to]

Hi Bernard,

Am Montag, den 05.09.2005, 18:00 +0200 schrieb Bernard FRIT:
> Probably a dumb question ...

Wise of the day: there are no dump questions, just dumb answers by gabb ;)

> sub begin : Private {
> my ( $self, $c , $categ) = @_;
> if ($categ) {
> $c->stash->{title} = "Category = $categ";
> return 1;
> }
> }
>
> when typing "domaine.tld /categ/MyCategory" I was expecting having
> $categ = MyCategory but I only have $categ=categ so I needed
> my ( $self, $c , $dummy, $categ) = @_;
> to get the correct value. Is it correct behavior ?
>
> More, I can't figure out why after executing begin, Catalyst execute
> default and redirect to "/default_action" ?

You might wanna check the docs for the "begin" action and its function.
Don't use it for this kinda thing, you a dedicated *public* action to
handle arguments.

What probably happened was:
1) You ask for domain.tld/categ/MyCategory
2) There is neither a *public* action named categ, nor a local action
named MyCategory in the controller Categ, so what happens next is:
3) of course your default action will be called and so on

Just write a sub categ : Global {}, put the code in it and it will work.

Regards,
Danijel "gabb" Milicevic


omegaatpalle.net

Sep 5, 2005, 10:19 PM

Post #3 of 7 (224 views)
Permalink
url parsing and sub controller [In reply to]

On 5. sep. 2005, at 18.00, Bernard FRIT wrote:

> Probably a dumb question ...
>
> I have a controller
> MyApp::C::Categ
>
> with
>
> sub default : Private {
> my ( $self, $c ) = @_;
> $c->res->redirect('/default_action');
> }
>
> sub begin : Private {
> my ( $self, $c , $categ) = @_;
> if ($categ) {
> $c->stash->{title} = "Category = $categ";
> return 1;
> }
> }
>
> when typing "domaine.tld /categ/MyCategory" I was expecting having
> $categ = MyCategory but I only have $categ=categ so I needed
> my ( $self, $c , $dummy, $categ) = @_;
> to get the correct value. Is it correct behavior ?
>


Yes, as the default : Private actions are inheritable, and as such
you need to make sure you use
the correct one. Think this has been debated before, atleast on IRC,
but cannot remember what the outcome was.

basicly the third argument to default is an array with every path-
element. So if you always want the last one, do my ($self, $c,
@args); and pick out the last one. If you want a specific one, use
that etc.

> More, I can't figure out why after executing begin, Catalyst execute
> default and redirect to "/default_action" ?
>


A log from the request would be mighty helpfull here, along with the
table showing registered actions etc from the startup,

> --
> Bernard FRIT still unbrainedly trying to understand...
>
> _______________________________________________
> Catalyst mailing list
> Catalyst [at] lists
> http://lists.rawmode.org/mailman/listinfo/catalyst
>


asratufl.edu

Sep 5, 2005, 11:50 PM

Post #4 of 7 (223 views)
Permalink
url parsing and sub controller [In reply to]



> You might wanna check the docs for the "begin" action and its function.
> Don't use it for this kinda thing, you a dedicated *public* action to handle
> arguments.

Would it be appropriate to do this in an auto() ?

I'm thinking it'd be nice to shove as much of this kind of housekeeping work up
to the application as possible.

Alternately one could

package MyApp;

sub Process_Args: Global { ... }



and then explicitly

package MyApp::C::Page

sub default: private
{
my ( $self, $c ) = @_;
$c->Process_Args($c);
[...]
}


or some similar pattern.

I'm currently working with the latter. My itch of the instant is that I wish
I could tell Process_Args that it gets run All The Time at the MyApp level.

Of course, it's entirely possible that there's a defined and documented method
to do this, so a whack with a cluestick won't offend.


- Allen S. Rout


Danijel.Milicevicatrawmode.org

Sep 6, 2005, 7:44 AM

Post #5 of 7 (220 views)
Permalink
url parsing and sub controller [In reply to]

Hi Allen,

First off: sorry for my weird first reply - I could barely understand it
myself after reading it this morning. I blame the tequila and will
supply .diff's in the future if this happens again. ;)

Am Montag, den 05.09.2005, 17:54 -0400 schrieb Allen S. Rout:
> Would it be appropriate to do this in an auto() ?
>
> I'm thinking it'd be nice to shove as much of this kind of housekeeping work up
> to the application as possible.
>
> Alternately one could
>
> package MyApp;
>
> sub Process_Args: Global { ... }

Best practice tells me that you should keep MyApp.pm as simple as
possible - no public (Local/Global/Path/Regex) actions in MyApp.pm.
There are a couple of reasons for this beside the obvious ones
(controller logic belongs to controllers, MVC), but the most important
one to me is, that it's not reusable. We got controller inheritance so
keeping a good MVC-like seperation also gives you the benefit of (more
or less) independent and reuseable controller-code.

>
> and then explicitly
>
> package MyApp::C::Page
>
> sub default: private
> {
> my ( $self, $c ) = @_;
> $c->Process_Args($c);
> [...]
> }
>
>
> or some similar pattern.
>
> I'm currently working with the latter. My itch of the instant is that I wish
> I could tell Process_Args that it gets run All The Time at the MyApp level.

"tell Process_Args that it gets run All The Time at the MyApp level",
I'm not too sure what you mean by "MyApp level", but that sounds pretty
much like auto() to me from a control flow POV. So the code would look
like:

package MyApp;

sub default : Private {
my ( $self, $c, $arg ) = @_;
$c->forward('page/foo', [qw/$arg/]);
}

sub auto : Private { ... } # processing you want on *every* request

---

package MyApp::C::Page;

sub default : Private { ... }

sub foo : Local {
my ( $self, $c ) = @_;
my $arg = $c->req->args->[0];
...
}

> Of course, it's entirely possible that there's a defined and documented method
> to do this, so a whack with a cluestick won't offend.

Since I'm not sure if I even answered your question, there won't be any
whacking with a stick, just some pointers to a direction:

- Intro.pod#FlowControl
- Cookbook.pod#Forwarding with args

Greets,
Danijel "gabb" Milicevic


moseleyathank.org

Sep 6, 2005, 3:13 PM

Post #6 of 7 (220 views)
Permalink
url parsing and sub controller [In reply to]

On Mon, Sep 05, 2005 at 10:22:27PM +0200, Andreas Marienborg wrote:
> Yes, as the default : Private actions are inheritable, and as such
> you need to make sure you use
> the correct one. Think this has been debated before, atleast on IRC,
> but cannot remember what the outcome was.

I've done some of that debating on #catalyst about default. The
outcome was basically that I wanted to use "default" for something
that it wasn't really designed for. My desire was to have "default"
act like a default local action for whatever controller the default
resides in.


> basicly the third argument to default is an array with every path-
> element. So if you always want the last one, do my ($self, $c,
> @args); and pick out the last one. If you want a specific one, use
> that etc.

And that was my problem with default. Unlike Local actions where the
code doesn't have to be aware of where it is in the controller name
space, default does have to know to be able to shift off the path
segments to get to the real arguments relative to the current
controller.

I'm still not clear why all the path arguments are passed to default --
that is, if it's a design feature or just the way default had to
work.


This was the discussion in July:

I needed to duplicate an existing URL mapping scheme from another
application.

I wanted a controller called MyApp::C::Path::To::Tables that did all
things related to "Tables", and I wanted to use local-style actions so
that later moving the controller to a new name space would not mean
rewriting the actions within the controller - i.e. actions were all
relative to the controller.

/path/to/tables - list all tables
/path/to/tables/users - list all in users table
/path/to/tables/users/21 - edit user 21
/path/to/tables/users/21/update - and update user 21

I didn't know the table names ahead of time so I didn't have actions
for each table. And that left "default" as a way to handle this.

If default worked like local (in how it returns @args) I could
handle the above like:

sub default : Local {
my ( $self, $c, $table_name, $id, $action ) = @_
}

I "solved" this by using this ugliness in each controller's auto
action to shift off the path segments pointing to the controller
leaving just the arguments:

$c->shift_args( __PACKAGE__ );


One problem with trying to use default as a default action in a
given controller is that another controller can take the action away.

Assuming no "users" action in MyApp::C::Path::To::Tables controller (i.e.
using default as above):

/path/to/tables/users/21

gets handled by the default action in Tables.pm. But if some day
MyApp::C::Path::To.pm defines a "tables" local action then the default
action will no longer work.

Of course, the same thing happens using Catalyst the "right" way:

/path/to/tables/list/users/21

calls the list action with @args = users, 21. The controller
App::C::Path::To::Tables::List with a "users" action will override
that.



--
Bill Moseley
moseley [at] hank


asratufl.edu

Sep 7, 2005, 4:19 AM

Post #7 of 7 (219 views)
Permalink
url parsing and sub controller [In reply to]



> First off: sorry for my weird first reply - I could barely understand it
> myself after reading it this morning. I blame the tequila and will
> supply .diff's in the future if this happens again. ;)

Tequila good. ;)

> Best practice tells me that you should keep MyApp.pm as simple as possible -
> no public (Local/Global/Path/Regex) actions in MyApp.pm. There are a couple
> of reasons for this beside the obvious ones (controller logic belongs to
> controllers, MVC), but the most important one to me is, that it's not
> reusable. We got controller inheritance so keeping a good MVC-like
> seperation also gives you the benefit of (more or less) independent and
> reuseable controller-code.

OK, understood. And I re-read the pod references you noted before completing
this sentence.

Here's what I -think- I want for this application, though I'd be happy to be
educated otherwise.

I've got a cluster of sub-apps, each of which is implemented in its' own
controller. The entire cluster works on grossly the same dozen data types. A
few of them use all the types, most use a varying 3-5 of them.

So I figured I should do all the argument handling once, at the MyApp level;
this would decrease the instances of duplicated code between the various
controllers.

And as I type this, I realize I had a brain-o [like a typo, but it's just
saying something stupid. ;) ] the process_args I had in mind, and coded, was
private not global. Does this make the idea sound less stupid?





- Allen S. Rout

Catalyst users RSS feed   Index | Next | Previous | View Threaded
 
 


Interested in having your list archived? Contact Gossamer Threads
 
  Web Applications & Managed Hosting Powered by Gossamer Threads Inc.