[Catalyst] Catalyst actions

John Napiorkowski jjn1056 at yahoo.com
Thu May 17 17:25:11 GMT 2007


--- Richard Jones <ra.jones at dpw.clara.co.uk> wrote:

> Help - I'm going round in circles with Catalyst
> actions. I want
> http://localhost:3000/search to map to the method
> search() in
> MyApp::Controller::Search, so I defined the method
> as:
> 
> sub search : Path Form('/search') { # a formbuilder
> method
>   if ( $form->submitted && $form->validate ) {
>     $c->detach('retrieve');
>   }
>   # etc;
> }
> 
> sub retrieve : Private {
>   # performs db lookup, results in $rs, then:
> 
>   if (! $rs->pager->total_entries ||
> $rs->pager->total_entries > 1000) {
>     $c->stash->{error_msg} = sprintf 'Total records
> matched = %s, please
> refine search', $rs->pager->total_entries;
>     $c->detach('search'); # re-load search form with
> message
>   }
>   else {
>     # display results in template
>   }
> }
> 
> Now, if the $rs->pager->total_entries value triggers
> $c->detach('search'), then the following error is
> generated:
> 
> Couldn't render template "file error -
> search/search: not found"
> 
> I also sometime see [% Catalyst.uri_for('search') %]
> translating to
> 'base_url/search/search' in the template, and though
> ugly, it does work.
> 
> It's probably got something to do with the
> definition of search() as an
> empty Path, but that's the only way I could get the
> the address to read
> http://localhost:3000/search as opposed to something
> ugly like
> http://localhost:3000/search/search, as it does if I
> define search() as
> a Local action, ie 'sub search : Local'.
> 
> I've also tried playing with calling the default
> method 'index' and
> 'default', and various attributes Local, Path,
> Global (I know that one's
> wrong) but ran into problems with all of those. I
> can't do a
> $c->res->redirect to the url '/search' as I need the
> original search
> params reloading. Can anyone see an obvious solution
> to this? Probably
> to do it the correct way!
> 
> -- 
> Richard Jones

Hi,

your search action is being mapped to the
/search/search namespace because when you use the Path
attribute without a value it defaults to whatever the
sub name is, in this case what you are doing is like
Path('search').  This gets scoped under the
controllers namespace (in this case the action
namespace for your controller is /search, so the
search method that you define get's put as
/search/search.)

The error you are getting is because by default TT
View looks for a template at a path based on the
action's namespace, so you want a file called search
under root/search path.

If you want your search method to be at url /search
try defining it with a Path('') attribute (explicitly
setting to empty).  Or put this stuff in your Root.pm
controller, which defines it's action namespace to
'/'.

BTW, you can spot all the private and public
namespaces for you application when it starts up.  It
gives a long debug info screen which is very helpful.

I know when you first start this can be difficult and
confusing.  I think it's a bit harder now because as
time has gone on Catalyst has added more and more ways
to map actions, mostly because as we've all used
Catalyst we've come up with more needs.  So some ways
of mapping are somewhat deprecated.  I tend to use
action chains mostly now, and sometimes Path.  Default
I tend to use in the root controller to capture an
ultimate not found response.

If this is too confusing then you can just put
everything into the Root.pm controller. Then it's like
building a CGI::Application webapp, which might be
easier to get.  The main advantage to breaking out
into multiply controllers is in easy of understanding
and when you make base controllers for different kinds
of activities.

--john

__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 



More information about the Catalyst mailing list