FAQ
Hi,

I'd like to add various web pages to my Catalyst app without the need to modify controllers and restarting the server.
Instead, I just want to add a Template::Toolkit .tt2 file on the file system and it get picked up automatically.

I'm not sure of an elegant/recommended way to produce an action to handle this sort of functionality, presumably some sort of logic in Root default action, that automatically detects template and displays it otherwise produces error and redirects to my 404 handle.

Any tips would appreciated!

Thanks,

Anthony

Search Discussions

  • Denny at Oct 11, 2010 at 2:21 pm

    On Mon, 2010-10-11 at 15:02 +0100, Anthony Gladdish wrote:
    I'd like to add various web pages to my Catalyst app without the need
    to modify controllers and restarting the server.
    Instead, I just want to add a Template::Toolkit .tt2 file on the file
    system and it get picked up automatically.
    Something like this may help...
    (in a theoretical MyApp/Controller/Thing.pm)

    sub view : Chained( '/' ) : PathPart( 'view' ) : Args( 1 ) {
    my ( $self, $c, $template ) = @_;

    # [ stuff to set template variables in stash goes here ]

    $c->stash->{ template } = 'template-directory/'.$template.'.tt';
    }

    ...so http://your.app/thing/view/foo will load the foo.tt template from
    in template-directory.

    That said, would you mind telling us a bit more about what you're
    actually trying to achieve in your application? There may be a better
    or more standard way of doing it.

    Regards,
    Denny

    -------------- next part --------------
    A non-text attachment was scrubbed...
    Name: not available
    Type: application/pgp-signature
    Size: 198 bytes
    Desc: This is a digitally signed message part
    Url : http://lists.scsys.co.uk/pipermail/catalyst/attachments/20101011/de007d96/attachment.pgp
  • Anthony Gladdish at Oct 11, 2010 at 2:50 pm

    -----Original Message-----
    From: Denny
    Sent: 11 October 2010 15:22
    To: The elegant MVC web framework
    Subject: Re: [Catalyst] Displaying template files without adding new controller
    actions
    On Mon, 2010-10-11 at 15:02 +0100, Anthony Gladdish wrote:
    I'd like to add various web pages to my Catalyst app without the need
    to modify controllers and restarting the server.
    Instead, I just want to add a Template::Toolkit .tt2 file on the file
    system and it get picked up automatically.
    That said, would you mind telling us a bit more about what you're
    actually trying to achieve in your application? There may be a better
    or more standard way of doing it.
    I want to add quite a few .tt2 pages to the app, in various directories.
    I don't want to have to create a Controller action per added template page ( this is the only way I know of adding a web page to a Catalyst app ).
    Every time I add a new page I'll have to add a new action to represent that page then restart the server. There must be a way to add as many template pages as required, and have a single Controller action display the web page if it's corresponding template exists, otherwise 404.

    /app/example/one
    /app/example/two
    /app/example/three/a
    /app/example/three/b

    ... each of these urls will map to a respective .tt2 template which the app will just forward to if it exists.

    Suppose I had a 100 different ( fairly static content ) web pages - I really don't want to have to create an action for each.

    Hope this helps.

    Anthony
  • Denny at Oct 11, 2010 at 3:04 pm

    On Mon, 2010-10-11 at 15:50 +0100, Anthony Gladdish wrote:
    Suppose I had a 100 different ( fairly static content ) web pages - I
    really don't want to have to create an action for each.
    Depending on what you're doing, you may possibly want to take a look at
    ShinyCMS: http://shinycms.org (specifically, the 'CMS Pages' features
    and/or the Pages controller)

    I can't claim it's particularly brilliant code, but it's there and
    you're welcome to steal bits :) (or just use it, if it does roughly
    what you need)

    Regards,
    Denny

    -------------- next part --------------
    A non-text attachment was scrubbed...
    Name: not available
    Type: application/pgp-signature
    Size: 198 bytes
    Desc: This is a digitally signed message part
    Url : http://lists.scsys.co.uk/pipermail/catalyst/attachments/20101011/9d35caf8/attachment.pgp
  • Ben van Staveren at Oct 11, 2010 at 3:14 pm
    Hi Anthony,

    If you set up your webserver to not send any URL starting with '/static'
    to the Catalyst app, it's easy enough to just have static pages. Since
    you already know what data you are going to put in there, you can easily
    enough build an off-line script that runs as a cronjob and rebuilds the
    pages once every so often; or just add a function to your app that will
    rebuild things every now and then.

    The other way to do it (and this is hackish), would be something like this:

    sub default :Path {
    my $self = shift;
    my $c = shift;
    my $req_uri = $c->res->path;
    $req_uri =~ s/\/$//;
    # assume that you want the path bit + .tt2 on the end
    my $template = $req_uri . ".tt2";

    if(-e $c->path_to('root','templates',$template)) {
    $c->stash->{template} = $template;
    } else {
    # the template doesn't exist
    $c->stash->{template} = '404.tt2';
    }
    }

    This is, however, very non-optimal since you are hitting the filesystem
    for every request that wasn't satisfied by an existing action. Like I
    said, you can either let the webserver serve up static pages. If you are
    worried about how the URL looks in the browser, some mod_rewrite magic
    will fix that for you, but that's a subject for another list :)

    YMMV, #include <std_disclaimer,h>, $self->keep_both_pieces if($broken),
    etc. etc. caveat emptor :)



    Anthony Gladdish wrote:
    -----Original Message-----
    From: Denny
    Sent: 11 October 2010 15:22
    To: The elegant MVC web framework
    Subject: Re: [Catalyst] Displaying template files without adding new controller
    actions
    On Mon, 2010-10-11 at 15:02 +0100, Anthony Gladdish wrote:

    I'd like to add various web pages to my Catalyst app without the need
    to modify controllers and restarting the server.
    Instead, I just want to add a Template::Toolkit .tt2 file on the file
    system and it get picked up automatically.
    That said, would you mind telling us a bit more about what you're
    actually trying to achieve in your application? There may be a better
    or more standard way of doing it.
    I want to add quite a few .tt2 pages to the app, in various directories.
    I don't want to have to create a Controller action per added template page ( this is the only way I know of adding a web page to a Catalyst app ).
    Every time I add a new page I'll have to add a new action to represent that page then restart the server. There must be a way to add as many template pages as required, and have a single Controller action display the web page if it's corresponding template exists, otherwise 404.

    /app/example/one
    /app/example/two
    /app/example/three/a
    /app/example/three/b

    ... each of these urls will map to a respective .tt2 template which the app will just forward to if it exists.

    Suppose I had a 100 different ( fairly static content ) web pages - I really don't want to have to create an action for each.

    Hope this helps.

    Anthony

    ------------------------------------------------------------------------

    _______________________________________________
    List: Catalyst@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/
    --
    Ben van Staveren
    phone: +62 81 70777529
    email: benvanstaveren@gmail.com
  • Stuart Watt at Oct 11, 2010 at 6:34 pm
    If it's a TT file you need (i.e., not static), along with appropriate processing, you can make a variation on Ben's suggestion by using the $c->request->arguments, and putting the file name into $c->stash->{template} before handing off to the TT view, which is likely to be the default. This is a slight variation on ben's suggestion, which will only hit the file system when looking at the right part of the URI space.

    I've not tested this, but it'd just look something like:

    sub dynamic : Local {
    my ($self, $c) = @_;
    my $args = $c->request->arguments();
    $c->stash->{template} = join('/', @$args);
    };

    This omits the error handling (assumes TT will take care of that) but should only handle requests that begin /dynamic. The arguments() method returns additional stuff after "/dynamic" in the requesting URL.

    I do something similar in my code (it's not precisely the same, as I retrieve the file contents through a model) and it works pretty well for us.

    For security, you probably want to remove stuff like "..", just to be safe.

    All the best
    Stuart

    On 2010-10-11, at 11:14 AM, Ben van Staveren wrote:

    The other way to do it (and this is hackish), would be something like this:

    ...
    This is, however, very non-optimal since you are hitting the filesystem for every request that wasn't satisfied by an existing action. Like I said, you can either let the webserver serve up static pages. If you are worried about how the URL looks in the browser, some mod_rewrite magic will fix that for you, but that's a subject for another list :)

    ...

    Anthony Gladdish wrote:
    I want to add quite a few .tt2 pages to the app, in various directories.
    I don't want to have to create a Controller action per added template page ( this is the only way I know of adding a web page to a Catalyst app ).
    Every time I add a new page I'll have to add a new action to represent that page then restart the server. There must be a way to add as many template pages as required, and have a single Controller action display the web page if it's corresponding template exists, otherwise 404.

    ...
    --
    Ben van Staveren
    phone: +62 81 70777529
    email: benvanstaveren@gmail.com
    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: http://lists.scsys.co.uk/pipermail/catalyst/attachments/20101011/fcc75af6/attachment.htm
  • Anthony Gladdish at Oct 12, 2010 at 3:47 pm
    Thanks for your feedback Denny, Ben and Stuart - good food for thought!

    I think some sort of handling logic in Root's default action to test for the existence of template and error or 404 if it doesn't - is the way forward.

    Many thanks,
    Anthony


    From: Stuart Watt
    Sent: 11 October 2010 19:35
    To: The elegant MVC web framework
    Subject: Re: [Catalyst] Displaying template files without adding new controller actions

    If it's a TT file you need (i.e., not static), along with appropriate processing, you can make a variation on Ben's suggestion by using the $c->request->arguments, and putting the file name into $c->stash->{template} before handing off to the TT view, which is likely to be the default. This is a slight variation on ben's suggestion, which will only hit the file system when looking at the right part of the URI space.

    I've not tested this, but it'd just look something like:

    sub dynamic : Local {
    my ($self, $c) = @_;
    my $args = $c->request->arguments();
    $c->stash->{template} = join('/', @$args);
    };

    This omits the error handling (assumes TT will take care of that) but should only handle requests that begin /dynamic. The arguments() method returns additional stuff after "/dynamic" in the requesting URL.

    I do something similar in my code (it's not precisely the same, as I retrieve the file contents through a model) and it works pretty well for us.

    For security, you probably want to remove stuff like "..", just to be safe.

    All the best
    Stuart


    On 2010-10-11, at 11:14 AM, Ben van Staveren wrote:


    The other way to do it (and this is hackish), would be something like this:

    ...


    This is, however, very non-optimal since you are hitting the filesystem for every request that wasn't satisfied by an existing action. Like I said, you can either let the webserver serve up static pages. If you are worried about how the URL looks in the browser, some mod_rewrite magic will fix that for you, but that's a subject for another list :)

    ...

    Anthony Gladdish wrote:


    I want to add quite a few .tt2 pages to the app, in various directories.
    I don't want to have to create a Controller action per added template page ( this is the only way I know of adding a web page to a Catalyst app ).
    Every time I add a new page I'll have to add a new action to represent that page then restart the server. There must be a way to add as many template pages as required, and have a single Controller action display the web page if it's corresponding template exists, otherwise 404.

    ...

    --
    Ben van Staveren
    phone: +62 81 70777529
    email: benvanstaveren@gmail.com

    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: http://lists.scsys.co.uk/pipermail/catalyst/attachments/20101012/a707f23e/attachment.htm
  • Fernan Aguero at Oct 12, 2010 at 4:27 pm

    On Tue, Oct 12, 2010 at 12:47 PM, Anthony Gladdish wrote:
    Thanks for your feedback Denny, Ben and Stuart ? good food for thought!

    I think some sort of handling logic in Root?s default action to test for the
    existence of template and error or 404 if it doesn?t ? is the way forward.

    Many thanks,

    Anthony
    Indeed. We had the same itch, and in our app, what we did is the following:

    i) uniquely name all templates that need some processing by the
    templating engine (e.g. to apply headers or footers) but otherwise no
    processing by a controller. In our case all templates are named as
    *.tts files.

    Then in the Root.pm controller we have something like:
    sub default : Private {
    my ( $self, $c ) = @_;

    my $path = $c->request->path;
    my $root = $c->config->{root};

    if ( -e "$root/src/$path.tts" ) {
    $c->stash->{template} = "$path.tts";
    ...
    ...


    HTH,

    --
    fernan
  • Fernan Aguero at Oct 12, 2010 at 4:29 pm

    On Tue, Oct 12, 2010 at 1:27 PM, Fernan Aguero wrote:
    On Tue, Oct 12, 2010 at 12:47 PM, Anthony Gladdish
    wrote:
    Thanks for your feedback Denny, Ben and Stuart ? good food for thought!

    I think some sort of handling logic in Root?s default action to test for the
    existence of template and error or 404 if it doesn?t ? is the way forward.

    Many thanks,

    Anthony
    Indeed. We had the same itch, and in our app, what we did is the following:

    i) uniquely name all templates that need some processing by the
    templating engine (e.g. to apply headers or footers) but otherwise no
    processing by a controller. In our case all templates are named as
    *.tts files.
    Errate: of course I meant 'all these templates' ... the rest of the
    templates (those referred to by controllers) are of course named '.tt'
    or '.tt2'

    Cheers,
    Then in the Root.pm controller we have something like:
    sub default : Private {
    ? my ( $self, $c ) = @_;

    ? my $path = $c->request->path;
    ? my $root = $c->config->{root};

    ? if ( -e "$root/src/$path.tts" ) {
    ? ? $c->stash->{template} = "$path.tts";
    ? ?...
    ? ...

    --
    fernan

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupcatalyst @
categoriescatalyst, perl
postedOct 11, '10 at 2:02p
activeOct 12, '10 at 4:29p
posts9
users5
websitecatalystframework.org
irc#catalyst

People

Translate

site design / logo © 2022 Grokbase