FAQ
I've created a view that's intended to write a couple of files to the file
system.

The output filename needs to be dynamically set. I'm having a bit of a go
figuring out how to do that.

The TT configuration documentation speaks of an output subroutine:

OUTPUT => \&output,

Later on in the view base class...

sub output {
my $filename = shift;
# do stuff
}

Here's my question:
How do I get the $filename into sub output when I forward to the view?


Here is my view class configuration:

package hde::View::TTprint;

use strict;
use base 'Catalyst::View::TT';

__PACKAGE__->config({
TEMPLATE_EXTENSION => '.tt2',
INCLUDE_PATH => [
hde->path_to( 'root', 'src' ),
hde->path_to( 'root', 'lib' ),
hde->path_to( 'root', 'tt2' )
],
PRE_PROCESS => 'config/main',
WRAPPER => 'site/wrapper',
OUTPUT => \&output,
OUTPUT_PATH => [
hde->path_to( 'root', 'static', 'published' ),
],
ERROR => 'error.tt2',
TIMER => 0
});

/dennis
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.scsys.co.uk/pipermail/catalyst/attachments/20090505/bda90230/attachment.htm

Search Discussions

  • Andrew Rodland at May 5, 2009 at 5:59 pm

    On Tuesday 05 May 2009 09:54:17 am Dennis Daupert wrote:
    I've created a view that's intended to write a couple of files to the file
    system.

    The output filename needs to be dynamically set. I'm having a bit of a go
    figuring out how to do that.

    The TT configuration documentation speaks of an output subroutine:

    OUTPUT => \&output,

    Later on in the view base class...

    sub output {
    my $filename = shift;
    # do stuff
    }

    Here's my question:
    How do I get the $filename into sub output when I forward to the view?
    This is kind of lazy lousy code because I hate trying to squeeze real code
    into an email. Hopefully it demonstrates the technique. :)


    package MyApp::View::TTtoFile;
    use strict;
    use base 'Catalyst::View::TT';

    my $outfile;

    sub output {
    # do stuff to $outfile
    }

    sub process {
    my $self = shift;
    (undef, $outfile) = @_; # Ignoring $c
    return $self->next::method(@_);
    }

    __PACKAGE__->config( ... etc. etc. ...);


    And then in your app you can just

    $c->forward('View::TTtoFile', '/var/ham/sandwich.txt');

    Andrew
  • Dennis Daupert at May 5, 2009 at 7:19 pm

    On Tue, May 5, 2009 at 1:59 PM, Andrew Rodland wrote:
    some code

    Andrew
    Hi Andrew,

    I just got your post, plugged it in, got an error. I'll need to play with
    this a bit, but have an appointment, so will try later.

    I really appreciate the info.

    /dennis
    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: http://lists.scsys.co.uk/pipermail/catalyst/attachments/20090505/08938904/attachment.htm
  • Tomas Doran at May 5, 2009 at 11:24 pm

    On 5 May 2009, at 20:19, Dennis Daupert wrote:
    I just got your post, plugged it in, got an error. I'll need to
    play with this a bit,
    Sorry for pointing out the obvious, but this is just perl:

    my $output = delete $c->res->{body};
    opem(FH, ">file") or die;
    print FH $output;
    close(FH);

    will do what you want...

    You obviously need to do something to fill the body before and after
    the snippet shown, but ;_)

    Cheers
    t0m
  • Dennis Daupert at May 6, 2009 at 2:01 pm

    On Tue, May 5, 2009 at 7:24 PM, Tomas Doran wrote:
    Sorry for pointing out the obvious, but this is just perl:

    my $output = delete $c->res->{body};
    opem(FH, ">file") or die;
    print FH $output;
    close(FH);

    will do what you want...

    Hi Tom,

    Thanks for your reply.

    There are some things that aren't so obvious to me. Where would I place the
    code represented in your snippet? I can't just hang it out in the main body
    of package hde::View::TTprint, since $c isn't available there. $c and
    $outfile *are* available in sub process, once the format for the forward
    statement is corrrect. So I *could* go ahead and perform the write-to-file
    operation there, but that seems a bit muddled. It seems to me the clearest
    place to write-to-file would be in sub output, but nothing seems to be
    showing up there.

    Even so, I did try writing from sub process, and it gave me an error, which
    leads me to Question 2.
    I'm trying to follow Template Toolkit's documented API, which offers these
    configuration options, which I've used in my TTprint base class:

    OUTPUT => \&output,
    OUTPUT_PATH => [
    hde->path_to( 'root', 'static', 'published' ),
    ],

    Supposedly, the processed template output will be written to the output file
    relative to OUTPUT_PATH. But I get the error:

    Caught exception in hde::View::TTprint->process "Cannot open
    Test1.0.0/TOC.html for writing: No such file or directory"


    BTW, this path already exists:
    ~/cat_work/hde/root/static/published/Test1.0.0

    Please feel free to point out any obvious bit I've botched.

    /dennis

    Code summary:

    In controller:
    my $path_and_file = "Test1.0.0 /TOC.html";
    $c->forward( $c->view('TTprint'), [ qq/$path_and_file/ ] );

    In package hde::View::TTprint;
    __PACKAGE__->config({
    TEMPLATE_EXTENSION => '.tt2',
    INCLUDE_PATH => [
    hde->path_to( 'root', 'src' ),
    hde->path_to( 'root', 'lib' ),
    hde->path_to( 'root', 'tt2' )
    ],
    PRE_PROCESS => 'config/main',
    WRAPPER => 'site/wrapper',
    OUTPUT => \&output,
    OUTPUT_PATH => [
    hde->path_to( 'root', 'static', 'published' ),
    ],
    ERROR => 'error.tt2',
    TIMER => 0
    });

    my $outfile;

    sub output {
    my $output = shift;
    # Nothing shows up here
    }

    sub process {
    my $self = shift;
    my ($c, $outfile) = @_; # Not ignoring $c, so I can get debug stuff
    # and delete body

    # $outfile = 'Test1.0.0 /TOC.html';

    $c->log->debug("In sub process"); # does print
    $c->log->debug("outfile: $outfile");

    my $output = delete $c->res->{body};
    open my $write_fh, '>', $outfile
    or die "Cannot open $outfile for writing: $!\n";
    print $write_fh $output;
    close $write_fh or warn "Cannot close $outfile: $!\n";

    return $self->next::method(@_);
    }
    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: http://lists.scsys.co.uk/pipermail/catalyst/attachments/20090506/65952a4e/attachment.htm
  • Andrew Rodland at May 6, 2009 at 9:28 pm

    On Wednesday 06 May 2009 09:01:43 am Dennis Daupert wrote:
    On Tue, May 5, 2009 at 7:24 PM, Tomas Doran wrote:
    my $output = delete $c->res->{body};
    opem(FH, ">file") or die;
    print FH $output;
    close(FH);

    will do what you want...
    There are some things that aren't so obvious to me. Where would I place the
    code represented in your snippet? I can't just hang it out in the main
    body of package hde::View::TTprint,
    In that example you don't *have* a View::TTprint. Or if you do, it's just
    another subclas of C::V::TT with a different config and search path. No
    overloading, no OUTPUT. You forward to the view, it writes into $c->res->body
    like it always does. You take the data out of $c->res->body and write it to a
    file, then null out $c->res->body so that RenderView will fill it in later
    using your default_view.

    Andrew
  • Dennis Daupert at May 6, 2009 at 10:11 pm

    On Wed, May 6, 2009 at 5:28 PM, Andrew Rodland wrote:
    In that example you don't *have* a View::TTprint. Or if you do, it's just
    another subclas of C::V::TT with a different config and search path. No
    overloading, no OUTPUT. You forward to the view, it writes into
    $c->res->body
    like it always does. You take the data out of $c->res->body and write it to
    a
    file, then null out $c->res->body so that RenderView will fill it in later
    using your default_view.

    Andrew
    Thanks, Andrew, your explanation does help a great deal. The template output
    gets written out nicely, now. I feel I do want to use a separate view,
    because the files I'm writing out need to have their own templates, images,
    etc., so different search paths will help keep things neatly separated.

    /dennis
    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: http://lists.scsys.co.uk/pipermail/catalyst/attachments/20090506/5f4868bb/attachment.htm
  • Matt S Trout at May 11, 2009 at 4:58 pm

    On Tue, May 05, 2009 at 10:54:17AM -0400, Dennis Daupert wrote:
    I've created a view that's intended to write a couple of files to the file
    system.

    The output filename needs to be dynamically set. I'm having a bit of a go
    figuring out how to do that.

    The TT configuration documentation speaks of an output subroutine:

    OUTPUT => \&output,

    Later on in the view base class...

    sub output {
    my $filename = shift;
    # do stuff
    }

    Here's my question:
    How do I get the $filename into sub output when I forward to the view?
    Screw that.

    sub write_file {
    my ($self, $c, $filename) = @_;
    my $data = $self->render($c, ...); # look at how process calls render
    <write data>
    }

    then do:

    $c->view('Foo')->write_file($c, $filename);

    Having to pass $c along like that is a little bit annoying, but this approach
    is -way- simpler.

    Of course if you were feeling truly insane you could do

    $self->template->{OUTPUT} = sub { <capture $filename here> };
    $self->render(...);

    but I don't really see that it would gain you anything.

    *wonders if write_file should be a role that applies to any view that supplies
    render* ...

    --
    Matt S Trout Catalyst and DBIx::Class consultancy with a clue
    Technical Director and a commit bit: http://shadowcat.co.uk/catalyst/
    Shadowcat Systems Limited
    mst (@) shadowcat.co.uk http://shadowcat.co.uk/blog/matt-s-trout/

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupcatalyst @
categoriescatalyst, perl
postedMay 5, '09 at 2:54p
activeMay 11, '09 at 4:58p
posts8
users4
websitecatalystframework.org
irc#catalyst

People

Translate

site design / logo © 2022 Grokbase